summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'gnu')
-rw-r--r--gnu/games/Makefile2
-rw-r--r--gnu/games/Makefile.inc2
-rw-r--r--gnu/games/chess/Xchess/Makefile4
-rw-r--r--gnu/games/chess/Xchess/XCircle.c4
-rw-r--r--gnu/games/chess/Xchess/board.c4
-rw-r--r--gnu/games/chess/Xchess/button.c4
-rw-r--r--gnu/games/chess/Xchess/clock.c4
-rw-r--r--gnu/games/chess/Xchess/control.c4
-rw-r--r--gnu/games/chess/Xchess/jail.c4
-rw-r--r--gnu/games/chess/Xchess/message.c4
-rw-r--r--gnu/games/chess/Xchess/parse.c4
-rw-r--r--gnu/games/chess/Xchess/popup.c4
-rw-r--r--gnu/games/chess/Xchess/program.c4
-rw-r--r--gnu/games/chess/Xchess/record.c4
-rw-r--r--gnu/games/chess/Xchess/std.c4
-rw-r--r--gnu/games/chess/Xchess/std.h4
-rw-r--r--gnu/games/chess/Xchess/valid.c4
-rw-r--r--gnu/games/chess/Xchess/window.c4
-rw-r--r--gnu/games/chess/Xchess/window.c.bm4
-rw-r--r--gnu/games/chess/Xchess/xchess.c4
-rw-r--r--gnu/games/chess/Xchess/xchess.c.1504
-rw-r--r--gnu/games/chess/Xchess/xchess.h4
-rwxr-xr-xgnu/gnu2bmake/gcc-2.6.1.tcl4
-rw-r--r--gnu/gnu2bmake/gnu2bmake.tcl2
-rw-r--r--gnu/include/Makefile2
-rw-r--r--gnu/lib/Makefile2
-rw-r--r--gnu/lib/Makefile.inc2
-rw-r--r--gnu/lib/libdialog/Makefile2
-rw-r--r--gnu/lib/libmalloc/Makefile2
-rw-r--r--gnu/lib/libreadline/Makefile2
-rw-r--r--gnu/lib/libreadline/VERSION1
-rw-r--r--gnu/lib/libregex/Makefile2
-rw-r--r--gnu/lib/libregex/doc/texinfo.tex3941
-rw-r--r--gnu/libexec/Makefile2
-rw-r--r--gnu/libexec/Makefile.inc2
-rw-r--r--gnu/libexec/uucp/Makefile2
-rw-r--r--gnu/libexec/uucp/common_sources/chat.c2
-rw-r--r--gnu/libexec/uucp/common_sources/conn.c2
-rw-r--r--gnu/libexec/uucp/common_sources/copy.c2
-rw-r--r--gnu/libexec/uucp/common_sources/log.c2
-rw-r--r--gnu/libexec/uucp/common_sources/prot.c2
-rw-r--r--gnu/libexec/uucp/common_sources/tcp.c2
-rw-r--r--gnu/libexec/uucp/common_sources/tli.c2
-rw-r--r--gnu/libexec/uucp/common_sources/util.c2
-rw-r--r--gnu/libexec/uucp/contrib/Makefile.uurt2
-rw-r--r--gnu/libexec/uucp/contrib/uupoll.shar21
-rw-r--r--gnu/libexec/uucp/contrib/uurate.c7
-rw-r--r--gnu/libexec/uucp/contrib/uurate.man2
-rw-r--r--gnu/libexec/uucp/contrib/uusnap.c2
-rw-r--r--gnu/libexec/uucp/cu/Makefile2
-rw-r--r--gnu/libexec/uucp/cu/cu.12
-rw-r--r--gnu/libexec/uucp/cu/cu.c2
-rw-r--r--gnu/libexec/uucp/libunix/Makefile2
-rw-r--r--gnu/libexec/uucp/libunix/cusub.c2
-rw-r--r--gnu/libexec/uucp/libunix/lock.c2
-rw-r--r--gnu/libexec/uucp/libunix/picksb.c2
-rw-r--r--gnu/libexec/uucp/libunix/pipe.c2
-rw-r--r--gnu/libexec/uucp/libunix/serial.c2
-rw-r--r--gnu/libexec/uucp/libunix/spool.c2
-rw-r--r--gnu/libexec/uucp/libunix/statsb.c2
-rw-r--r--gnu/libexec/uucp/libunix/work.c2
-rw-r--r--gnu/libexec/uucp/libunix/xqtfil.c2
-rw-r--r--gnu/libexec/uucp/libunix/xqtsub.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/Makefile2
-rw-r--r--gnu/libexec/uucp/libuuconf/addblk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/addstr.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/allblk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/alloc.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/base.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/bool.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/callin.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/calout.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/chatc.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/cmdarg.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/cmdfil.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/cmdlin.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/debfil.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/deblev.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/diacod.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/dial.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/diasub.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/dnams.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/errno.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/errstr.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/filnam.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/freblk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/fredia.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/free.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/freprt.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/fresys.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/grdcmp.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hdial.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hdnams.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hinit.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hlocnm.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hport.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hrmunk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hsinfo.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hsnams.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hsys.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/hunk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/iniglb.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/init.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/int.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/lckdir.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/lineno.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/llocnm.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/local.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/locnm.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/logfil.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/maxuxq.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/mrgblk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/paramc.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/port.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/prtsub.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/pubdir.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/rdlocs.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/rdperm.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/reliab.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/remunk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/runuxq.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/sinfo.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/snams.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/split.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/spool.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/stafil.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/syssub.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tcalou.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tdial.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tdialc.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tdnams.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tgcmp.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/thread.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/time.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tinit.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tlocnm.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tport.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tportc.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tsinfo.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tsnams.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tsys.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/tval.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/ugtlin.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/unk.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/val.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/vinit.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/vport.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/vsinfo.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/vsnams.c2
-rw-r--r--gnu/libexec/uucp/libuuconf/vsys.c2
-rw-r--r--gnu/libexec/uucp/libuucp/Makefile2
-rw-r--r--gnu/libexec/uucp/libuucp/parse.c2
-rw-r--r--gnu/libexec/uucp/sample/Makefile2
-rw-r--r--gnu/libexec/uucp/tstuu.c2
-rw-r--r--gnu/libexec/uucp/uuchk/Makefile2
-rw-r--r--gnu/libexec/uucp/uuchk/uuchk.c2
-rw-r--r--gnu/libexec/uucp/uucico/Makefile2
-rw-r--r--gnu/libexec/uucp/uucico/prote.c2
-rw-r--r--gnu/libexec/uucp/uucico/protf.c2
-rw-r--r--gnu/libexec/uucp/uucico/protg.c2
-rw-r--r--gnu/libexec/uucp/uucico/proti.c2
-rw-r--r--gnu/libexec/uucp/uucico/protj.c2
-rw-r--r--gnu/libexec/uucp/uucico/prott.c2
-rw-r--r--gnu/libexec/uucp/uucico/protz.c2
-rw-r--r--gnu/libexec/uucp/uucico/rec.c2
-rw-r--r--gnu/libexec/uucp/uucico/send.c2
-rw-r--r--gnu/libexec/uucp/uucico/time.c2
-rw-r--r--gnu/libexec/uucp/uucico/trans.c2
-rw-r--r--gnu/libexec/uucp/uucico/uucico.82
-rw-r--r--gnu/libexec/uucp/uucico/uucico.c2
-rw-r--r--gnu/libexec/uucp/uucico/xcmd.c2
-rw-r--r--gnu/libexec/uucp/uuconv/Makefile2
-rw-r--r--gnu/libexec/uucp/uuconv/uuconv.c2
-rw-r--r--gnu/libexec/uucp/uucp/Makefile2
-rw-r--r--gnu/libexec/uucp/uucp/uucp.12
-rw-r--r--gnu/libexec/uucp/uucp/uucp.c2
-rw-r--r--gnu/libexec/uucp/uulog/Makefile2
-rw-r--r--gnu/libexec/uucp/uulog/uulog.c2
-rw-r--r--gnu/libexec/uucp/uuname/Makefile2
-rw-r--r--gnu/libexec/uucp/uuname/uuname.c2
-rw-r--r--gnu/libexec/uucp/uupick/Makefile2
-rw-r--r--gnu/libexec/uucp/uupick/uupick.c2
-rw-r--r--gnu/libexec/uucp/uusched/Makefile2
-rw-r--r--gnu/libexec/uucp/uustat/Makefile2
-rw-r--r--gnu/libexec/uucp/uustat/uustat.12
-rw-r--r--gnu/libexec/uucp/uustat/uustat.c2
-rw-r--r--gnu/libexec/uucp/uuto/Makefile2
-rw-r--r--gnu/libexec/uucp/uux/Makefile2
-rw-r--r--gnu/libexec/uucp/uux/uux.12
-rw-r--r--gnu/libexec/uucp/uux/uux.c2
-rw-r--r--gnu/libexec/uucp/uuxqt/Makefile2
-rw-r--r--gnu/libexec/uucp/uuxqt/uuxqt.82
-rw-r--r--gnu/libexec/uucp/uuxqt/uuxqt.c2
-rw-r--r--gnu/usr.bin/Makefile2
-rw-r--r--gnu/usr.bin/Makefile.inc2
-rw-r--r--gnu/usr.bin/as/Makefile2
-rw-r--r--gnu/usr.bin/as/app.c2
-rw-r--r--gnu/usr.bin/as/as.c2
-rw-r--r--gnu/usr.bin/as/as.h2
-rw-r--r--gnu/usr.bin/as/atof-generic.c2
-rw-r--r--gnu/usr.bin/as/bignum-copy.c2
-rw-r--r--gnu/usr.bin/as/bignum.h2
-rw-r--r--gnu/usr.bin/as/bit_fix.h2
-rw-r--r--gnu/usr.bin/as/cond.c2
-rw-r--r--gnu/usr.bin/as/config/Makefile.hp3002
-rw-r--r--gnu/usr.bin/as/config/Makefile.i3862
-rw-r--r--gnu/usr.bin/as/config/Makefile.pc5322
-rw-r--r--gnu/usr.bin/as/config/Makefile.sparc2
-rw-r--r--gnu/usr.bin/as/config/Makefile.vax2
-rw-r--r--gnu/usr.bin/as/config/atof-ieee.c2
-rw-r--r--gnu/usr.bin/as/config/ho-i386.h2
-rw-r--r--gnu/usr.bin/as/config/obj-aout.h2
-rw-r--r--gnu/usr.bin/as/config/tc-i386.c2
-rw-r--r--gnu/usr.bin/as/config/tc-i386.h2
-rw-r--r--gnu/usr.bin/as/config/tc-sparc.c2
-rw-r--r--gnu/usr.bin/as/config/tc-sparc.h2
-rw-r--r--gnu/usr.bin/as/config/te-generic.h2
-rw-r--r--gnu/usr.bin/as/debug.c2
-rw-r--r--gnu/usr.bin/as/doc/all.m42
-rw-r--r--gnu/usr.bin/as/doc/as.texinfo4
-rw-r--r--gnu/usr.bin/as/doc/gen.m42
-rw-r--r--gnu/usr.bin/as/doc/none.m42
-rw-r--r--gnu/usr.bin/as/doc/pretex.m42
-rw-r--r--gnu/usr.bin/as/doc/vintage.m42
-rw-r--r--gnu/usr.bin/as/expr.c2
-rw-r--r--gnu/usr.bin/as/expr.h2
-rw-r--r--gnu/usr.bin/as/flo-const.c2
-rw-r--r--gnu/usr.bin/as/flo-copy.c2
-rw-r--r--gnu/usr.bin/as/flonum-mult.c2
-rw-r--r--gnu/usr.bin/as/flonum.h2
-rw-r--r--gnu/usr.bin/as/frags.c2
-rw-r--r--gnu/usr.bin/as/frags.h2
-rw-r--r--gnu/usr.bin/as/hash.c2
-rw-r--r--gnu/usr.bin/as/hash.h2
-rw-r--r--gnu/usr.bin/as/hex-value.c2
-rw-r--r--gnu/usr.bin/as/input-file.c2
-rw-r--r--gnu/usr.bin/as/input-file.h2
-rw-r--r--gnu/usr.bin/as/input-scrub.c2
-rw-r--r--gnu/usr.bin/as/listing.c2
-rw-r--r--gnu/usr.bin/as/listing.h2
-rw-r--r--gnu/usr.bin/as/makefile.dos2
-rw-r--r--gnu/usr.bin/as/messages.c2
-rw-r--r--gnu/usr.bin/as/obj.h2
-rw-r--r--gnu/usr.bin/as/obstack.c2
-rw-r--r--gnu/usr.bin/as/obstack.h2
-rw-r--r--gnu/usr.bin/as/opcode/a29k.h5
-rw-r--r--gnu/usr.bin/as/opcode/i386.h2
-rw-r--r--gnu/usr.bin/as/opcode/i960.h2
-rw-r--r--gnu/usr.bin/as/opcode/sparc.h2
-rw-r--r--gnu/usr.bin/as/output-file.c2
-rw-r--r--gnu/usr.bin/as/output-file.h2
-rw-r--r--gnu/usr.bin/as/read.c2
-rw-r--r--gnu/usr.bin/as/read.h2
-rw-r--r--gnu/usr.bin/as/struc-symbol.h2
-rw-r--r--gnu/usr.bin/as/subsegs.c2
-rw-r--r--gnu/usr.bin/as/subsegs.h2
-rw-r--r--gnu/usr.bin/as/symbols.c2
-rw-r--r--gnu/usr.bin/as/symbols.h2
-rw-r--r--gnu/usr.bin/as/tc.h2
-rwxr-xr-xgnu/usr.bin/as/testscripts/doboth2
-rwxr-xr-xgnu/usr.bin/as/testscripts/doobjcmp2
-rwxr-xr-xgnu/usr.bin/as/testscripts/dostriptest2
-rwxr-xr-xgnu/usr.bin/as/testscripts/dotest2
-rwxr-xr-xgnu/usr.bin/as/testscripts/dounsortreloc2
-rwxr-xr-xgnu/usr.bin/as/testscripts/dounsortsymbols2
-rw-r--r--gnu/usr.bin/as/version.c4
-rw-r--r--gnu/usr.bin/as/write.c2
-rw-r--r--gnu/usr.bin/as/xmalloc.c2
-rw-r--r--gnu/usr.bin/as/xrealloc.c2
-rw-r--r--gnu/usr.bin/bc/scan.c2
-rw-r--r--gnu/usr.bin/cc/Makefile2
-rw-r--r--gnu/usr.bin/cc/Makefile.inc2
-rw-r--r--gnu/usr.bin/cc/README2
-rw-r--r--gnu/usr.bin/cc/c++/Makefile2
-rw-r--r--gnu/usr.bin/cc/cc/Makefile2
-rw-r--r--gnu/usr.bin/cc/cc/cc.12
-rw-r--r--gnu/usr.bin/cc/cc1/Makefile2
-rw-r--r--gnu/usr.bin/cc/cc1plus/Makefile2
-rw-r--r--gnu/usr.bin/cc/cc_int/Makefile2
-rw-r--r--gnu/usr.bin/cc/cpp/Makefile2
-rw-r--r--gnu/usr.bin/cc/f77/Makefile2
-rw-r--r--gnu/usr.bin/cc/libgcc/Makefile2
-rw-r--r--gnu/usr.bin/cvs/contrib/pcl-cvs/texinfo.tex3230
-rw-r--r--gnu/usr.bin/cvs/cvsinit/Makefile2
-rw-r--r--gnu/usr.bin/dc/texinfo.tex4003
-rw-r--r--gnu/usr.bin/dialog/Makefile2
-rw-r--r--gnu/usr.bin/gdb/doc/gdbint.texinfo4
-rw-r--r--gnu/usr.bin/gdb/doc/refcard.tex2
-rw-r--r--gnu/usr.bin/gdb/doc/stabs.texinfo2
-rw-r--r--gnu/usr.bin/gdb/gdb/gdb.12
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmalloc.texi2
-rw-r--r--gnu/usr.bin/groff/BUG-REPORT57
-rw-r--r--gnu/usr.bin/groff/COPYING339
-rw-r--r--gnu/usr.bin/groff/ChangeLog4958
-rw-r--r--gnu/usr.bin/groff/Makefile12
-rw-r--r--gnu/usr.bin/groff/Makefile.cfg42
-rw-r--r--gnu/usr.bin/groff/NEWS662
-rw-r--r--gnu/usr.bin/groff/PROBLEMS458
-rw-r--r--gnu/usr.bin/groff/PROJECTS19
-rw-r--r--gnu/usr.bin/groff/README.gnu38
-rw-r--r--gnu/usr.bin/groff/TODO24
-rw-r--r--gnu/usr.bin/groff/VERSION1
-rw-r--r--gnu/usr.bin/groff/addftinfo/Makefile12
-rw-r--r--gnu/usr.bin/groff/addftinfo/addftinfo.185
-rw-r--r--gnu/usr.bin/groff/addftinfo/addftinfo.cc194
-rw-r--r--gnu/usr.bin/groff/addftinfo/guess.cc490
-rw-r--r--gnu/usr.bin/groff/addftinfo/guess.h44
-rw-r--r--gnu/usr.bin/groff/afmtodit/Makefile9
-rw-r--r--gnu/usr.bin/groff/afmtodit/afmtodit.1204
-rw-r--r--gnu/usr.bin/groff/afmtodit/afmtodit.pl325
-rw-r--r--gnu/usr.bin/groff/devices/Makefile10
-rw-r--r--gnu/usr.bin/groff/devices/Makefile.dev43
-rw-r--r--gnu/usr.bin/groff/devices/Makefile.tty52
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/CB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/CBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/CI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/CR306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/DESC9
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/HB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/HBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/HI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/HR306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/Makefile10
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/NB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/NBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/NI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/NR306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/S226
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/TB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/TBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/TI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100-12/TRbin0 -> 3302 bytes
-rw-r--r--gnu/usr.bin/groff/devices/devX100/CB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/CBIbin0 -> 3190 bytes
-rw-r--r--gnu/usr.bin/groff/devices/devX100/CI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/CR306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/DESC9
-rw-r--r--gnu/usr.bin/groff/devices/devX100/HB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/HBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/HI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/HR306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/Makefile10
-rw-r--r--gnu/usr.bin/groff/devices/devX100/NB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/NBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/NI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/NR306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/S226
-rw-r--r--gnu/usr.bin/groff/devices/devX100/TB306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/TBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/TI306
-rw-r--r--gnu/usr.bin/groff/devices/devX100/TR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/CB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/CBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/CI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/CR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/DESC9
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/HB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/HBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/HI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/HR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/Makefile10
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/NB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/NBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/NI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/NR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/S226
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/TB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/TBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/TI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75-12/TR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/CB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/CBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/CI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/CR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/DESC9
-rw-r--r--gnu/usr.bin/groff/devices/devX75/HB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/HBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/HI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/HR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/Makefile10
-rw-r--r--gnu/usr.bin/groff/devices/devX75/NB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/NBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/NI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/NR306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/S226
-rw-r--r--gnu/usr.bin/groff/devices/devX75/TB306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/TBI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/TI306
-rw-r--r--gnu/usr.bin/groff/devices/devX75/TR306
-rw-r--r--gnu/usr.bin/groff/devices/devascii/DESC.proto8
-rw-r--r--gnu/usr.bin/groff/devices/devascii/Makefile6
-rw-r--r--gnu/usr.bin/groff/devices/devascii/R.proto184
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/B347
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/BI352
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/CW158
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/DESC11
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/EX144
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/H302
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/HB302
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/HI303
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/I353
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/MI136
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/Makefile12
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/R430
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/S152
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/SA143
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/SB132
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/CompileFonts15
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/Makefile93
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/msam.map127
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/msbm.map121
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/texb.map127
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/texex.map100
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/texi.map127
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/texmi.map32
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/texr.map127
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/texsy.map100
-rw-r--r--gnu/usr.bin/groff/devices/devdvi/generate/textt.map126
-rw-r--r--gnu/usr.bin/groff/devices/devlatin1/DESC.proto8
-rw-r--r--gnu/usr.bin/groff/devices/devlatin1/Makefile6
-rw-r--r--gnu/usr.bin/groff/devices/devlatin1/R.proto353
-rw-r--r--gnu/usr.bin/groff/devices/devps/AB559
-rw-r--r--gnu/usr.bin/groff/devices/devps/ABI560
-rw-r--r--gnu/usr.bin/groff/devices/devps/AI559
-rw-r--r--gnu/usr.bin/groff/devices/devps/AR558
-rw-r--r--gnu/usr.bin/groff/devices/devps/BMB438
-rw-r--r--gnu/usr.bin/groff/devices/devps/BMBI441
-rw-r--r--gnu/usr.bin/groff/devices/devps/BMI434
-rw-r--r--gnu/usr.bin/groff/devices/devps/BMR430
-rw-r--r--gnu/usr.bin/groff/devices/devps/CB336
-rw-r--r--gnu/usr.bin/groff/devices/devps/CBI337
-rw-r--r--gnu/usr.bin/groff/devices/devps/CI337
-rw-r--r--gnu/usr.bin/groff/devices/devps/CR336
-rw-r--r--gnu/usr.bin/groff/devices/devps/DESC14
-rw-r--r--gnu/usr.bin/groff/devices/devps/DESC-A414
-rw-r--r--gnu/usr.bin/groff/devices/devps/DESC-letter14
-rw-r--r--gnu/usr.bin/groff/devices/devps/HB546
-rw-r--r--gnu/usr.bin/groff/devices/devps/HBI547
-rw-r--r--gnu/usr.bin/groff/devices/devps/HI617
-rw-r--r--gnu/usr.bin/groff/devices/devps/HNB546
-rw-r--r--gnu/usr.bin/groff/devices/devps/HNBI547
-rw-r--r--gnu/usr.bin/groff/devices/devps/HNI617
-rw-r--r--gnu/usr.bin/groff/devices/devps/HNR616
-rw-r--r--gnu/usr.bin/groff/devices/devps/HR616
-rw-r--r--gnu/usr.bin/groff/devices/devps/Makefile15
-rw-r--r--gnu/usr.bin/groff/devices/devps/NB446
-rw-r--r--gnu/usr.bin/groff/devices/devps/NBI447
-rw-r--r--gnu/usr.bin/groff/devices/devps/NI447
-rw-r--r--gnu/usr.bin/groff/devices/devps/NR447
-rw-r--r--gnu/usr.bin/groff/devices/devps/PB449
-rw-r--r--gnu/usr.bin/groff/devices/devps/PBI451
-rw-r--r--gnu/usr.bin/groff/devices/devps/PI453
-rw-r--r--gnu/usr.bin/groff/devices/devps/PR456
-rw-r--r--gnu/usr.bin/groff/devices/devps/S227
-rw-r--r--gnu/usr.bin/groff/devices/devps/SS194
-rw-r--r--gnu/usr.bin/groff/devices/devps/TB533
-rw-r--r--gnu/usr.bin/groff/devices/devps/TBI515
-rw-r--r--gnu/usr.bin/groff/devices/devps/TI528
-rw-r--r--gnu/usr.bin/groff/devices/devps/TR519
-rw-r--r--gnu/usr.bin/groff/devices/devps/ZCMI477
-rw-r--r--gnu/usr.bin/groff/devices/devps/ZD193
-rw-r--r--gnu/usr.bin/groff/devices/devps/ZDR193
-rw-r--r--gnu/usr.bin/groff/devices/devps/download5
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/Makefile224
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/afmname44
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/dingbatsmap2
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/dingbatsrmap1
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/lgreekmap28
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/symbol.sed33
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/symbolchars60
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/symbolsl.afm203
-rw-r--r--gnu/usr.bin/groff/devices/devps/generate/textmap449
-rw-r--r--gnu/usr.bin/groff/devices/devps/prologue152
-rw-r--r--gnu/usr.bin/groff/devices/devps/symbol.afm215
-rw-r--r--gnu/usr.bin/groff/devices/devps/symbolsl.pfa29
-rw-r--r--gnu/usr.bin/groff/devices/devps/text.enc231
-rw-r--r--gnu/usr.bin/groff/devices/devps/zapfdr.afm222
-rw-r--r--gnu/usr.bin/groff/devices/devps/zapfdr.pfa218
-rw-r--r--gnu/usr.bin/groff/doc/Makefile55
-rw-r--r--gnu/usr.bin/groff/doc/meintro.me2246
-rw-r--r--gnu/usr.bin/groff/doc/meref.me2194
-rw-r--r--gnu/usr.bin/groff/eqn/Makefile26
-rw-r--r--gnu/usr.bin/groff/eqn/TODO41
-rw-r--r--gnu/usr.bin/groff/eqn/box.cc611
-rw-r--r--gnu/usr.bin/groff/eqn/box.h277
-rw-r--r--gnu/usr.bin/groff/eqn/delim.cc380
-rw-r--r--gnu/usr.bin/groff/eqn/eqn.1862
-rw-r--r--gnu/usr.bin/groff/eqn/eqn.h51
-rw-r--r--gnu/usr.bin/groff/eqn/eqn.y331
-rw-r--r--gnu/usr.bin/groff/eqn/lex.cc1160
-rw-r--r--gnu/usr.bin/groff/eqn/limit.cc195
-rw-r--r--gnu/usr.bin/groff/eqn/list.cc236
-rw-r--r--gnu/usr.bin/groff/eqn/main.cc352
-rw-r--r--gnu/usr.bin/groff/eqn/mark.cc121
-rw-r--r--gnu/usr.bin/groff/eqn/neqn.sh5
-rw-r--r--gnu/usr.bin/groff/eqn/other.cc601
-rw-r--r--gnu/usr.bin/groff/eqn/over.cc196
-rw-r--r--gnu/usr.bin/groff/eqn/pbox.h141
-rw-r--r--gnu/usr.bin/groff/eqn/pile.cc293
-rw-r--r--gnu/usr.bin/groff/eqn/script.cc221
-rw-r--r--gnu/usr.bin/groff/eqn/special.cc115
-rw-r--r--gnu/usr.bin/groff/eqn/sqrt.cc179
-rw-r--r--gnu/usr.bin/groff/eqn/text.cc528
-rw-r--r--gnu/usr.bin/groff/grodvi/Makefile12
-rw-r--r--gnu/usr.bin/groff/grodvi/dvi.cc895
-rw-r--r--gnu/usr.bin/groff/grodvi/grodvi.1154
-rw-r--r--gnu/usr.bin/groff/groff/Makefile12
-rw-r--r--gnu/usr.bin/groff/groff/groff.1362
-rw-r--r--gnu/usr.bin/groff/groff/groff.cc590
-rw-r--r--gnu/usr.bin/groff/groff/pipeline.c239
-rw-r--r--gnu/usr.bin/groff/groff/pipeline.h30
-rw-r--r--gnu/usr.bin/groff/grog/Makefile8
-rw-r--r--gnu/usr.bin/groff/grog/grog.154
-rw-r--r--gnu/usr.bin/groff/grog/grog.pl149
-rw-r--r--gnu/usr.bin/groff/grog/grog.sh78
-rw-r--r--gnu/usr.bin/groff/grops/Makefile12
-rw-r--r--gnu/usr.bin/groff/grops/TODO25
-rw-r--r--gnu/usr.bin/groff/grops/grops.1797
-rw-r--r--gnu/usr.bin/groff/grops/ps.cc1507
-rw-r--r--gnu/usr.bin/groff/grops/ps.h122
-rw-r--r--gnu/usr.bin/groff/grops/psfig.diff106
-rw-r--r--gnu/usr.bin/groff/grops/psrm.cc1092
-rw-r--r--gnu/usr.bin/groff/grotty/Makefile12
-rw-r--r--gnu/usr.bin/groff/grotty/TODO3
-rw-r--r--gnu/usr.bin/groff/grotty/grotty.1204
-rw-r--r--gnu/usr.bin/groff/grotty/tty.cc440
-rw-r--r--gnu/usr.bin/groff/include/assert.h41
-rw-r--r--gnu/usr.bin/groff/include/cmap.h56
-rw-r--r--gnu/usr.bin/groff/include/cset.h75
-rw-r--r--gnu/usr.bin/groff/include/defs.h9
-rw-r--r--gnu/usr.bin/groff/include/device.h21
-rw-r--r--gnu/usr.bin/groff/include/driver.h36
-rw-r--r--gnu/usr.bin/groff/include/errarg.h46
-rw-r--r--gnu/usr.bin/groff/include/error.h58
-rw-r--r--gnu/usr.bin/groff/include/font.h113
-rw-r--r--gnu/usr.bin/groff/include/index.h42
-rw-r--r--gnu/usr.bin/groff/include/lib.h105
-rw-r--r--gnu/usr.bin/groff/include/macropath.h21
-rw-r--r--gnu/usr.bin/groff/include/posix.h49
-rw-r--r--gnu/usr.bin/groff/include/printer.h66
-rw-r--r--gnu/usr.bin/groff/include/ptable.h166
-rw-r--r--gnu/usr.bin/groff/include/refid.h35
-rw-r--r--gnu/usr.bin/groff/include/search.h96
-rw-r--r--gnu/usr.bin/groff/include/searchpath.h29
-rw-r--r--gnu/usr.bin/groff/include/stringclass.h174
-rw-r--r--gnu/usr.bin/groff/include/unix.h0
-rw-r--r--gnu/usr.bin/groff/indxbib/Makefile20
-rw-r--r--gnu/usr.bin/groff/indxbib/dirnamemax.c49
-rw-r--r--gnu/usr.bin/groff/indxbib/eign133
-rw-r--r--gnu/usr.bin/groff/indxbib/indxbib.1187
-rw-r--r--gnu/usr.bin/groff/indxbib/indxbib.cc742
-rw-r--r--gnu/usr.bin/groff/indxbib/signal.c63
-rw-r--r--gnu/usr.bin/groff/libbib/Makefile14
-rw-r--r--gnu/usr.bin/groff/libbib/common.cc38
-rw-r--r--gnu/usr.bin/groff/libbib/index.cc614
-rw-r--r--gnu/usr.bin/groff/libbib/linear.cc484
-rw-r--r--gnu/usr.bin/groff/libbib/map.c75
-rw-r--r--gnu/usr.bin/groff/libbib/search.cc130
-rw-r--r--gnu/usr.bin/groff/libdriver/Makefile14
-rw-r--r--gnu/usr.bin/groff/libdriver/input.cc473
-rw-r--r--gnu/usr.bin/groff/libdriver/printer.cc240
-rw-r--r--gnu/usr.bin/groff/libgroff/Makefile24
-rw-r--r--gnu/usr.bin/groff/libgroff/assert.cc39
-rw-r--r--gnu/usr.bin/groff/libgroff/change_lf.cc39
-rw-r--r--gnu/usr.bin/groff/libgroff/cmap.cc55
-rw-r--r--gnu/usr.bin/groff/libgroff/cset.cc101
-rw-r--r--gnu/usr.bin/groff/libgroff/device.cc38
-rw-r--r--gnu/usr.bin/groff/libgroff/errarg.cc120
-rw-r--r--gnu/usr.bin/groff/libgroff/error.cc139
-rw-r--r--gnu/usr.bin/groff/libgroff/fatal.cc29
-rw-r--r--gnu/usr.bin/groff/libgroff/filename.cc1
-rw-r--r--gnu/usr.bin/groff/libgroff/fmod.c28
-rw-r--r--gnu/usr.bin/groff/libgroff/font.cc911
-rw-r--r--gnu/usr.bin/groff/libgroff/fontfile.cc64
-rw-r--r--gnu/usr.bin/groff/libgroff/getcwd.c38
-rw-r--r--gnu/usr.bin/groff/libgroff/iftoa.c65
-rw-r--r--gnu/usr.bin/groff/libgroff/illegal.cc22
-rw-r--r--gnu/usr.bin/groff/libgroff/itoa.c43
-rw-r--r--gnu/usr.bin/groff/libgroff/lf.cc63
-rw-r--r--gnu/usr.bin/groff/libgroff/lineno.cc1
-rw-r--r--gnu/usr.bin/groff/libgroff/macropath.cc28
-rw-r--r--gnu/usr.bin/groff/libgroff/matherr.c45
-rw-r--r--gnu/usr.bin/groff/libgroff/nametoindex.cc117
-rw-r--r--gnu/usr.bin/groff/libgroff/new.cc67
-rw-r--r--gnu/usr.bin/groff/libgroff/prime.cc28
-rw-r--r--gnu/usr.bin/groff/libgroff/progname.cc1
-rw-r--r--gnu/usr.bin/groff/libgroff/ptable.cc51
-rw-r--r--gnu/usr.bin/groff/libgroff/putenv.c96
-rw-r--r--gnu/usr.bin/groff/libgroff/searchpath.cc117
-rw-r--r--gnu/usr.bin/groff/libgroff/strerror.c37
-rw-r--r--gnu/usr.bin/groff/libgroff/string.cc310
-rw-r--r--gnu/usr.bin/groff/libgroff/strsave.cc33
-rw-r--r--gnu/usr.bin/groff/libgroff/strtol.c120
-rw-r--r--gnu/usr.bin/groff/libgroff/tmpfile.cc99
-rw-r--r--gnu/usr.bin/groff/lkbib/Makefile12
-rw-r--r--gnu/usr.bin/groff/lkbib/lkbib.190
-rw-r--r--gnu/usr.bin/groff/lkbib/lkbib.cc122
-rw-r--r--gnu/usr.bin/groff/lookbib/Makefile12
-rw-r--r--gnu/usr.bin/groff/lookbib/lookbib.158
-rw-r--r--gnu/usr.bin/groff/lookbib/lookbib.cc127
-rw-r--r--gnu/usr.bin/groff/man/Makefile7
-rw-r--r--gnu/usr.bin/groff/man/groff_char.7545
-rw-r--r--gnu/usr.bin/groff/man/groff_font.5351
-rw-r--r--gnu/usr.bin/groff/man/groff_out.5215
-rw-r--r--gnu/usr.bin/groff/mm/ChangeLog252
-rw-r--r--gnu/usr.bin/groff/mm/Makefile34
-rw-r--r--gnu/usr.bin/groff/mm/NOTES101
-rw-r--r--gnu/usr.bin/groff/mm/README26
-rw-r--r--gnu/usr.bin/groff/mm/groff_mm.7738
-rw-r--r--gnu/usr.bin/groff/mm/groff_mmse.736
-rw-r--r--gnu/usr.bin/groff/mm/mm/0.MT143
-rw-r--r--gnu/usr.bin/groff/mm/mm/4.MT65
-rw-r--r--gnu/usr.bin/groff/mm/mm/5.MT33
-rw-r--r--gnu/usr.bin/groff/mm/mm/ms.cov82
-rw-r--r--gnu/usr.bin/groff/mm/mm/se_ms.cov2
-rw-r--r--gnu/usr.bin/groff/mm/tmac.m2582
-rw-r--r--gnu/usr.bin/groff/mm/tmac.mse42
-rw-r--r--gnu/usr.bin/groff/nroff/Makefile11
-rw-r--r--gnu/usr.bin/groff/nroff/nroff.158
-rw-r--r--gnu/usr.bin/groff/nroff/nroff.sh52
-rw-r--r--gnu/usr.bin/groff/nroff/psroff.sh2
-rw-r--r--gnu/usr.bin/groff/pfbtops/Makefile10
-rw-r--r--gnu/usr.bin/groff/pfbtops/pfbtops.127
-rw-r--r--gnu/usr.bin/groff/pfbtops/pfbtops.c112
-rw-r--r--gnu/usr.bin/groff/pic/Makefile17
-rw-r--r--gnu/usr.bin/groff/pic/TODO37
-rw-r--r--gnu/usr.bin/groff/pic/common.cc495
-rw-r--r--gnu/usr.bin/groff/pic/common.h70
-rw-r--r--gnu/usr.bin/groff/pic/depend21
-rw-r--r--gnu/usr.bin/groff/pic/lex.cc1938
-rw-r--r--gnu/usr.bin/groff/pic/main.cc611
-rw-r--r--gnu/usr.bin/groff/pic/object.cc1815
-rw-r--r--gnu/usr.bin/groff/pic/object.h215
-rw-r--r--gnu/usr.bin/groff/pic/output.h79
-rw-r--r--gnu/usr.bin/groff/pic/pic.1730
-rw-r--r--gnu/usr.bin/groff/pic/pic.h101
-rw-r--r--gnu/usr.bin/groff/pic/pic.y1780
-rw-r--r--gnu/usr.bin/groff/pic/position.h47
-rw-r--r--gnu/usr.bin/groff/pic/tex.cc411
-rw-r--r--gnu/usr.bin/groff/pic/text.h28
-rw-r--r--gnu/usr.bin/groff/pic/troff.cc499
-rw-r--r--gnu/usr.bin/groff/psbb/Makefile8
-rw-r--r--gnu/usr.bin/groff/psbb/psbb.126
-rw-r--r--gnu/usr.bin/groff/psbb/psbb.c169
-rw-r--r--gnu/usr.bin/groff/refer/Makefile15
-rw-r--r--gnu/usr.bin/groff/refer/command.cc807
-rw-r--r--gnu/usr.bin/groff/refer/command.h36
-rw-r--r--gnu/usr.bin/groff/refer/label.y1173
-rw-r--r--gnu/usr.bin/groff/refer/ref.cc1144
-rw-r--r--gnu/usr.bin/groff/refer/ref.h120
-rw-r--r--gnu/usr.bin/groff/refer/refer.11282
-rw-r--r--gnu/usr.bin/groff/refer/refer.cc1221
-rw-r--r--gnu/usr.bin/groff/refer/refer.h78
-rw-r--r--gnu/usr.bin/groff/refer/token.cc370
-rw-r--r--gnu/usr.bin/groff/refer/token.h81
-rw-r--r--gnu/usr.bin/groff/soelim/Makefile12
-rw-r--r--gnu/usr.bin/groff/soelim/soelim.142
-rw-r--r--gnu/usr.bin/groff/soelim/soelim.cc278
-rw-r--r--gnu/usr.bin/groff/tbl/Makefile12
-rw-r--r--gnu/usr.bin/groff/tbl/main.cc1497
-rw-r--r--gnu/usr.bin/groff/tbl/table.cc2764
-rw-r--r--gnu/usr.bin/groff/tbl/table.h151
-rw-r--r--gnu/usr.bin/groff/tbl/tbl.1143
-rw-r--r--gnu/usr.bin/groff/tfmtodit/Makefile12
-rw-r--r--gnu/usr.bin/groff/tfmtodit/tfmtodit.1150
-rw-r--r--gnu/usr.bin/groff/tfmtodit/tfmtodit.cc850
-rw-r--r--gnu/usr.bin/groff/tmac/Makefile26
-rw-r--r--gnu/usr.bin/groff/tmac/TODO38
-rw-r--r--gnu/usr.bin/groff/tmac/eqnrc60
-rw-r--r--gnu/usr.bin/groff/tmac/groff_ms.7210
-rw-r--r--gnu/usr.bin/groff/tmac/man.local0
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.X45
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.Xps44
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.an326
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.dvi132
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.latin1101
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.pic10
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.ps52
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.psatk61
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.psfig87
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.psnew26
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.psold60
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.pspic41
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.s1803
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.tty48
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.tty-char196
-rw-r--r--gnu/usr.bin/groff/tmac/troffrc24
-rw-r--r--gnu/usr.bin/groff/troff/Makefile38
-rw-r--r--gnu/usr.bin/groff/troff/TODO132
-rw-r--r--gnu/usr.bin/groff/troff/charinfo.h165
-rw-r--r--gnu/usr.bin/groff/troff/column.cc732
-rw-r--r--gnu/usr.bin/groff/troff/dictionary.cc211
-rw-r--r--gnu/usr.bin/groff/troff/dictionary.h92
-rw-r--r--gnu/usr.bin/groff/troff/div.cc1124
-rw-r--r--gnu/usr.bin/groff/troff/div.h146
-rw-r--r--gnu/usr.bin/groff/troff/env.cc3052
-rw-r--r--gnu/usr.bin/groff/troff/env.h327
-rw-r--r--gnu/usr.bin/groff/troff/hvunits.h340
-rw-r--r--gnu/usr.bin/groff/troff/hyphen.us4449
-rw-r--r--gnu/usr.bin/groff/troff/input.cc5824
-rw-r--r--gnu/usr.bin/groff/troff/node.cc4845
-rw-r--r--gnu/usr.bin/groff/troff/node.h493
-rw-r--r--gnu/usr.bin/groff/troff/number.cc669
-rw-r--r--gnu/usr.bin/groff/troff/reg.cc458
-rw-r--r--gnu/usr.bin/groff/troff/reg.h73
-rw-r--r--gnu/usr.bin/groff/troff/request.h80
-rw-r--r--gnu/usr.bin/groff/troff/symbol.cc144
-rw-r--r--gnu/usr.bin/groff/troff/symbol.h73
-rw-r--r--gnu/usr.bin/groff/troff/token.h197
-rw-r--r--gnu/usr.bin/groff/troff/troff.12004
-rw-r--r--gnu/usr.bin/groff/troff/troff.h86
-rw-r--r--gnu/usr.bin/groff/xditview/ChangeLog259
-rw-r--r--gnu/usr.bin/groff/xditview/DESC9
-rw-r--r--gnu/usr.bin/groff/xditview/Dvi.c544
-rw-r--r--gnu/usr.bin/groff/xditview/Dvi.h46
-rw-r--r--gnu/usr.bin/groff/xditview/DviChar.c664
-rw-r--r--gnu/usr.bin/groff/xditview/DviChar.h37
-rw-r--r--gnu/usr.bin/groff/xditview/DviP.h233
-rw-r--r--gnu/usr.bin/groff/xditview/FontMap17
-rw-r--r--gnu/usr.bin/groff/xditview/GXditview.ad57
-rw-r--r--gnu/usr.bin/groff/xditview/INSTALL20
-rw-r--r--gnu/usr.bin/groff/xditview/Imakefile52
-rw-r--r--gnu/usr.bin/groff/xditview/Makefile30
-rw-r--r--gnu/usr.bin/groff/xditview/Menu.h46
-rw-r--r--gnu/usr.bin/groff/xditview/README14
-rw-r--r--gnu/usr.bin/groff/xditview/TODO15
-rw-r--r--gnu/usr.bin/groff/xditview/XFontName.c256
-rw-r--r--gnu/usr.bin/groff/xditview/XFontName.h45
-rw-r--r--gnu/usr.bin/groff/xditview/device.c587
-rw-r--r--gnu/usr.bin/groff/xditview/device.h21
-rw-r--r--gnu/usr.bin/groff/xditview/draw.c721
-rw-r--r--gnu/usr.bin/groff/xditview/font.c471
-rw-r--r--gnu/usr.bin/groff/xditview/gxditview.1217
-rw-r--r--gnu/usr.bin/groff/xditview/lex.c103
-rw-r--r--gnu/usr.bin/groff/xditview/page.c88
-rw-r--r--gnu/usr.bin/groff/xditview/parse.c334
-rw-r--r--gnu/usr.bin/groff/xditview/xdit.bm14
-rw-r--r--gnu/usr.bin/groff/xditview/xdit_mask.bm14
-rw-r--r--gnu/usr.bin/groff/xditview/xditview.c587
-rw-r--r--gnu/usr.bin/groff/xditview/xtotroff.c303
-rw-r--r--gnu/usr.bin/gzip/bits.c2
-rw-r--r--gnu/usr.bin/gzip/crypt.c2
-rw-r--r--gnu/usr.bin/gzip/deflate.c2
-rw-r--r--gnu/usr.bin/gzip/gzip.c2
-rw-r--r--gnu/usr.bin/gzip/inflate.c2
-rw-r--r--gnu/usr.bin/gzip/lzw.c2
-rw-r--r--gnu/usr.bin/gzip/match.S2
-rw-r--r--gnu/usr.bin/gzip/revision.h2
-rw-r--r--gnu/usr.bin/gzip/tailor.h2
-rw-r--r--gnu/usr.bin/gzip/trees.c2
-rw-r--r--gnu/usr.bin/gzip/unlzh.c2
-rw-r--r--gnu/usr.bin/gzip/unlzw.c2
-rw-r--r--gnu/usr.bin/gzip/unpack.c2
-rw-r--r--gnu/usr.bin/gzip/unzip.c2
-rw-r--r--gnu/usr.bin/gzip/util.c2
-rw-r--r--gnu/usr.bin/gzip/zip.c2
-rw-r--r--gnu/usr.bin/kgdb/COPYING249
-rw-r--r--gnu/usr.bin/kgdb/ChangeLog4887
-rw-r--r--gnu/usr.bin/kgdb/Gdbinit15
-rw-r--r--gnu/usr.bin/kgdb/Makefile34
-rw-r--r--gnu/usr.bin/kgdb/Makefile.dist371
-rw-r--r--gnu/usr.bin/kgdb/Projects114
-rw-r--r--gnu/usr.bin/kgdb/README.gnu142
-rw-r--r--gnu/usr.bin/kgdb/XGdbinit.samp15
-rw-r--r--gnu/usr.bin/kgdb/Xgdb.ad8
-rw-r--r--gnu/usr.bin/kgdb/blockframe.c622
-rw-r--r--gnu/usr.bin/kgdb/breakpoint.c1383
-rw-r--r--gnu/usr.bin/kgdb/command.c856
-rw-r--r--gnu/usr.bin/kgdb/command.h77
-rw-r--r--gnu/usr.bin/kgdb/config/Makefile.i3866
-rw-r--r--gnu/usr.bin/kgdb/config/default-dep.c585
-rw-r--r--gnu/usr.bin/kgdb/config/i386-dep.c1275
-rw-r--r--gnu/usr.bin/kgdb/config/i386-pinsn.c1812
-rw-r--r--gnu/usr.bin/kgdb/config/i386bsd-dep.c1893
-rw-r--r--gnu/usr.bin/kgdb/config/m-i386-sv32.h28
-rw-r--r--gnu/usr.bin/kgdb/config/m-i386.h394
-rw-r--r--gnu/usr.bin/kgdb/config/m-i386bsd.h375
-rw-r--r--gnu/usr.bin/kgdb/config/m-i386g-sv32.h28
-rw-r--r--gnu/usr.bin/kgdb/config/m-i386gas.h37
-rw-r--r--gnu/usr.bin/kgdb/copying.c215
-rw-r--r--gnu/usr.bin/kgdb/core.c579
-rw-r--r--gnu/usr.bin/kgdb/cplus-dem.c996
-rw-r--r--gnu/usr.bin/kgdb/dbxread.c5727
-rw-r--r--gnu/usr.bin/kgdb/defs.h122
-rw-r--r--gnu/usr.bin/kgdb/environ.c185
-rw-r--r--gnu/usr.bin/kgdb/environ.h39
-rw-r--r--gnu/usr.bin/kgdb/eval.c1065
-rw-r--r--gnu/usr.bin/kgdb/expprint.c324
-rw-r--r--gnu/usr.bin/kgdb/expread.y1782
-rw-r--r--gnu/usr.bin/kgdb/expression.h191
-rw-r--r--gnu/usr.bin/kgdb/findvar.c579
-rw-r--r--gnu/usr.bin/kgdb/frame.h115
-rw-r--r--gnu/usr.bin/kgdb/getpagesize.h25
-rw-r--r--gnu/usr.bin/kgdb/infcmd.c1200
-rw-r--r--gnu/usr.bin/kgdb/inferior.h142
-rw-r--r--gnu/usr.bin/kgdb/inflow.c568
-rw-r--r--gnu/usr.bin/kgdb/infrun.c1458
-rw-r--r--gnu/usr.bin/kgdb/kgdb.115
-rw-r--r--gnu/usr.bin/kgdb/kgdb_proto.h63
-rw-r--r--gnu/usr.bin/kgdb/main.c2236
-rw-r--r--gnu/usr.bin/kgdb/ngdb.i386/Makefile29
-rw-r--r--gnu/usr.bin/kgdb/obstack.c313
-rw-r--r--gnu/usr.bin/kgdb/obstack.h372
-rw-r--r--gnu/usr.bin/kgdb/printcmd.c1867
-rw-r--r--gnu/usr.bin/kgdb/regex.c1738
-rw-r--r--gnu/usr.bin/kgdb/regex.h185
-rw-r--r--gnu/usr.bin/kgdb/remote-sl.c10
-rw-r--r--gnu/usr.bin/kgdb/remote.c626
-rw-r--r--gnu/usr.bin/kgdb/source.c1166
-rw-r--r--gnu/usr.bin/kgdb/stab.def115
-rw-r--r--gnu/usr.bin/kgdb/stack.c960
-rw-r--r--gnu/usr.bin/kgdb/symmisc.c584
-rw-r--r--gnu/usr.bin/kgdb/symseg.h523
-rw-r--r--gnu/usr.bin/kgdb/symtab.c2473
-rw-r--r--gnu/usr.bin/kgdb/symtab.h384
-rw-r--r--gnu/usr.bin/kgdb/utils.c1094
-rw-r--r--gnu/usr.bin/kgdb/valarith.c690
-rw-r--r--gnu/usr.bin/kgdb/valops.c1418
-rw-r--r--gnu/usr.bin/kgdb/valprint.c1430
-rw-r--r--gnu/usr.bin/kgdb/value.h212
-rw-r--r--gnu/usr.bin/kgdb/values.c1059
-rw-r--r--gnu/usr.bin/kgdb/version.c20
-rw-r--r--gnu/usr.bin/kgdb/wait.h81
-rw-r--r--gnu/usr.bin/kgdb/xgdb/Makefile40
-rw-r--r--gnu/usr.bin/kgdb/xgdb/xgdb.c700
-rw-r--r--gnu/usr.bin/ld/Makefile2
-rw-r--r--gnu/usr.bin/ld/cplus-dem.c2
-rw-r--r--gnu/usr.bin/ld/etc.c2
-rw-r--r--gnu/usr.bin/ld/i386/md-static-funcs.c2
-rw-r--r--gnu/usr.bin/ld/i386/md.c2
-rw-r--r--gnu/usr.bin/ld/i386/md.h2
-rw-r--r--gnu/usr.bin/ld/i386/mdprologue.S2
-rw-r--r--gnu/usr.bin/ld/ld.12
-rw-r--r--gnu/usr.bin/ld/ld.c2
-rw-r--r--gnu/usr.bin/ld/ld.h2
-rw-r--r--gnu/usr.bin/ld/ldconfig/Makefile2
-rw-r--r--gnu/usr.bin/ld/ldconfig/ldconfig.c2
-rw-r--r--gnu/usr.bin/ld/ldd/Makefile2
-rw-r--r--gnu/usr.bin/ld/ldd/ldd.c2
-rw-r--r--gnu/usr.bin/ld/lib.c2
-rw-r--r--gnu/usr.bin/ld/rrs.c2
-rw-r--r--gnu/usr.bin/ld/rtld/Makefile2
-rw-r--r--gnu/usr.bin/ld/rtld/malloc.c2
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.c2
-rw-r--r--gnu/usr.bin/ld/rtld/sbrk.c2
-rw-r--r--gnu/usr.bin/ld/shlib.c2
-rw-r--r--gnu/usr.bin/ld/sparc/md-static-funcs.c2
-rw-r--r--gnu/usr.bin/ld/sparc/md.c2
-rw-r--r--gnu/usr.bin/ld/sparc/md.h2
-rw-r--r--gnu/usr.bin/ld/sparc/mdprologue.S2
-rw-r--r--gnu/usr.bin/ld/symbol.c2
-rw-r--r--gnu/usr.bin/ld/symseg.h2
-rw-r--r--gnu/usr.bin/ld/warnings.c2
-rw-r--r--gnu/usr.bin/ld/xbits.c2
-rw-r--r--gnu/usr.bin/man/apropos/Makefile2
-rw-r--r--gnu/usr.bin/patch/EXTERN.h7
-rw-r--r--gnu/usr.bin/patch/INTERN.h7
-rw-r--r--gnu/usr.bin/patch/common.h8
-rw-r--r--gnu/usr.bin/patch/inp.c7
-rw-r--r--gnu/usr.bin/patch/inp.h7
-rw-r--r--gnu/usr.bin/patch/patch.17
-rw-r--r--gnu/usr.bin/patch/patch.c7
-rw-r--r--gnu/usr.bin/patch/pch.c7
-rw-r--r--gnu/usr.bin/patch/pch.h7
-rw-r--r--gnu/usr.bin/patch/util.h7
-rw-r--r--gnu/usr.bin/patch/version.c7
-rw-r--r--gnu/usr.bin/patch/version.h7
-rw-r--r--gnu/usr.bin/perl/eg/ADB2
-rw-r--r--gnu/usr.bin/perl/eg/changes2
-rw-r--r--gnu/usr.bin/perl/eg/dus2
-rw-r--r--gnu/usr.bin/perl/eg/findcp2
-rw-r--r--gnu/usr.bin/perl/eg/findtar2
-rw-r--r--gnu/usr.bin/perl/eg/g/gcp2
-rw-r--r--gnu/usr.bin/perl/eg/g/gcp.man2
-rw-r--r--gnu/usr.bin/perl/eg/g/ged2
-rw-r--r--gnu/usr.bin/perl/eg/g/gsh2
-rw-r--r--gnu/usr.bin/perl/eg/g/gsh.man2
-rw-r--r--gnu/usr.bin/perl/eg/muck.man2
-rw-r--r--gnu/usr.bin/perl/eg/myrup2
-rw-r--r--gnu/usr.bin/perl/eg/nih2
-rw-r--r--gnu/usr.bin/perl/eg/relink7
-rw-r--r--gnu/usr.bin/perl/eg/rename7
-rw-r--r--gnu/usr.bin/perl/eg/rmfrom2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scan_df2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scan_last2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scan_messages2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scan_passwd2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scan_ps2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scan_sudo2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scan_suid2
-rw-r--r--gnu/usr.bin/perl/eg/scan/scanner2
-rw-r--r--gnu/usr.bin/perl/eg/shmkill2
-rw-r--r--gnu/usr.bin/perl/eg/van/empty2
-rw-r--r--gnu/usr.bin/perl/eg/van/unvanish2
-rw-r--r--gnu/usr.bin/perl/eg/van/vanexp2
-rw-r--r--gnu/usr.bin/perl/eg/van/vanish2
-rw-r--r--gnu/usr.bin/perl/emacs/perldb.pl7
-rw-r--r--gnu/usr.bin/perl/lib/ctime.pl2
-rw-r--r--gnu/usr.bin/perl/lib/getopt.pl2
-rw-r--r--gnu/usr.bin/perl/lib/importenv.pl2
-rw-r--r--gnu/usr.bin/perl/lib/perldb.pl7
-rw-r--r--gnu/usr.bin/perl/lib/pwd.pl7
-rw-r--r--gnu/usr.bin/perl/lib/stat.pl2
-rw-r--r--gnu/usr.bin/perl/lib/syslog.pl5
-rw-r--r--gnu/usr.bin/perl/lib/termcap.pl2
-rw-r--r--gnu/usr.bin/perl/lib/validate.pl2
-rw-r--r--gnu/usr.bin/perl/misc/c2ph2
-rw-r--r--gnu/usr.bin/perl/misc/pstruct2
-rw-r--r--gnu/usr.bin/perl/perl/EXTERN.h7
-rw-r--r--gnu/usr.bin/perl/perl/INTERN.h7
-rw-r--r--gnu/usr.bin/perl/perl/arg.h8
-rw-r--r--gnu/usr.bin/perl/perl/array.c7
-rw-r--r--gnu/usr.bin/perl/perl/array.h7
-rw-r--r--gnu/usr.bin/perl/perl/cmd.c7
-rw-r--r--gnu/usr.bin/perl/perl/cmd.h7
-rw-r--r--gnu/usr.bin/perl/perl/cons.c7
-rw-r--r--gnu/usr.bin/perl/perl/consarg.c8
-rw-r--r--gnu/usr.bin/perl/perl/crypt.c2
-rw-r--r--gnu/usr.bin/perl/perl/doarg.c8
-rw-r--r--gnu/usr.bin/perl/perl/doio.c8
-rw-r--r--gnu/usr.bin/perl/perl/dolist.c7
-rw-r--r--gnu/usr.bin/perl/perl/dump.c8
-rw-r--r--gnu/usr.bin/perl/perl/eval.c7
-rw-r--r--gnu/usr.bin/perl/perl/form.c7
-rw-r--r--gnu/usr.bin/perl/perl/form.h7
-rw-r--r--gnu/usr.bin/perl/perl/handy.h7
-rw-r--r--gnu/usr.bin/perl/perl/hash.c7
-rw-r--r--gnu/usr.bin/perl/perl/hash.h7
-rw-r--r--gnu/usr.bin/perl/perl/malloc.c7
-rw-r--r--gnu/usr.bin/perl/perl/perl.110
-rw-r--r--gnu/usr.bin/perl/perl/perl.c10
-rw-r--r--gnu/usr.bin/perl/perl/perl.h7
-rw-r--r--gnu/usr.bin/perl/perl/regcomp.c7
-rw-r--r--gnu/usr.bin/perl/perl/regcomp.h7
-rw-r--r--gnu/usr.bin/perl/perl/regexec.c7
-rw-r--r--gnu/usr.bin/perl/perl/regexp.h7
-rw-r--r--gnu/usr.bin/perl/perl/spat.h7
-rw-r--r--gnu/usr.bin/perl/perl/stab.c7
-rw-r--r--gnu/usr.bin/perl/perl/stab.h7
-rw-r--r--gnu/usr.bin/perl/perl/str.c7
-rw-r--r--gnu/usr.bin/perl/perl/str.h7
-rw-r--r--gnu/usr.bin/perl/perl/t/Op.dbmx.dbbin0 -> 16384 bytes
-rwxr-xr-xgnu/usr.bin/perl/perl/t/TEST2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/base/cond.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/base/if.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/base/lex.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/base/pat.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/base/term.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/cmd/elsif.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/cmd/for.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/cmd/mod.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/cmd/subval.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/cmd/switch.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/cmd/while.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/comp/cmdopt.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/comp/cpp.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/comp/decl.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/comp/multiline.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/comp/script.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/comp/term.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/io/argv.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/io/dup.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/io/fs.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/io/inplace.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/io/pipe.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/io/print.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/io/tell.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/append.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/array.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/auto.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/chop.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/cond.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/dbm.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/delete.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/do.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/each.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/eval.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/exec.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/exp.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/flip.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/fork.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/glob.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/goto.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/index.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/int.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/join.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/list.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/local.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/magic.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/mkdir.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/oct.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/ord.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/pack.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/pat.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/push.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/range.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/read.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/regexp.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/repeat.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/s.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/sleep.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/sort.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/split.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/sprintf.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/stat.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/study.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/substr.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/time.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/undef.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/unshift.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/vec.t2
-rwxr-xr-xgnu/usr.bin/perl/perl/t/op/write.t2
-rw-r--r--gnu/usr.bin/perl/perl/tdoio.c7
-rw-r--r--gnu/usr.bin/perl/perl/toke.c7
-rw-r--r--gnu/usr.bin/perl/perl/usersub.c7
-rw-r--r--gnu/usr.bin/perl/perl/usub/bsdcurses.mus7
-rw-r--r--gnu/usr.bin/perl/perl/usub/curses.mus7
-rw-r--r--gnu/usr.bin/perl/perl/usub/usersub.c7
-rw-r--r--gnu/usr.bin/perl/perl/util.c7
-rw-r--r--gnu/usr.bin/perl/perl/util.h7
-rw-r--r--gnu/usr.bin/perl/x2p/EXTERN.h7
-rw-r--r--gnu/usr.bin/perl/x2p/INTERN.h7
-rw-r--r--gnu/usr.bin/perl/x2p/a2p.17
-rw-r--r--gnu/usr.bin/perl/x2p/a2p.c7
-rw-r--r--gnu/usr.bin/perl/x2p/a2p.h7
-rw-r--r--gnu/usr.bin/perl/x2p/a2p.y7
-rw-r--r--gnu/usr.bin/perl/x2p/a2py.c7
-rw-r--r--gnu/usr.bin/perl/x2p/handy.h7
-rw-r--r--gnu/usr.bin/perl/x2p/hash.c7
-rw-r--r--gnu/usr.bin/perl/x2p/hash.h7
-rw-r--r--gnu/usr.bin/perl/x2p/malloc.c7
-rwxr-xr-xgnu/usr.bin/perl/x2p/s2p15
-rw-r--r--gnu/usr.bin/perl/x2p/s2p.17
-rw-r--r--gnu/usr.bin/perl/x2p/str.c7
-rw-r--r--gnu/usr.bin/perl/x2p/str.h7
-rw-r--r--gnu/usr.bin/perl/x2p/util.c7
-rw-r--r--gnu/usr.bin/perl/x2p/util.h7
-rw-r--r--gnu/usr.bin/perl/x2p/walk.c7
-rw-r--r--gnu/usr.bin/ptx/texinfo.tex4053
-rw-r--r--gnu/usr.bin/rcs/ci/ci.12
-rw-r--r--gnu/usr.bin/rcs/ci/ci.c7
-rw-r--r--gnu/usr.bin/rcs/co/co.12
-rw-r--r--gnu/usr.bin/rcs/co/co.c9
-rw-r--r--gnu/usr.bin/rcs/doc/rcs.ms2
-rw-r--r--gnu/usr.bin/rcs/ident/ident.12
-rw-r--r--gnu/usr.bin/rcs/ident/ident.c7
-rw-r--r--gnu/usr.bin/rcs/lib/conf.h2
-rw-r--r--gnu/usr.bin/rcs/lib/maketime.c7
-rw-r--r--gnu/usr.bin/rcs/lib/merger.c2
-rw-r--r--gnu/usr.bin/rcs/lib/partime.c7
-rw-r--r--gnu/usr.bin/rcs/lib/rcsbase.h9
-rw-r--r--gnu/usr.bin/rcs/lib/rcsedit.c9
-rw-r--r--gnu/usr.bin/rcs/lib/rcsfcmp.c7
-rw-r--r--gnu/usr.bin/rcs/lib/rcsfnms.c7
-rw-r--r--gnu/usr.bin/rcs/lib/rcsgen.c7
-rw-r--r--gnu/usr.bin/rcs/lib/rcskeep.c7
-rw-r--r--gnu/usr.bin/rcs/lib/rcskeys.c10
-rw-r--r--gnu/usr.bin/rcs/lib/rcslex.c8
-rw-r--r--gnu/usr.bin/rcs/lib/rcsmap.c2
-rw-r--r--gnu/usr.bin/rcs/lib/rcsrev.c7
-rw-r--r--gnu/usr.bin/rcs/lib/rcssyn.c7
-rw-r--r--gnu/usr.bin/rcs/lib/rcsutil.c7
-rw-r--r--gnu/usr.bin/rcs/merge/merge.12
-rw-r--r--gnu/usr.bin/rcs/merge/merge.c2
-rw-r--r--gnu/usr.bin/rcs/rcs/rcs.12
-rw-r--r--gnu/usr.bin/rcs/rcs/rcs.c7
-rw-r--r--gnu/usr.bin/rcs/rcs/rcsfile.52
-rw-r--r--gnu/usr.bin/rcs/rcs/rcsintro.12
-rw-r--r--gnu/usr.bin/rcs/rcsclean/rcsclean.12
-rw-r--r--gnu/usr.bin/rcs/rcsclean/rcsclean.c2
-rw-r--r--gnu/usr.bin/rcs/rcsdiff/rcsdiff.12
-rw-r--r--gnu/usr.bin/rcs/rcsdiff/rcsdiff.c7
-rw-r--r--gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.12
-rw-r--r--gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh2
-rw-r--r--gnu/usr.bin/rcs/rcsmerge/rcsmerge.12
-rw-r--r--gnu/usr.bin/rcs/rcsmerge/rcsmerge.c7
-rw-r--r--[-rwxr-xr-x]gnu/usr.bin/rcs/rcstest2
-rw-r--r--gnu/usr.bin/rcs/rlog/rlog.12
-rw-r--r--gnu/usr.bin/rcs/rlog/rlog.c7
-rw-r--r--gnu/usr.bin/tar/getdate.y4
-rw-r--r--gnu/usr.bin/texinfo/Makefile2
-rw-r--r--gnu/usr.bin/texinfo/Makefile.inc2
-rw-r--r--gnu/usr.bin/texinfo/info-files/texi-files/texinfo.tex4003
-rw-r--r--gnu/usr.bin/texinfo/makedoc/Makefile2
-rw-r--r--gnu/usr.bin/texinfo/makeinfo/Makefile2
-rwxr-xr-xgnu/usr.bin/texinfo/misc/texindexbin0 -> 52315 bytes
-rw-r--r--gnu/usr.bin/texinfo/texindex/Makefile2
1087 files changed, 211296 insertions, 688 deletions
diff --git a/gnu/games/Makefile b/gnu/games/Makefile
index 4a7577e53ef8..487b2281f428 100644
--- a/gnu/games/Makefile
+++ b/gnu/games/Makefile
@@ -1,4 +1,4 @@
-# $Id$
+# Makefile,v 1.1 1994/01/30 00:55:25 rgrimes Exp
SUBDIR= chess
diff --git a/gnu/games/Makefile.inc b/gnu/games/Makefile.inc
index 4437a8428bef..fc510d3f5d98 100644
--- a/gnu/games/Makefile.inc
+++ b/gnu/games/Makefile.inc
@@ -1,4 +1,4 @@
-# $Id$
+# Makefile.inc,v 1.1 1994/01/30 00:55:54 rgrimes Exp
BINOWN?= games
.if defined(HIDEGAME)
diff --git a/gnu/games/chess/Xchess/Makefile b/gnu/games/chess/Xchess/Makefile
index d8892e29d39e..d9ed74c40596 100644
--- a/gnu/games/chess/Xchess/Makefile
+++ b/gnu/games/chess/Xchess/Makefile
@@ -1,5 +1,5 @@
-# RCS Info: $Revision: 1.1.1.1 $ on $Date: 1993/06/12 14:41:05 $
-# $Source: /a/cvs/386BSD/src/gnu/chess/Xchess/Makefile,v $
+# RCS Info: 1.2 on 1994/01/07 11:10:39
+# /home/ncvs/src/gnu/games/chess/Xchess/Makefile,v
# Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#
# Makefile for xchess.
diff --git a/gnu/games/chess/Xchess/XCircle.c b/gnu/games/chess/Xchess/XCircle.c
index d2144bcab849..6a2f2afe95d2 100644
--- a/gnu/games/chess/Xchess/XCircle.c
+++ b/gnu/games/chess/Xchess/XCircle.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:17:04 $
- * $Source: /users/faustus/xchess/RCS/XCircle.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:12
+ * /home/ncvs/src/gnu/games/chess/Xchess/XCircle.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/board.c b/gnu/games/chess/Xchess/board.c
index 4c5b9347d8e6..a4c63b3653cf 100644
--- a/gnu/games/chess/Xchess/board.c
+++ b/gnu/games/chess/Xchess/board.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:17:15 $
- * $Source: /users/faustus/xchess/RCS/board.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:08
+ * /home/ncvs/src/gnu/games/chess/Xchess/board.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/button.c b/gnu/games/chess/Xchess/button.c
index 67bf3c86942f..e183501952ba 100644
--- a/gnu/games/chess/Xchess/button.c
+++ b/gnu/games/chess/Xchess/button.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:09:41 $
- * $Source: /users/faustus/xchess/RCS/button.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:15
+ * /home/ncvs/src/gnu/games/chess/Xchess/button.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/clock.c b/gnu/games/chess/Xchess/clock.c
index a7b3c3264e3c..c451d8447967 100644
--- a/gnu/games/chess/Xchess/clock.c
+++ b/gnu/games/chess/Xchess/clock.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:09:47 $
- * $Source: /users/faustus/xchess/RCS/clock.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:08
+ * /home/ncvs/src/gnu/games/chess/Xchess/clock.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/control.c b/gnu/games/chess/Xchess/control.c
index ad2e1d7994fd..e72b4d4b3fa3 100644
--- a/gnu/games/chess/Xchess/control.c
+++ b/gnu/games/chess/Xchess/control.c
@@ -19,8 +19,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:17:32 $
- * $Source: /users/faustus/xchess/RCS/control.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:11
+ * /home/ncvs/src/gnu/games/chess/Xchess/control.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/jail.c b/gnu/games/chess/Xchess/jail.c
index e5e60642430a..9d69e0e6d9d0 100644
--- a/gnu/games/chess/Xchess/jail.c
+++ b/gnu/games/chess/Xchess/jail.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.3 $ on $Date: 86/11/26 12:09:54 $
- * $Source: /users/faustus/xchess/RCS/jail.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:12
+ * /home/ncvs/src/gnu/games/chess/Xchess/jail.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/message.c b/gnu/games/chess/Xchess/message.c
index 8b85e9c77f83..c6b536eeb369 100644
--- a/gnu/games/chess/Xchess/message.c
+++ b/gnu/games/chess/Xchess/message.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:10:22 $
- * $Source: /users/faustus/xchess/RCS/message.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:14
+ * /home/ncvs/src/gnu/games/chess/Xchess/message.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/parse.c b/gnu/games/chess/Xchess/parse.c
index c66cc38bdbfe..338484c0dce4 100644
--- a/gnu/games/chess/Xchess/parse.c
+++ b/gnu/games/chess/Xchess/parse.c
@@ -19,8 +19,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:17:59 $
- * $Source: /users/faustus/xchess/RCS/parse.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:06
+ * /home/ncvs/src/gnu/games/chess/Xchess/parse.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/popup.c b/gnu/games/chess/Xchess/popup.c
index 2e19ee5b4c35..cd3ce113438c 100644
--- a/gnu/games/chess/Xchess/popup.c
+++ b/gnu/games/chess/Xchess/popup.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/26 12:10:38 $
- * $Source: /users/faustus/xchess/RCS/popup.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:13
+ * /home/ncvs/src/gnu/games/chess/Xchess/popup.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* faustus@cad.berkeley.edu, ucbvax!faustus
* Permission is granted to modify and re-distribute this code in any manner
diff --git a/gnu/games/chess/Xchess/program.c b/gnu/games/chess/Xchess/program.c
index c1ec0aca64bb..ceff46e71d5e 100644
--- a/gnu/games/chess/Xchess/program.c
+++ b/gnu/games/chess/Xchess/program.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.2 $ on $Date: 1994/01/07 11:10:40 $
- * $Source: /home/ncvs/src/gnu/games/chess/Xchess/program.c,v $
+/* RCS Info: 1.3 on 1994/11/04 02:11:30
+ * /home/ncvs/src/gnu/games/chess/Xchess/program.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/record.c b/gnu/games/chess/Xchess/record.c
index d9459b3a64f0..d548b580829c 100644
--- a/gnu/games/chess/Xchess/record.c
+++ b/gnu/games/chess/Xchess/record.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:18:20 $
- * $Source: /users/faustus/xchess/RCS/record.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:09
+ * /home/ncvs/src/gnu/games/chess/Xchess/record.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/std.c b/gnu/games/chess/Xchess/std.c
index 1aa9e8389186..e733c146344e 100644
--- a/gnu/games/chess/Xchess/std.c
+++ b/gnu/games/chess/Xchess/std.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.2 $ on $Date: 1994/01/07 11:10:42 $
- * $Source: /home/ncvs/src/gnu/games/chess/Xchess/std.c,v $
+/* RCS Info: 1.3 on 1994/11/04 02:11:33
+ * /home/ncvs/src/gnu/games/chess/Xchess/std.c,v
* Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
*
* Utility routines.
diff --git a/gnu/games/chess/Xchess/std.h b/gnu/games/chess/Xchess/std.h
index fc8fa6460dcb..29c603d07bf6 100644
--- a/gnu/games/chess/Xchess/std.h
+++ b/gnu/games/chess/Xchess/std.h
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:18:32 $
- * $Source: /users/faustus/xchess/RCS/std.h,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:06
+ * /home/ncvs/src/gnu/games/chess/Xchess/std.h,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
*
* Standard definitions.
diff --git a/gnu/games/chess/Xchess/valid.c b/gnu/games/chess/Xchess/valid.c
index 3dcdb004d320..e037134f4b8e 100644
--- a/gnu/games/chess/Xchess/valid.c
+++ b/gnu/games/chess/Xchess/valid.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.3 $ on $Date: 86/11/23 17:18:35 $
- * $Source: /users/faustus/xchess/RCS/valid.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:08
+ * /home/ncvs/src/gnu/games/chess/Xchess/valid.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/window.c b/gnu/games/chess/Xchess/window.c
index 4aae06d9ad90..fb92206149c9 100644
--- a/gnu/games/chess/Xchess/window.c
+++ b/gnu/games/chess/Xchess/window.c
@@ -19,8 +19,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:15 $
- * $Source: /users/faustus/xchess/RCS/window.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:08
+ * /home/ncvs/src/gnu/games/chess/Xchess/window.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/window.c.bm b/gnu/games/chess/Xchess/window.c.bm
index 19134d0cdc14..0979769439d9 100644
--- a/gnu/games/chess/Xchess/window.c.bm
+++ b/gnu/games/chess/Xchess/window.c.bm
@@ -19,8 +19,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:15 $
- * $Source: /users/faustus/xchess/RCS/window.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:07
+ * /home/ncvs/src/gnu/games/chess/Xchess/window.c.bm,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/xchess.c b/gnu/games/chess/Xchess/xchess.c
index 6de6502ddd28..ff3b3b4e1cc1 100644
--- a/gnu/games/chess/Xchess/xchess.c
+++ b/gnu/games/chess/Xchess/xchess.c
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.2 $ on $Date: 89/04/28 08:44:02 $
- * $Source: /usr/local/src/source/X.V11R3/contrib/games/xchess/Xchess/RCS/xchess.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:09
+ * /home/ncvs/src/gnu/games/chess/Xchess/xchess.c,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/xchess.c.150 b/gnu/games/chess/Xchess/xchess.c.150
index 2c17906c3571..36c237984a59 100644
--- a/gnu/games/chess/Xchess/xchess.c.150
+++ b/gnu/games/chess/Xchess/xchess.c.150
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:32 $
- * $Source: /users/faustus/xchess/RCS/xchess.c,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:20
+ * /home/ncvs/src/gnu/games/chess/Xchess/xchess.c.150,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/games/chess/Xchess/xchess.h b/gnu/games/chess/Xchess/xchess.h
index 355731d8b403..da9014195568 100644
--- a/gnu/games/chess/Xchess/xchess.h
+++ b/gnu/games/chess/Xchess/xchess.h
@@ -20,8 +20,8 @@ file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */
-/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:39 $
- * $Source: /users/faustus/xchess/RCS/xchess.h,v $
+/* RCS Info: 1.1.1.1 on 1993/06/12 14:41:15
+ * /home/ncvs/src/gnu/games/chess/Xchess/xchess.h,v
* Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
* Permission is granted to do anything with this code except sell it
* or remove this message.
diff --git a/gnu/gnu2bmake/gcc-2.6.1.tcl b/gnu/gnu2bmake/gcc-2.6.1.tcl
index a56c804af861..4a8313ab2d9f 100755
--- a/gnu/gnu2bmake/gcc-2.6.1.tcl
+++ b/gnu/gnu2bmake/gcc-2.6.1.tcl
@@ -7,7 +7,7 @@
# this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
# ----------------------------------------------------------------------------
#
-# $Id$
+# gcc-2.6.1.tcl,v 1.2 1994/11/15 04:52:18 phk Exp
#
# Good for 2.6.1 and 2.6.2
@@ -135,7 +135,7 @@ sh "mkdir $ddir/legal"
sh "cp $sdir/gen-*.c $sdir/md $ddir/legal"
set f [open $ddir/README w]
puts $f {
-$Id$
+gcc-2.6.1.tcl,v 1.2 1994/11/15 04:52:18 phk Exp
This directory contains gcc in a form that uses "bmake" makefiles.
This is not the place you want to start, if you want to hack gcc.
diff --git a/gnu/gnu2bmake/gnu2bmake.tcl b/gnu/gnu2bmake/gnu2bmake.tcl
index a99b1b3d134d..35e29a93b3aa 100644
--- a/gnu/gnu2bmake/gnu2bmake.tcl
+++ b/gnu/gnu2bmake/gnu2bmake.tcl
@@ -7,7 +7,7 @@
# this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
# ----------------------------------------------------------------------------
#
-# $Id$
+# gnu2bmake.tcl,v 1.3 1994/11/15 04:52:19 phk Exp
#
#######################################################################
# Generic procedures usable in the process of gnu-to-bmake jobs.
diff --git a/gnu/include/Makefile b/gnu/include/Makefile
index e05dbf801302..e8c8abf96bc3 100644
--- a/gnu/include/Makefile
+++ b/gnu/include/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.19 1994/11/01 09:19:50 pst Exp $
+# Makefile,v 1.1 1994/11/08 00:47:02 ache Exp
#
all depend lint tags:
diff --git a/gnu/lib/Makefile b/gnu/lib/Makefile
index dd6496f8f6d8..85c3048cd5b4 100644
--- a/gnu/lib/Makefile
+++ b/gnu/lib/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.4 1994/09/09 15:10:37 rgrimes Exp $
+# Makefile,v 1.5 1994/10/11 23:34:13 ache Exp
SUBDIR= libdialog libg++ libmalloc libregex libreadline
diff --git a/gnu/lib/Makefile.inc b/gnu/lib/Makefile.inc
index 605c0cd382ab..7123f8bc6e89 100644
--- a/gnu/lib/Makefile.inc
+++ b/gnu/lib/Makefile.inc
@@ -1,4 +1,4 @@
-# $Id: Makefile.inc,v 1.3 1994/05/28 09:56:30 csgr Exp $
+# Makefile.inc,v 1.4 1994/08/05 21:33:53 wollman Exp
SHLIB_MAJOR?= 2
SHLIB_MINOR?= 0
diff --git a/gnu/lib/libdialog/Makefile b/gnu/lib/libdialog/Makefile
index 55624154ae72..6d321d221ccf 100644
--- a/gnu/lib/libdialog/Makefile
+++ b/gnu/lib/libdialog/Makefile
@@ -1,5 +1,5 @@
# Makefile for libdialog
-# $Id: Makefile,v 1.5 1994/10/28 03:08:14 ache Exp $
+# Makefile,v 1.6 1994/10/28 05:36:38 jkh Exp
LIB= dialog
SRCS= kernel.c rc.c checklist.c inputbox.c menubox.c msgbox.c \
diff --git a/gnu/lib/libmalloc/Makefile b/gnu/lib/libmalloc/Makefile
index 1d33b0f25bc5..f6868cd80ecd 100644
--- a/gnu/lib/libmalloc/Makefile
+++ b/gnu/lib/libmalloc/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.4 1993/12/28 07:54:51 smace Exp $
+# Makefile,v 1.5 1994/05/27 10:48:19 csgr Exp
CFLAGS+= -I${.CURDIR}
diff --git a/gnu/lib/libreadline/Makefile b/gnu/lib/libreadline/Makefile
index 514cf2b52431..3352b45d909e 100644
--- a/gnu/lib/libreadline/Makefile
+++ b/gnu/lib/libreadline/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.15 1994/11/01 09:13:02 pst Exp $
+# Makefile,v 1.16 1994/11/01 17:32:46 ache Exp
CFLAGS+= -I${.CURDIR} -DVOID_SIGHANDLER \
diff --git a/gnu/lib/libreadline/VERSION b/gnu/lib/libreadline/VERSION
new file mode 100644
index 000000000000..97c5aef14b50
--- /dev/null
+++ b/gnu/lib/libreadline/VERSION
@@ -0,0 +1 @@
+readline 2.0 from bash1.14.1
diff --git a/gnu/lib/libregex/Makefile b/gnu/lib/libregex/Makefile
index 7fee0790a90b..22e5e0856fb9 100644
--- a/gnu/lib/libregex/Makefile
+++ b/gnu/lib/libregex/Makefile
@@ -1,4 +1,4 @@
-# $Header: /home/ncvs/src/gnu/lib/libregex/Makefile,v 1.8 1994/05/27 10:53:33 csgr Exp $
+# /home/ncvs/src/gnu/lib/libregex/Makefile,v 1.9 1994/09/15 19:52:50 bde Exp
LIB= gnuregex
diff --git a/gnu/lib/libregex/doc/texinfo.tex b/gnu/lib/libregex/doc/texinfo.tex
new file mode 100644
index 000000000000..d10917e237db
--- /dev/null
+++ b/gnu/lib/libregex/doc/texinfo.tex
@@ -0,0 +1,3941 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc.
+
+%This texinfo.tex 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 texinfo.tex 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 texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+\def\texinfoversion{2.104}
+\message{Loading texinfo package [Version \texinfoversion]:}
+\message{}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ } % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }}
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments.
+
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+{\advance \baselineskip by -\singlespaceskip
+\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) But the next line of text also gets us \parskip glue.
+ % Final result: space below is slightly more than space above.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % We do @comment here in case we are called inside an environment,
+ % such as @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+%Use \input\thisfile to avoid blank after \input, which may be an active
+%char (in which case the blank would become the \input argument).
+%The grouping keeps the value of \thisfile correct even when @include
+%is nested.
+\def\includezzz #1{\begingroup
+\def\thisfile{#1}\input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\include = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ \long\def\doignoretext##1\end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+%
+\def\set{\parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+}
+\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+ \ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}
+ \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex). But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\font\textrm=cmr12
+\font\texttt=cmtt12
+\else
+\font\textrm=cmr10 scaled \mainmagstep
+\font\texttt=cmtt10 scaled \mainmagstep
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\textbf=cmb10 scaled \mainmagstep
+\font\textit=cmti10 scaled \mainmagstep
+\font\textsl=cmsl10 scaled \mainmagstep
+\font\textsf=cmss10 scaled \mainmagstep
+\font\textsc=cmcsc10 scaled \mainmagstep
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\font\ninett=cmtt9
+\font\indrm=cmr9
+\font\indit=cmsl9
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\let\indsc=\indrm
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+\font\chapsc=cmcsc10 scaled\magstep3
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+\font\secsc=cmcsc10 scaled\magstep2
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad.
+% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+\font\ssecsc=cmcsc10 scaled \magstep1
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current. Plain TeX does, for example,
+% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need
+% to redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+ \resetmathfonts}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+ \resetmathfonts}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+ \resetmathfonts}
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
+ \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\font\shortcontrm=cmr12
+\font\shortcontbf=cmbx12
+\font\shortcontsl=cmsl12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \nohyphenation \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+\let\code=\tclose
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ \parskip=0in
+ \par
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0
+ \nobreak
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}%
+ \fi
+ \endgroup
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\endgroup\afterenvbreak}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\endgroup\afterenvbreak}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\endgroup\afterenvbreak}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\endgroup\afterenvbreak}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\def\doind #1#2{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+ \tex
+ \dobreak \chapheadingskip {10000}
+ \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+ \catcode`\$=\other\catcode`\_=\other
+ \catcode`\~=\other
+ %
+ % The following don't help, since the chars were translated
+ % when the raw index was written, and their fonts were discarded
+ % due to \indexnofonts.
+ %\catcode`\"=\active
+ %\catcode`\^=\active
+ %\catcode`\_=\active
+ %\catcode`\|=\active
+ %\catcode`\<=\active
+ %\catcode`\>=\active
+ % %
+ \def\indexbackslash{\rawbackslashxx}
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+ \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent=2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXbook, page 416.
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage
+ =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \eject
+ %
+ % Now switch to the double-column output routine.
+ \output={\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it once.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +- <
+ % 1pt) as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+ \doublecolumnpagegoal
+}
+
+\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
+
+\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
+ \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
+ \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
+ \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+ \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+}
+\def\doublecolumnpagegoal{%
+ \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\doublecolumnout{%
+ \setbox5=\copy255
+ {\vbadness=10000 \doublecolumnsplit}
+ \ifvbox255
+ \setbox0=\vtop to\dimen@{\unvbox0}
+ \setbox2=\vtop to\dimen@{\unvbox2}
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
+ \else
+ \setbox0=\vbox{\unvbox5}
+ \ifvbox0
+ \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ {\vbadness=10000
+ \loop \global\setbox5=\copy0
+ \setbox1=\vsplit5 to\dimen@
+ \setbox3=\vsplit5 to\dimen@
+ \ifvbox5 \global\advance\dimen@ by1pt \repeat
+ \setbox0=\vbox to\dimen@{\unvbox1}
+ \setbox2=\vbox to\dimen@{\unvbox3}
+ \global\setbox\partialpage=\vbox{\pagesofar}
+ \doublecolumnpagegoal
+ }
+ \fi
+ \fi
+}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appenixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #2\enspace #1}%
+ }%
+ \bigskip
+ \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \ifnum \pageno>0
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{Table of Contents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{Short Contents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm Appendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in in \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+\def\tocentry#1#2{\begingroup
+ \hyphenpenalty = 10000
+ \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^M gets inside @lisp
+% phr: changed space to \null, to avoid overfull hbox problems.
+{\obeyspaces%
+\gdef\lisppar{\null\endgraf}}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces %
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical.
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace % single space lines
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+\def\Elisp{\endgroup\afterenvbreak}%
+
+\def\lisp{\begingroup
+ \nonfillstart
+ \def\Elisp{\endgroup\afterenvbreak}%
+ \tt
+ \rawbackslash % output the \ character from the current font
+ \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\Elisp\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\Elisp\endgroup}\lisp}
+
+% Macro for 9 pt. examples, necessary to print with 5" lines. From
+% Pavel@xerox. This is not used for @smallexamples unless the
+% @smallbook command is given.
+%
+\def\smalllispx{\begingroup
+ \nonfillstart
+ \def\Esmalllisp{\endgroup\afterenvbreak}%
+ %
+ % Smaller interline space and fonts for small examples.
+ \baselineskip 10pt
+ \indexfonts \tt
+ \rawbackslash % output the \ character from the current font
+ \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \def\Edisplay{\endgroup\afterenvbreak}%
+ \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \def\Eformat{\endgroup\afterenvbreak}
+ \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \def\Eflushleft{\endgroup\afterenvbreak}%
+ \gobble
+}
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \def\Eflushright{\endgroup\afterenvbreak}%
+ \advance\leftskip by 0pt plus 1fill
+ \gobble}
+
+% @quotation does normal linebreaking and narrows the margins.
+%
+\def\quotation{%
+\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\def\Equotation{\par\endgroup\afterenvbreak}%
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\advance \rightskip by \lispnarrowing
+\exdentamount=\lispnarrowing
+\let\nonarrowing=\relax
+\fi}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+\def\defvrparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#4}}}
+
+% This seems to work right in all cases.
+\let\deftpparsebody=\defvrparsebody
+% This fails to work. When given `@deftp {Data Type} foo_t',
+% it thinks the type name is just `f'.
+%%% This is the same as all the others except for the last line. We need
+%%% to parse the arguments differently for @deftp, since the ``attributes''
+%%% there are optional.
+%%%
+%%\def\deftpparsebody #1#2#3#4 {\begingroup\inENV %
+%%\medbreak %
+%%% Define the end token that this defining construct specifies
+%%% so that it will exit this group.
+%%\def#1{\endgraf\endgroup\medbreak}%
+%%\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+%%\parindent=0in
+%%\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+%%\exdentamount=\defbodyindent
+%%\begingroup\obeylines\parsetpheaderline{#3{#4}}}
+
+%%{\obeylines %
+%% % Parse the type name and any attributes (field names, etc.).
+%% % #1 is the beginning of the macro call that will produce the output,
+%% % i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody.
+%% % #2 is the type name, e.g., `struct termios'.
+%% % #3 is the (possibly empty) attribute list.
+%% %
+%% \gdef\parsetpheaderline#1#2#3^^M{%
+%% \endgroup % Started in \deftpparsebody.
+%% %
+%% % If the attribute list is in fact empty, there will be no space after
+%% % #2; so we can't put a space in our TeX parameter list. But if it
+%% % isn't empty, then #3 will begin with an unwanted space.
+%% \def\theargs{\ignorespaces #3}%
+%% %
+%% % Call the macro to produce the output.
+%% #1{#2}\theargs %
+%% }%
+%%}
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names. Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss. Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed.
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.1}
+\def\strutheightpercent{.71}
+\def\strutdepthpercent{.29}
+%
+\def\setleading#1{%
+ \baselineskip = #1\relax
+ \normalbaselineskip = \baselineskip
+ \lineskip = \lineskipfactor\baselineskip
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\setleading{15pt}
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+\else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+
+% These values for secheadingskip and subsecheadingskip are
+% experiments. RJC 7 Aug 1992
+\global\secheadingskip = 17pt plus 6pt minus 3pt
+\global\subsecheadingskip = 14pt plus 6pt minus 3pt
+
+\global\lispnarrowing = 0.3in
+\setleading{12pt}
+\advance\topskip by -1cm
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+% \lvvmode is equivalent in function to \leavevmode.
+% Using \leavevmode runs into trouble when written out to
+% an index file due to the expansion of \leavevmode into ``\unhbox
+% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
+% magic tricks with @.
+\def\lvvmode{\vbox to 0pt{}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/gnu/libexec/Makefile b/gnu/libexec/Makefile
index f90dec26d165..47bd3abccba1 100644
--- a/gnu/libexec/Makefile
+++ b/gnu/libexec/Makefile
@@ -1,4 +1,4 @@
-# $Id$
+# Makefile,v 1.1 1994/01/30 01:08:18 rgrimes Exp
SUBDIR= uucp
diff --git a/gnu/libexec/Makefile.inc b/gnu/libexec/Makefile.inc
index 1ac3dc7c91c8..461eb5c3e7a5 100644
--- a/gnu/libexec/Makefile.inc
+++ b/gnu/libexec/Makefile.inc
@@ -1,3 +1,3 @@
-# $Id$
+# Makefile.inc,v 1.1 1994/01/30 01:08:21 rgrimes Exp
BINDIR?= /usr/libexec
diff --git a/gnu/libexec/uucp/Makefile b/gnu/libexec/uucp/Makefile
index 9b5dcced6f9e..e463faed1438 100644
--- a/gnu/libexec/uucp/Makefile
+++ b/gnu/libexec/uucp/Makefile
@@ -1,5 +1,5 @@
# This is the Makefile for Taylor UUCP
-# $Id: Makefile,v 1.1 1993/08/05 18:22:22 conklin Exp $
+# Makefile,v 1.2 1993/10/14 12:17:57 rgrimes Exp
SUBDIR= libunix libuucp libuuconf \
cu sample \
diff --git a/gnu/libexec/uucp/common_sources/chat.c b/gnu/libexec/uucp/common_sources/chat.c
index 2fbea0a05587..3257b6e18a99 100644
--- a/gnu/libexec/uucp/common_sources/chat.c
+++ b/gnu/libexec/uucp/common_sources/chat.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char chat_rcsid[] = "$Id: chat.c,v 1.42 1994/01/30 21:02:56 ian Rel $";
+const char chat_rcsid[] = "chat.c,v 1.2 1994/05/07 18:08:33 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/common_sources/conn.c b/gnu/libexec/uucp/common_sources/conn.c
index 6598f1093ee8..1ea7b0166ae4 100644
--- a/gnu/libexec/uucp/common_sources/conn.c
+++ b/gnu/libexec/uucp/common_sources/conn.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char conn_rcsid[] = "$Id: conn.c,v 1.13 1994/03/24 01:41:02 ian Rel $";
+const char conn_rcsid[] = "conn.c,v 1.2 1994/05/07 18:08:38 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/common_sources/copy.c b/gnu/libexec/uucp/common_sources/copy.c
index e1b974d159e4..a19f9e64e35c 100644
--- a/gnu/libexec/uucp/common_sources/copy.c
+++ b/gnu/libexec/uucp/common_sources/copy.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char copy_rcsid[] = "$Id: copy.c,v 1.13 1994/01/30 21:01:46 ian Rel $";
+const char copy_rcsid[] = "copy.c,v 1.2 1994/05/07 18:08:42 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/common_sources/log.c b/gnu/libexec/uucp/common_sources/log.c
index 1544bc93d292..2170e49726f2 100644
--- a/gnu/libexec/uucp/common_sources/log.c
+++ b/gnu/libexec/uucp/common_sources/log.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char log_rcsid[] = "$Id: log.c,v 1.54 1994/04/17 02:28:24 ian Rel $";
+const char log_rcsid[] = "log.c,v 1.2 1994/05/07 18:08:47 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/common_sources/prot.c b/gnu/libexec/uucp/common_sources/prot.c
index 0a6cbc8da1a7..ef4fdf9d2f12 100644
--- a/gnu/libexec/uucp/common_sources/prot.c
+++ b/gnu/libexec/uucp/common_sources/prot.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char prot_rcsid[] = "$Id: prot.c,v 1.30 1994/04/14 03:07:56 ian Rel $";
+const char prot_rcsid[] = "prot.c,v 1.2 1994/05/07 18:08:51 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/common_sources/tcp.c b/gnu/libexec/uucp/common_sources/tcp.c
index 4efded948c29..35c368430aa8 100644
--- a/gnu/libexec/uucp/common_sources/tcp.c
+++ b/gnu/libexec/uucp/common_sources/tcp.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char tcp_rcsid[] = "$Id: tcp.c,v 1.34 1994/01/30 21:01:46 ian Rel $";
+const char tcp_rcsid[] = "tcp.c,v 1.2 1994/05/07 18:09:01 ache Exp";
#endif
#if HAVE_TCP
diff --git a/gnu/libexec/uucp/common_sources/tli.c b/gnu/libexec/uucp/common_sources/tli.c
index c36399853046..378ea05e3bc1 100644
--- a/gnu/libexec/uucp/common_sources/tli.c
+++ b/gnu/libexec/uucp/common_sources/tli.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char tli_rcsid[] = "$Id: tli.c,v 1.15 1994/01/30 20:59:40 ian Rel $";
+const char tli_rcsid[] = "tli.c,v 1.2 1994/05/07 18:09:03 ache Exp";
#endif
#if HAVE_TLI
diff --git a/gnu/libexec/uucp/common_sources/util.c b/gnu/libexec/uucp/common_sources/util.c
index 78a94558cf88..bcc532b6d11e 100644
--- a/gnu/libexec/uucp/common_sources/util.c
+++ b/gnu/libexec/uucp/common_sources/util.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char util_rcsid[] = "$Id: util.c,v 1.6 1994/01/30 20:59:40 ian Rel $";
+const char util_rcsid[] = "util.c,v 1.2 1994/05/07 18:09:07 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/contrib/Makefile.uurt b/gnu/libexec/uucp/contrib/Makefile.uurt
index e97ff7ed2ff0..c523973b67fd 100644
--- a/gnu/libexec/uucp/contrib/Makefile.uurt
+++ b/gnu/libexec/uucp/contrib/Makefile.uurt
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.4 1994/04/14 17:47:52 kdburg Exp $
+# Makefile.uurt,v 1.2 1994/05/07 18:09:19 ache Exp
# Makefile for uurate 1.10
#
diff --git a/gnu/libexec/uucp/contrib/uupoll.shar b/gnu/libexec/uucp/contrib/uupoll.shar
index a03a0737b1f2..e468cb3d343c 100644
--- a/gnu/libexec/uucp/contrib/uupoll.shar
+++ b/gnu/libexec/uucp/contrib/uupoll.shar
@@ -493,10 +493,13 @@ X not scan the uucico log.
X
X
#if !defined(lint)
-static char rcsid[] = "$Id: autopoll.c,v 2.8 1994/04/14 17:22:54 kdburg Rel $";
+static char rcsid[] = "uupoll.shar,v 1.1 1994/05/07 18:09:32 ache Exp";
#endif /* not lint */
X
-/* $Log: autopoll.c,v $
+/* uupoll.shar,v
+# Revision 1.1 1994/05/07 18:09:32 ache
+# Upgrade to version 1.05
+#
X * Revision 2.8 1994/04/14 17:22:54 kdburg
X * corrected misspelled AT_OPTION
X *
@@ -1628,8 +1631,11 @@ sed 's/^X//' << 'SHAR_EOF' > 'uupoll/conf.h' &&
#ifndef CONF
X #define CONF
X
-/* $Id: conf.h,v 1.9 1994/04/14 17:24:58 kdburg Rel $ */
-/* $Log: conf.h,v $
+/* uupoll.shar,v 1.1 1994/05/07 18:09:32 ache Exp */
+/* uupoll.shar,v
+# Revision 1.1 1994/05/07 18:09:32 ache
+# Upgrade to version 1.05
+#
X * Revision 1.9 1994/04/14 17:24:58 kdburg
X * added comment to the AT_OPTION
X *
@@ -1986,10 +1992,13 @@ X - No alias expansion is done on the given names.
*/
X
#if !defined(lint)
-static char rcsid[] = "$Id: uupoll.c,v 2.7 1994/04/14 17:22:04 kdburg Rel $";
+static char rcsid[] = "uupoll.shar,v 1.1 1994/05/07 18:09:32 ache Exp";
#endif /* not lint */
X
-/* $Log: uupoll.c,v $
+/* uupoll.shar,v
+# Revision 1.1 1994/05/07 18:09:32 ache
+# Upgrade to version 1.05
+#
X * Revision 2.7 1994/04/14 17:22:04 kdburg
X * major rework done
X *
diff --git a/gnu/libexec/uucp/contrib/uurate.c b/gnu/libexec/uucp/contrib/uurate.c
index 1ff9afb829b8..3b4a8f567d68 100644
--- a/gnu/libexec/uucp/contrib/uurate.c
+++ b/gnu/libexec/uucp/contrib/uurate.c
@@ -83,7 +83,10 @@
* - reapplied patch by Scott Boyd <scott@futures.com> that I did not
* get knowledge of
*/
-/* $Log: uurate.c,v $
+/* uurate.c,v
+ * Revision 1.2 1994/05/07 18:09:35 ache
+ * Upgrade to version 1.05
+ *
* Revision 1.15 1994/04/07 21:47:11 kdburg
* printed 'no data avail' while there was data; layout chnaged
* (cosmetic only)
@@ -139,7 +142,7 @@
* */
char version[] = "@(#) Taylor UUCP Log File Summary Filter, Version 1.2.2";
-static char rcsid[] = "$Id: uurate.c,v 1.15 1994/04/07 21:47:11 kdburg Rel $";
+static char rcsid[] = "uurate.c,v 1.2 1994/05/07 18:09:35 ache Exp";
#include <ctype.h> /* Character Classification */
#include <math.h>
#include "uucp.h"
diff --git a/gnu/libexec/uucp/contrib/uurate.man b/gnu/libexec/uucp/contrib/uurate.man
index e12a4e1c0a84..4280989ccc5c 100644
--- a/gnu/libexec/uucp/contrib/uurate.man
+++ b/gnu/libexec/uucp/contrib/uurate.man
@@ -1,4 +1,4 @@
-''' $Id: uurate.man,v 1.4 1993/09/28 17:38:31 kdburg Rel $
+''' uurate.man,v 1.2 1994/05/07 18:09:37 ache Exp
.TH uurate 1
.SH NAME
uurate \- Report Taylor UUCP statistics
diff --git a/gnu/libexec/uucp/contrib/uusnap.c b/gnu/libexec/uucp/contrib/uusnap.c
index 123741cbff28..d6cd8d54e867 100644
--- a/gnu/libexec/uucp/contrib/uusnap.c
+++ b/gnu/libexec/uucp/contrib/uusnap.c
@@ -25,7 +25,7 @@
#include "uucp.h"
#if USE_RCS_ID
-char uusnap_rcsid[] = "$Id: uusnap.c,v 1.9 92/05/05 22:51:50 hwr Exp Locker: hwr $";
+char uusnap_rcsid[] = "uusnap.c,v 1.2 1994/05/07 18:09:40 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/cu/Makefile b/gnu/libexec/uucp/cu/Makefile
index 53343cecf529..03badfa7e833 100644
--- a/gnu/libexec/uucp/cu/Makefile
+++ b/gnu/libexec/uucp/cu/Makefile
@@ -1,5 +1,5 @@
# Makefile for cu
-# $Id: Makefile,v 1.2 1994/05/31 05:23:39 ache Exp $
+# Makefile,v 1.3 1994/05/31 07:47:39 ache Exp
BINDIR= $(bindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/cu/cu.1 b/gnu/libexec/uucp/cu/cu.1
index 65d94360bcbc..07fd00d58d77 100644
--- a/gnu/libexec/uucp/cu/cu.1
+++ b/gnu/libexec/uucp/cu/cu.1
@@ -1,4 +1,4 @@
-''' $Id: cu.1,v 1.4 1993/07/20 01:59:03 ian Rel $
+''' cu.1,v 1.2 1994/05/07 18:09:51 ache Exp
.TH cu 1 "Taylor UUCP 1.05"
.SH NAME
cu \- Call up another system
diff --git a/gnu/libexec/uucp/cu/cu.c b/gnu/libexec/uucp/cu/cu.c
index 54516b62dd34..8b5ce87ac534 100644
--- a/gnu/libexec/uucp/cu/cu.c
+++ b/gnu/libexec/uucp/cu/cu.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char cu_rcsid[] = "$Id: cu.c,v 1.2 1994/05/07 18:09:54 ache Exp $";
+const char cu_rcsid[] = "cu.c,v 1.3 1994/10/02 23:10:39 ache Exp";
#endif
#include "cu.h"
diff --git a/gnu/libexec/uucp/libunix/Makefile b/gnu/libexec/uucp/libunix/Makefile
index 9da39759e156..c0bc2f339090 100644
--- a/gnu/libexec/uucp/libunix/Makefile
+++ b/gnu/libexec/uucp/libunix/Makefile
@@ -1,5 +1,5 @@
# This subdirectory contains Unix specific support functions.
-# $Id: Makefile,v 1.1 1993/08/05 18:23:34 conklin Exp $
+# Makefile,v 1.2 1994/05/07 18:10:03 ache Exp
LIB= unix
SRCS = access.c addbas.c app3.c app4.c basnam.c bytfre.c corrup.c \
diff --git a/gnu/libexec/uucp/libunix/cusub.c b/gnu/libexec/uucp/libunix/cusub.c
index bf947a8ee8ef..a21da93ab918 100644
--- a/gnu/libexec/uucp/libunix/cusub.c
+++ b/gnu/libexec/uucp/libunix/cusub.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char cusub_rcsid[] = "$Id: cusub.c,v 1.19 1994/01/30 21:09:20 ian Rel $";
+const char cusub_rcsid[] = "cusub.c,v 1.2 1994/05/07 18:10:14 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/lock.c b/gnu/libexec/uucp/libunix/lock.c
index 73ce976feda6..a10322b2183b 100644
--- a/gnu/libexec/uucp/libunix/lock.c
+++ b/gnu/libexec/uucp/libunix/lock.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char lock_rcsid[] = "$Id: lock.c,v 1.15 1994/01/30 21:09:20 ian Rel $";
+const char lock_rcsid[] = "lock.c,v 1.2 1994/05/07 18:10:40 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/picksb.c b/gnu/libexec/uucp/libunix/picksb.c
index 4fbd965968b5..1591dc559307 100644
--- a/gnu/libexec/uucp/libunix/picksb.c
+++ b/gnu/libexec/uucp/libunix/picksb.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char picksb_rcsid[] = "$Id: picksb.c,v 1.8 1994/01/30 21:09:20 ian Rel $";
+const char picksb_rcsid[] = "picksb.c,v 1.2 1994/05/07 18:10:54 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/pipe.c b/gnu/libexec/uucp/libunix/pipe.c
index 69763f65177d..bb9dd40a282a 100644
--- a/gnu/libexec/uucp/libunix/pipe.c
+++ b/gnu/libexec/uucp/libunix/pipe.c
@@ -27,7 +27,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char pipe_rcsid[] = "$Id: pipe.c,v 1.4 1994/03/25 04:09:30 ian Rel $";
+const char pipe_rcsid[] = "pipe.c,v 1.1 1994/05/07 18:10:56 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/serial.c b/gnu/libexec/uucp/libunix/serial.c
index 4bee3bf4d7fb..ed2a765dc5f5 100644
--- a/gnu/libexec/uucp/libunix/serial.c
+++ b/gnu/libexec/uucp/libunix/serial.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char serial_rcsid[] = "$Id: serial.c,v 1.56 1994/04/13 01:57:05 ian Rel $";
+const char serial_rcsid[] = "serial.c,v 1.4 1994/05/07 18:11:09 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/spool.c b/gnu/libexec/uucp/libunix/spool.c
index 2244f0365613..3420e6d425aa 100644
--- a/gnu/libexec/uucp/libunix/spool.c
+++ b/gnu/libexec/uucp/libunix/spool.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char spool_rcsid[] = "$Id: spool.c,v 1.8 1994/01/30 21:09:20 ian Rel $";
+const char spool_rcsid[] = "spool.c,v 1.2 1994/05/07 18:11:24 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/statsb.c b/gnu/libexec/uucp/libunix/statsb.c
index a57d2a3be784..eece0a5ea12b 100644
--- a/gnu/libexec/uucp/libunix/statsb.c
+++ b/gnu/libexec/uucp/libunix/statsb.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char statsb_rcsid[] = "$Id: statsb.c,v 1.17 1994/04/10 22:06:10 ian Rel $";
+const char statsb_rcsid[] = "statsb.c,v 1.2 1994/05/07 18:11:29 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/work.c b/gnu/libexec/uucp/libunix/work.c
index 0381c20d6601..2b6367e16eb8 100644
--- a/gnu/libexec/uucp/libunix/work.c
+++ b/gnu/libexec/uucp/libunix/work.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char work_rcsid[] = "$Id: work.c,v 1.15 1994/01/30 21:09:20 ian Rel $";
+const char work_rcsid[] = "work.c,v 1.2 1994/05/07 18:11:41 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/xqtfil.c b/gnu/libexec/uucp/libunix/xqtfil.c
index d0ca75779326..d1b0860afc46 100644
--- a/gnu/libexec/uucp/libunix/xqtfil.c
+++ b/gnu/libexec/uucp/libunix/xqtfil.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char xqtfil_rcsid[] = "$Id: xqtfil.c,v 1.7 1994/01/30 21:09:20 ian Rel $";
+const char xqtfil_rcsid[] = "xqtfil.c,v 1.2 1994/05/07 18:11:42 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libunix/xqtsub.c b/gnu/libexec/uucp/libunix/xqtsub.c
index 62f4e8937702..32c9f0197171 100644
--- a/gnu/libexec/uucp/libunix/xqtsub.c
+++ b/gnu/libexec/uucp/libunix/xqtsub.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char xqtsub_rcsid[] = "$Id: xqtsub.c,v 1.14 1994/01/30 21:09:20 ian Rel $";
+const char xqtsub_rcsid[] = "xqtsub.c,v 1.2 1994/05/07 18:11:43 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/libuuconf/Makefile b/gnu/libexec/uucp/libuuconf/Makefile
index 7b7f3ece4149..7394ec7ad6bd 100644
--- a/gnu/libexec/uucp/libuuconf/Makefile
+++ b/gnu/libexec/uucp/libuuconf/Makefile
@@ -1,5 +1,5 @@
# This is the Makefile for the Taylor UUCP uuconf library
-# $Id: Makefile,v 1.1 1993/08/05 18:24:52 conklin Exp $
+# Makefile,v 1.2 1994/05/07 18:11:49 ache Exp
LIB= uuconf
SRCS = addblk.c addstr.c allblk.c alloc.c base.c bool.c callin.c \
diff --git a/gnu/libexec/uucp/libuuconf/addblk.c b/gnu/libexec/uucp/libuuconf/addblk.c
index 66ed0956a1ca..ad98f0ceb8fa 100644
--- a/gnu/libexec/uucp/libuuconf/addblk.c
+++ b/gnu/libexec/uucp/libuuconf/addblk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_addblk_rcsid[] = "$Id: addblk.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_addblk_rcsid[] = "addblk.c,v 1.2 1994/05/07 18:11:51 ache Exp";
#endif
#include "alloc.h"
diff --git a/gnu/libexec/uucp/libuuconf/addstr.c b/gnu/libexec/uucp/libuuconf/addstr.c
index be372b24bd89..46729801b1b4 100644
--- a/gnu/libexec/uucp/libuuconf/addstr.c
+++ b/gnu/libexec/uucp/libuuconf/addstr.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_addstr_rcsid[] = "$Id: addstr.c,v 1.5 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_addstr_rcsid[] = "addstr.c,v 1.2 1994/05/07 18:11:52 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/allblk.c b/gnu/libexec/uucp/libuuconf/allblk.c
index 54d80b02e4fd..8c9c98668cb6 100644
--- a/gnu/libexec/uucp/libuuconf/allblk.c
+++ b/gnu/libexec/uucp/libuuconf/allblk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_allblk_rcsid[] = "$Id: allblk.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_allblk_rcsid[] = "allblk.c,v 1.2 1994/05/07 18:11:53 ache Exp";
#endif
#include "alloc.h"
diff --git a/gnu/libexec/uucp/libuuconf/alloc.c b/gnu/libexec/uucp/libuuconf/alloc.c
index 8bd86dc20b0a..4d3be6337497 100644
--- a/gnu/libexec/uucp/libuuconf/alloc.c
+++ b/gnu/libexec/uucp/libuuconf/alloc.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_alloc_rcsid[] = "$Id: alloc.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_alloc_rcsid[] = "alloc.c,v 1.2 1994/05/07 18:11:54 ache Exp";
#endif
#include "alloc.h"
diff --git a/gnu/libexec/uucp/libuuconf/base.c b/gnu/libexec/uucp/libuuconf/base.c
index e48e5553cdb3..08f77de8b387 100644
--- a/gnu/libexec/uucp/libuuconf/base.c
+++ b/gnu/libexec/uucp/libuuconf/base.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_base_rcsid[] = "$Id: base.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_base_rcsid[] = "base.c,v 1.2 1994/05/07 18:11:57 ache Exp";
#endif
/* This turns a cmdtab_offset table into a uuconf_cmdtab table. Each
diff --git a/gnu/libexec/uucp/libuuconf/bool.c b/gnu/libexec/uucp/libuuconf/bool.c
index 73072a3e6c6f..36a4c2f0f693 100644
--- a/gnu/libexec/uucp/libuuconf/bool.c
+++ b/gnu/libexec/uucp/libuuconf/bool.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_bool_rcsid[] = "$Id: bool.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_bool_rcsid[] = "bool.c,v 1.2 1994/05/07 18:11:58 ache Exp";
#endif
/* Parse a boolean string into a variable. This is called by
diff --git a/gnu/libexec/uucp/libuuconf/callin.c b/gnu/libexec/uucp/libuuconf/callin.c
index fd58b18f98ff..c2d1e5ec4ad0 100644
--- a/gnu/libexec/uucp/libuuconf/callin.c
+++ b/gnu/libexec/uucp/libuuconf/callin.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_callin_rcsid[] = "$Id: callin.c,v 1.8 1994/03/29 01:18:20 ian Rel $";
+const char _uuconf_callin_rcsid[] = "callin.c,v 1.2 1994/05/07 18:11:58 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/calout.c b/gnu/libexec/uucp/libuuconf/calout.c
index 4f893946f336..469693ce14ae 100644
--- a/gnu/libexec/uucp/libuuconf/calout.c
+++ b/gnu/libexec/uucp/libuuconf/calout.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_calout_rcsid[] = "$Id: calout.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_calout_rcsid[] = "calout.c,v 1.2 1994/05/07 18:12:00 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/chatc.c b/gnu/libexec/uucp/libuuconf/chatc.c
index 6b5faeda5a5a..9fb87d21e017 100644
--- a/gnu/libexec/uucp/libuuconf/chatc.c
+++ b/gnu/libexec/uucp/libuuconf/chatc.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_chatc_rcsid[] = "$Id: chatc.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_chatc_rcsid[] = "chatc.c,v 1.2 1994/05/07 18:12:01 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/libuuconf/cmdarg.c b/gnu/libexec/uucp/libuuconf/cmdarg.c
index e08c499c73fa..2a2909127400 100644
--- a/gnu/libexec/uucp/libuuconf/cmdarg.c
+++ b/gnu/libexec/uucp/libuuconf/cmdarg.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_cmdarg_rcsid[] = "$Id: cmdarg.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_cmdarg_rcsid[] = "cmdarg.c,v 1.2 1994/05/07 18:12:02 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/libuuconf/cmdfil.c b/gnu/libexec/uucp/libuuconf/cmdfil.c
index 6d6dd72f6b58..8f343e9e60ad 100644
--- a/gnu/libexec/uucp/libuuconf/cmdfil.c
+++ b/gnu/libexec/uucp/libuuconf/cmdfil.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_cmdfil_rcsid[] = "$Id: cmdfil.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_cmdfil_rcsid[] = "cmdfil.c,v 1.2 1994/05/07 18:12:03 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/cmdlin.c b/gnu/libexec/uucp/libuuconf/cmdlin.c
index 736dd0ca8b1b..b3c637077c40 100644
--- a/gnu/libexec/uucp/libuuconf/cmdlin.c
+++ b/gnu/libexec/uucp/libuuconf/cmdlin.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_cmdlin_rcsid[] = "$Id: cmdlin.c,v 1.2 1994/05/07 18:12:04 ache Exp $";
+const char _uuconf_cmdlin_rcsid[] = "cmdlin.c,v 1.3 1994/10/22 03:51:34 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/debfil.c b/gnu/libexec/uucp/libuuconf/debfil.c
index b4fd46cb7e4e..2d1ee9c275e4 100644
--- a/gnu/libexec/uucp/libuuconf/debfil.c
+++ b/gnu/libexec/uucp/libuuconf/debfil.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_debfil_rcsid[] = "$Id: debfil.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_debfil_rcsid[] = "debfil.c,v 1.2 1994/05/07 18:12:05 ache Exp";
#endif
/* Get the name of the UUCP debugging file. */
diff --git a/gnu/libexec/uucp/libuuconf/deblev.c b/gnu/libexec/uucp/libuuconf/deblev.c
index 926ab52652e2..f481ba15beee 100644
--- a/gnu/libexec/uucp/libuuconf/deblev.c
+++ b/gnu/libexec/uucp/libuuconf/deblev.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_deblev_rcsid[] = "$Id: deblev.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_deblev_rcsid[] = "deblev.c,v 1.2 1994/05/07 18:12:06 ache Exp";
#endif
/* Get the UUCP debugging level. */
diff --git a/gnu/libexec/uucp/libuuconf/diacod.c b/gnu/libexec/uucp/libuuconf/diacod.c
index f90568c2c903..e1184173f619 100644
--- a/gnu/libexec/uucp/libuuconf/diacod.c
+++ b/gnu/libexec/uucp/libuuconf/diacod.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_diacod_rcsid[] = "$Id: diacod.c,v 1.7 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_diacod_rcsid[] = "diacod.c,v 1.2 1994/05/07 18:12:07 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/dial.c b/gnu/libexec/uucp/libuuconf/dial.c
index 0709d123944e..552f7b3ef568 100644
--- a/gnu/libexec/uucp/libuuconf/dial.c
+++ b/gnu/libexec/uucp/libuuconf/dial.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_dial_rcsid[] = "$Id: dial.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_dial_rcsid[] = "dial.c,v 1.2 1994/05/07 18:12:08 ache Exp";
#endif
/* Find a dialer by name. */
diff --git a/gnu/libexec/uucp/libuuconf/diasub.c b/gnu/libexec/uucp/libuuconf/diasub.c
index b87bde59620c..87c0cd9b2a9b 100644
--- a/gnu/libexec/uucp/libuuconf/diasub.c
+++ b/gnu/libexec/uucp/libuuconf/diasub.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_diasub_rcsid[] = "$Id: diasub.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_diasub_rcsid[] = "diasub.c,v 1.2 1994/05/07 18:12:09 ache Exp";
#endif
/* Clear the information in a dialer. */
diff --git a/gnu/libexec/uucp/libuuconf/dnams.c b/gnu/libexec/uucp/libuuconf/dnams.c
index a4985343a474..ea52c64f0737 100644
--- a/gnu/libexec/uucp/libuuconf/dnams.c
+++ b/gnu/libexec/uucp/libuuconf/dnams.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_dnams_rcsid[] = "$Id: dnams.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_dnams_rcsid[] = "dnams.c,v 1.2 1994/05/07 18:12:10 ache Exp";
#endif
/* Get all known dialer names. */
diff --git a/gnu/libexec/uucp/libuuconf/errno.c b/gnu/libexec/uucp/libuuconf/errno.c
index d0e1cac68da1..0797deabd25f 100644
--- a/gnu/libexec/uucp/libuuconf/errno.c
+++ b/gnu/libexec/uucp/libuuconf/errno.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_errno_rcsid[] = "$Id: errno.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_errno_rcsid[] = "errno.c,v 1.2 1994/05/07 18:12:11 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/errstr.c b/gnu/libexec/uucp/libuuconf/errstr.c
index 40c97e81b95b..31d3a9c8b9c7 100644
--- a/gnu/libexec/uucp/libuuconf/errstr.c
+++ b/gnu/libexec/uucp/libuuconf/errstr.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_errstr_rcsid[] = "$Id: errstr.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_errstr_rcsid[] = "errstr.c,v 1.2 1994/05/07 18:12:12 ache Exp";
#endif
static char *zeprint_num P((char *zbuf, size_t cbuf, int ival));
diff --git a/gnu/libexec/uucp/libuuconf/filnam.c b/gnu/libexec/uucp/libuuconf/filnam.c
index 4e126b4bce03..c810fdfef36e 100644
--- a/gnu/libexec/uucp/libuuconf/filnam.c
+++ b/gnu/libexec/uucp/libuuconf/filnam.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_filnam_rcsid[] = "$Id: filnam.c,v 1.4 1994/03/30 04:00:35 ian Rel $";
+const char _uuconf_filnam_rcsid[] = "filnam.c,v 1.2 1994/05/07 18:12:13 ache Exp";
#endif
/* Return the saved file name. */
diff --git a/gnu/libexec/uucp/libuuconf/freblk.c b/gnu/libexec/uucp/libuuconf/freblk.c
index 894c26a9f0a6..b56d3da6b17d 100644
--- a/gnu/libexec/uucp/libuuconf/freblk.c
+++ b/gnu/libexec/uucp/libuuconf/freblk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_freblk_rcsid[] = "$Id: freblk.c,v 1.5 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_freblk_rcsid[] = "freblk.c,v 1.2 1994/05/07 18:12:14 ache Exp";
#endif
#include "alloc.h"
diff --git a/gnu/libexec/uucp/libuuconf/fredia.c b/gnu/libexec/uucp/libuuconf/fredia.c
index a2bf8a461633..78609da5d6cc 100644
--- a/gnu/libexec/uucp/libuuconf/fredia.c
+++ b/gnu/libexec/uucp/libuuconf/fredia.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_fredia_rcsid[] = "$Id: fredia.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_fredia_rcsid[] = "fredia.c,v 1.2 1994/05/07 18:12:15 ache Exp";
#endif
/* Free the memory allocated for a dialer. */
diff --git a/gnu/libexec/uucp/libuuconf/free.c b/gnu/libexec/uucp/libuuconf/free.c
index b8204fce50bb..6da8da6ba78f 100644
--- a/gnu/libexec/uucp/libuuconf/free.c
+++ b/gnu/libexec/uucp/libuuconf/free.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_free_rcsid[] = "$Id: free.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_free_rcsid[] = "free.c,v 1.2 1994/05/07 18:12:17 ache Exp";
#endif
#include "alloc.h"
diff --git a/gnu/libexec/uucp/libuuconf/freprt.c b/gnu/libexec/uucp/libuuconf/freprt.c
index d7e58ae9515c..8b32b1aff4d8 100644
--- a/gnu/libexec/uucp/libuuconf/freprt.c
+++ b/gnu/libexec/uucp/libuuconf/freprt.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_freprt_rcsid[] = "$Id: freprt.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_freprt_rcsid[] = "freprt.c,v 1.2 1994/05/07 18:12:18 ache Exp";
#endif
/* Free the memory allocated for a port. */
diff --git a/gnu/libexec/uucp/libuuconf/fresys.c b/gnu/libexec/uucp/libuuconf/fresys.c
index 135703159a7b..a688dda0ec15 100644
--- a/gnu/libexec/uucp/libuuconf/fresys.c
+++ b/gnu/libexec/uucp/libuuconf/fresys.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_fresys_rcsid[] = "$Id: fresys.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_fresys_rcsid[] = "fresys.c,v 1.2 1994/05/07 18:12:19 ache Exp";
#endif
/* Free the memory allocated for a system. */
diff --git a/gnu/libexec/uucp/libuuconf/grdcmp.c b/gnu/libexec/uucp/libuuconf/grdcmp.c
index af5f26acc9a1..9679fe1107ba 100644
--- a/gnu/libexec/uucp/libuuconf/grdcmp.c
+++ b/gnu/libexec/uucp/libuuconf/grdcmp.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_grdcmp_rcsid[] = "$Id: grdcmp.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_grdcmp_rcsid[] = "grdcmp.c,v 1.2 1994/05/07 18:12:20 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/libuuconf/hdial.c b/gnu/libexec/uucp/libuuconf/hdial.c
index 909bdb222219..5b454cea4bbc 100644
--- a/gnu/libexec/uucp/libuuconf/hdial.c
+++ b/gnu/libexec/uucp/libuuconf/hdial.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hdial_rcsid[] = "$Id: hdial.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hdial_rcsid[] = "hdial.c,v 1.2 1994/05/07 18:12:20 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hdnams.c b/gnu/libexec/uucp/libuuconf/hdnams.c
index 5051a7fbe9c8..1a6d681753bb 100644
--- a/gnu/libexec/uucp/libuuconf/hdnams.c
+++ b/gnu/libexec/uucp/libuuconf/hdnams.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hdnams_rcsid[] = "$Id: hdnams.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hdnams_rcsid[] = "hdnams.c,v 1.2 1994/05/07 18:12:21 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hinit.c b/gnu/libexec/uucp/libuuconf/hinit.c
index 06155d9c5d67..3faea7bb8d92 100644
--- a/gnu/libexec/uucp/libuuconf/hinit.c
+++ b/gnu/libexec/uucp/libuuconf/hinit.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hinit_rcsid[] = "$Id: hinit.c,v 1.6 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hinit_rcsid[] = "hinit.c,v 1.2 1994/05/07 18:12:23 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hlocnm.c b/gnu/libexec/uucp/libuuconf/hlocnm.c
index d94ce778c23a..4f08a5d17692 100644
--- a/gnu/libexec/uucp/libuuconf/hlocnm.c
+++ b/gnu/libexec/uucp/libuuconf/hlocnm.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hlocnm_rcsid[] = "$Id: hlocnm.c,v 1.5 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hlocnm_rcsid[] = "hlocnm.c,v 1.2 1994/05/07 18:12:23 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hport.c b/gnu/libexec/uucp/libuuconf/hport.c
index fb0cd9564673..83b5d36985c6 100644
--- a/gnu/libexec/uucp/libuuconf/hport.c
+++ b/gnu/libexec/uucp/libuuconf/hport.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hport_rcsid[] = "$Id: hport.c,v 1.11 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hport_rcsid[] = "hport.c,v 1.2 1994/05/07 18:12:25 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hrmunk.c b/gnu/libexec/uucp/libuuconf/hrmunk.c
index 1e39b8c4a585..d76c03eb72c6 100644
--- a/gnu/libexec/uucp/libuuconf/hrmunk.c
+++ b/gnu/libexec/uucp/libuuconf/hrmunk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hrmunk_rcsid[] = "$Id: hrmunk.c,v 1.2 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hrmunk_rcsid[] = "hrmunk.c,v 1.2 1994/05/07 18:12:26 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hsinfo.c b/gnu/libexec/uucp/libuuconf/hsinfo.c
index 6c92b3b8317a..26663a63a06b 100644
--- a/gnu/libexec/uucp/libuuconf/hsinfo.c
+++ b/gnu/libexec/uucp/libuuconf/hsinfo.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hsinfo_rcsid[] = "$Id: hsinfo.c,v 1.10 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hsinfo_rcsid[] = "hsinfo.c,v 1.2 1994/05/07 18:12:27 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hsnams.c b/gnu/libexec/uucp/libuuconf/hsnams.c
index 73f3dbb2ab27..cce70535721b 100644
--- a/gnu/libexec/uucp/libuuconf/hsnams.c
+++ b/gnu/libexec/uucp/libuuconf/hsnams.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hsnams_rcsid[] = "$Id: hsnams.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hsnams_rcsid[] = "hsnams.c,v 1.2 1994/05/07 18:12:28 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/hsys.c b/gnu/libexec/uucp/libuuconf/hsys.c
index 16be3b9b977f..b7e39e7233ea 100644
--- a/gnu/libexec/uucp/libuuconf/hsys.c
+++ b/gnu/libexec/uucp/libuuconf/hsys.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hsys_rcsid[] = "$Id: hsys.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hsys_rcsid[] = "hsys.c,v 1.2 1994/05/07 18:12:29 ache Exp";
#endif
/* Get system information from the HDB configuration files. This is a
diff --git a/gnu/libexec/uucp/libuuconf/hunk.c b/gnu/libexec/uucp/libuuconf/hunk.c
index cfc79bb0cacf..9e4a7a1d3fc0 100644
--- a/gnu/libexec/uucp/libuuconf/hunk.c
+++ b/gnu/libexec/uucp/libuuconf/hunk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_hunk_rcsid[] = "$Id: hunk.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_hunk_rcsid[] = "hunk.c,v 1.2 1994/05/07 18:12:30 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/iniglb.c b/gnu/libexec/uucp/libuuconf/iniglb.c
index fa8e79624b20..346ea9c42253 100644
--- a/gnu/libexec/uucp/libuuconf/iniglb.c
+++ b/gnu/libexec/uucp/libuuconf/iniglb.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_iniglb_rcsid[] = "$Id: iniglb.c,v 1.8 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_iniglb_rcsid[] = "iniglb.c,v 1.2 1994/05/07 18:12:31 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/init.c b/gnu/libexec/uucp/libuuconf/init.c
index 4c4ef84aacf2..d00dd7870d2d 100644
--- a/gnu/libexec/uucp/libuuconf/init.c
+++ b/gnu/libexec/uucp/libuuconf/init.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_init_rcsid[] = "$Id: init.c,v 1.5 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_init_rcsid[] = "init.c,v 1.2 1994/05/07 18:12:32 ache Exp";
#endif
/* Initialize the UUCP configuration file reading routines. This is
diff --git a/gnu/libexec/uucp/libuuconf/int.c b/gnu/libexec/uucp/libuuconf/int.c
index 1639006849db..41857feb5cb2 100644
--- a/gnu/libexec/uucp/libuuconf/int.c
+++ b/gnu/libexec/uucp/libuuconf/int.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_int_rcsid[] = "$Id: int.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_int_rcsid[] = "int.c,v 1.2 1994/05/07 18:12:33 ache Exp";
#endif
/* Parse a string into a variable. This is called by uuconf_cmd_args,
diff --git a/gnu/libexec/uucp/libuuconf/lckdir.c b/gnu/libexec/uucp/libuuconf/lckdir.c
index d0be913dcbeb..6df35070fded 100644
--- a/gnu/libexec/uucp/libuuconf/lckdir.c
+++ b/gnu/libexec/uucp/libuuconf/lckdir.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_lckdir_rcsid[] = "$Id: lckdir.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_lckdir_rcsid[] = "lckdir.c,v 1.2 1994/05/07 18:12:34 ache Exp";
#endif
/* Get the name of the UUCP lock directory. */
diff --git a/gnu/libexec/uucp/libuuconf/lineno.c b/gnu/libexec/uucp/libuuconf/lineno.c
index e95981446195..1e14541569d9 100644
--- a/gnu/libexec/uucp/libuuconf/lineno.c
+++ b/gnu/libexec/uucp/libuuconf/lineno.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_lineno_rcsid[] = "$Id: lineno.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_lineno_rcsid[] = "lineno.c,v 1.2 1994/05/07 18:12:35 ache Exp";
#endif
/* Return the saved line number. */
diff --git a/gnu/libexec/uucp/libuuconf/llocnm.c b/gnu/libexec/uucp/libuuconf/llocnm.c
index 96ae75e1a208..269b46eb3166 100644
--- a/gnu/libexec/uucp/libuuconf/llocnm.c
+++ b/gnu/libexec/uucp/libuuconf/llocnm.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_llocnm_rcsid[] = "$Id: llocnm.c,v 1.6 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_llocnm_rcsid[] = "llocnm.c,v 1.2 1994/05/07 18:12:36 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/local.c b/gnu/libexec/uucp/libuuconf/local.c
index 64593ca96dd5..f618516b1f69 100644
--- a/gnu/libexec/uucp/libuuconf/local.c
+++ b/gnu/libexec/uucp/libuuconf/local.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_local_rcsid[] = "$Id: local.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_local_rcsid[] = "local.c,v 1.2 1994/05/07 18:12:37 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/locnm.c b/gnu/libexec/uucp/libuuconf/locnm.c
index 4309387e2ad3..77538fbe8d80 100644
--- a/gnu/libexec/uucp/libuuconf/locnm.c
+++ b/gnu/libexec/uucp/libuuconf/locnm.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_locnm_rcsid[] = "$Id: locnm.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_locnm_rcsid[] = "locnm.c,v 1.2 1994/05/07 18:12:38 ache Exp";
#endif
/* Get the local node name. */
diff --git a/gnu/libexec/uucp/libuuconf/logfil.c b/gnu/libexec/uucp/libuuconf/logfil.c
index f2f2695d497c..3c461cd39b87 100644
--- a/gnu/libexec/uucp/libuuconf/logfil.c
+++ b/gnu/libexec/uucp/libuuconf/logfil.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_logfil_rcsid[] = "$Id: logfil.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_logfil_rcsid[] = "logfil.c,v 1.2 1994/05/07 18:12:39 ache Exp";
#endif
/* Get the name of the UUCP log file. */
diff --git a/gnu/libexec/uucp/libuuconf/maxuxq.c b/gnu/libexec/uucp/libuuconf/maxuxq.c
index 852f7e393bde..3280d99e2abd 100644
--- a/gnu/libexec/uucp/libuuconf/maxuxq.c
+++ b/gnu/libexec/uucp/libuuconf/maxuxq.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_maxuxq_rcsid[] = "$Id: maxuxq.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_maxuxq_rcsid[] = "maxuxq.c,v 1.2 1994/05/07 18:12:40 ache Exp";
#endif
/* Get the maximum number of simultaneous uuxqt executions. When
diff --git a/gnu/libexec/uucp/libuuconf/mrgblk.c b/gnu/libexec/uucp/libuuconf/mrgblk.c
index 713e24099650..09af4dc91ed9 100644
--- a/gnu/libexec/uucp/libuuconf/mrgblk.c
+++ b/gnu/libexec/uucp/libuuconf/mrgblk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_mrgblk_rcsid[] = "$Id: mrgblk.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_mrgblk_rcsid[] = "mrgblk.c,v 1.2 1994/05/07 18:12:41 ache Exp";
#endif
#include "alloc.h"
diff --git a/gnu/libexec/uucp/libuuconf/paramc.c b/gnu/libexec/uucp/libuuconf/paramc.c
index caa76c3f35e4..03a3a37ef519 100644
--- a/gnu/libexec/uucp/libuuconf/paramc.c
+++ b/gnu/libexec/uucp/libuuconf/paramc.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_paramc_rcsid[] = "$Id: paramc.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_paramc_rcsid[] = "paramc.c,v 1.2 1994/05/07 18:12:42 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/port.c b/gnu/libexec/uucp/libuuconf/port.c
index 63a0550908b2..0b4a660d01a5 100644
--- a/gnu/libexec/uucp/libuuconf/port.c
+++ b/gnu/libexec/uucp/libuuconf/port.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_port_rcsid[] = "$Id: port.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_port_rcsid[] = "port.c,v 1.2 1994/05/07 18:12:43 ache Exp";
#endif
/* Find a port by name, baud rate, and special purpose function. */
diff --git a/gnu/libexec/uucp/libuuconf/prtsub.c b/gnu/libexec/uucp/libuuconf/prtsub.c
index 8e6dde314f6e..003573e49acc 100644
--- a/gnu/libexec/uucp/libuuconf/prtsub.c
+++ b/gnu/libexec/uucp/libuuconf/prtsub.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_prtsub_rcsid[] = "$Id: prtsub.c,v 1.5 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_prtsub_rcsid[] = "prtsub.c,v 1.2 1994/05/07 18:12:44 ache Exp";
#endif
/* Clear the information in a port. This can only clear the type
diff --git a/gnu/libexec/uucp/libuuconf/pubdir.c b/gnu/libexec/uucp/libuuconf/pubdir.c
index 0d6f5f1d9ae0..001d718afe36 100644
--- a/gnu/libexec/uucp/libuuconf/pubdir.c
+++ b/gnu/libexec/uucp/libuuconf/pubdir.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_pubdir_rcsid[] = "$Id: pubdir.c,v 1.5 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_pubdir_rcsid[] = "pubdir.c,v 1.2 1994/05/07 18:12:45 ache Exp";
#endif
/* Get the name of the UUCP public directory. */
diff --git a/gnu/libexec/uucp/libuuconf/rdlocs.c b/gnu/libexec/uucp/libuuconf/rdlocs.c
index 4393cc8c6f61..63a813e23c38 100644
--- a/gnu/libexec/uucp/libuuconf/rdlocs.c
+++ b/gnu/libexec/uucp/libuuconf/rdlocs.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_rdlocs_rcsid[] = "$Id: rdlocs.c,v 1.5 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_rdlocs_rcsid[] = "rdlocs.c,v 1.2 1994/05/07 18:12:46 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/rdperm.c b/gnu/libexec/uucp/libuuconf/rdperm.c
index 1d365864a0e4..f04e0db61f4c 100644
--- a/gnu/libexec/uucp/libuuconf/rdperm.c
+++ b/gnu/libexec/uucp/libuuconf/rdperm.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_rdperm_rcsid[] = "$Id: rdperm.c,v 1.7 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_rdperm_rcsid[] = "rdperm.c,v 1.2 1994/05/07 18:12:48 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/reliab.c b/gnu/libexec/uucp/libuuconf/reliab.c
index 57d238b0b4ab..4e668a5338c0 100644
--- a/gnu/libexec/uucp/libuuconf/reliab.c
+++ b/gnu/libexec/uucp/libuuconf/reliab.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_reliab_rcsid[] = "$Id: reliab.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_reliab_rcsid[] = "reliab.c,v 1.2 1994/05/07 18:12:49 ache Exp";
#endif
/* Handle the "seven-bit" command for a port or a dialer. The pvar
diff --git a/gnu/libexec/uucp/libuuconf/remunk.c b/gnu/libexec/uucp/libuuconf/remunk.c
index be947b73c955..73ebbe73b98a 100644
--- a/gnu/libexec/uucp/libuuconf/remunk.c
+++ b/gnu/libexec/uucp/libuuconf/remunk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_remunk_rcsid[] = "$Id: remunk.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_remunk_rcsid[] = "remunk.c,v 1.2 1994/05/07 18:12:50 ache Exp";
#endif
/* Get the name of the remote.unknown shell script. */
diff --git a/gnu/libexec/uucp/libuuconf/runuxq.c b/gnu/libexec/uucp/libuuconf/runuxq.c
index 013cca3cdefa..312e5e364fca 100644
--- a/gnu/libexec/uucp/libuuconf/runuxq.c
+++ b/gnu/libexec/uucp/libuuconf/runuxq.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_runuxq_rcsid[] = "$Id: runuxq.c,v 1.3 1994/03/25 04:39:39 ian Rel $";
+const char _uuconf_runuxq_rcsid[] = "runuxq.c,v 1.1 1994/05/07 18:12:51 ache Exp";
#endif
/* Return how often to spawn a uuxqt process. This is either a
diff --git a/gnu/libexec/uucp/libuuconf/sinfo.c b/gnu/libexec/uucp/libuuconf/sinfo.c
index 60282a201feb..d922c66ac7d9 100644
--- a/gnu/libexec/uucp/libuuconf/sinfo.c
+++ b/gnu/libexec/uucp/libuuconf/sinfo.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_sinfo_rcsid[] = "$Id: sinfo.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_sinfo_rcsid[] = "sinfo.c,v 1.2 1994/05/07 18:12:52 ache Exp";
#endif
/* Get information about a particular system. We combine the
diff --git a/gnu/libexec/uucp/libuuconf/snams.c b/gnu/libexec/uucp/libuuconf/snams.c
index 8b24f0445940..29a7de90e9ba 100644
--- a/gnu/libexec/uucp/libuuconf/snams.c
+++ b/gnu/libexec/uucp/libuuconf/snams.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_snams_rcsid[] = "$Id: snams.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_snams_rcsid[] = "snams.c,v 1.2 1994/05/07 18:12:53 ache Exp";
#endif
/* Get all known system names. */
diff --git a/gnu/libexec/uucp/libuuconf/split.c b/gnu/libexec/uucp/libuuconf/split.c
index 96c1d897126e..c7eb3ea14e7a 100644
--- a/gnu/libexec/uucp/libuuconf/split.c
+++ b/gnu/libexec/uucp/libuuconf/split.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_split_rcsid[] = "$Id: split.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_split_rcsid[] = "split.c,v 1.2 1994/05/07 18:12:54 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/libuuconf/spool.c b/gnu/libexec/uucp/libuuconf/spool.c
index f56f0d5c9315..86c9db782900 100644
--- a/gnu/libexec/uucp/libuuconf/spool.c
+++ b/gnu/libexec/uucp/libuuconf/spool.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_spool_rcsid[] = "$Id: spool.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_spool_rcsid[] = "spool.c,v 1.2 1994/05/07 18:12:55 ache Exp";
#endif
/* Get the name of the UUCP spool directory. */
diff --git a/gnu/libexec/uucp/libuuconf/stafil.c b/gnu/libexec/uucp/libuuconf/stafil.c
index e02e838d331b..acd75d386e96 100644
--- a/gnu/libexec/uucp/libuuconf/stafil.c
+++ b/gnu/libexec/uucp/libuuconf/stafil.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_stafil_rcsid[] = "$Id: stafil.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_stafil_rcsid[] = "stafil.c,v 1.2 1994/05/07 18:12:56 ache Exp";
#endif
/* Get the name of the UUCP statistics file. */
diff --git a/gnu/libexec/uucp/libuuconf/syssub.c b/gnu/libexec/uucp/libuuconf/syssub.c
index 4a209d8fc72c..87f57bc4680e 100644
--- a/gnu/libexec/uucp/libuuconf/syssub.c
+++ b/gnu/libexec/uucp/libuuconf/syssub.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_syssub_rcsid[] = "$Id: syssub.c,v 1.11 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_syssub_rcsid[] = "syssub.c,v 1.2 1994/05/07 18:12:59 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tcalou.c b/gnu/libexec/uucp/libuuconf/tcalou.c
index bc13a6039ae3..8850636edbd3 100644
--- a/gnu/libexec/uucp/libuuconf/tcalou.c
+++ b/gnu/libexec/uucp/libuuconf/tcalou.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tcalou_rcsid[] = "$Id: tcalou.c,v 1.6 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tcalou_rcsid[] = "tcalou.c,v 1.2 1994/05/07 18:13:00 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tdial.c b/gnu/libexec/uucp/libuuconf/tdial.c
index 61f913419bac..b4f6c45c1547 100644
--- a/gnu/libexec/uucp/libuuconf/tdial.c
+++ b/gnu/libexec/uucp/libuuconf/tdial.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tdial_rcsid[] = "$Id: tdial.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tdial_rcsid[] = "tdial.c,v 1.2 1994/05/07 18:13:01 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tdialc.c b/gnu/libexec/uucp/libuuconf/tdialc.c
index 02063b2180d3..f8ed335f5dea 100644
--- a/gnu/libexec/uucp/libuuconf/tdialc.c
+++ b/gnu/libexec/uucp/libuuconf/tdialc.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tdialc_rcsid[] = "$Id: tdialc.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tdialc_rcsid[] = "tdialc.c,v 1.2 1994/05/07 18:13:02 ache Exp";
#endif
static int idchat P((pointer pglobal, int argc, char **argv, pointer pvar,
diff --git a/gnu/libexec/uucp/libuuconf/tdnams.c b/gnu/libexec/uucp/libuuconf/tdnams.c
index fa55a1f121e6..2f6f5c592ee7 100644
--- a/gnu/libexec/uucp/libuuconf/tdnams.c
+++ b/gnu/libexec/uucp/libuuconf/tdnams.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tdnams_rcsid[] = "$Id: tdnams.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tdnams_rcsid[] = "tdnams.c,v 1.2 1994/05/07 18:13:03 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tgcmp.c b/gnu/libexec/uucp/libuuconf/tgcmp.c
index 3e54a449e044..283323569af9 100644
--- a/gnu/libexec/uucp/libuuconf/tgcmp.c
+++ b/gnu/libexec/uucp/libuuconf/tgcmp.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tgcmp_rcsid[] = "$Id: tgcmp.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tgcmp_rcsid[] = "tgcmp.c,v 1.2 1994/05/07 18:13:04 ache Exp";
#endif
/* A comparison function to pass to _uuconf_itime_parse. This
diff --git a/gnu/libexec/uucp/libuuconf/thread.c b/gnu/libexec/uucp/libuuconf/thread.c
index 5a7bc7c262ad..5fecf2661614 100644
--- a/gnu/libexec/uucp/libuuconf/thread.c
+++ b/gnu/libexec/uucp/libuuconf/thread.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_thread_rcsid[] = "$Id: thread.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_thread_rcsid[] = "thread.c,v 1.2 1994/05/07 18:13:05 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/time.c b/gnu/libexec/uucp/libuuconf/time.c
index 4aaafe5b21db..57da31f2a2fc 100644
--- a/gnu/libexec/uucp/libuuconf/time.c
+++ b/gnu/libexec/uucp/libuuconf/time.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_time_rcsid[] = "$Id: time.c,v 1.11 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_time_rcsid[] = "time.c,v 1.2 1994/05/07 18:13:06 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/libuuconf/tinit.c b/gnu/libexec/uucp/libuuconf/tinit.c
index 69767aa6375f..e2d9055e8de3 100644
--- a/gnu/libexec/uucp/libuuconf/tinit.c
+++ b/gnu/libexec/uucp/libuuconf/tinit.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tinit_rcsid[] = "$Id: tinit.c,v 1.10 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tinit_rcsid[] = "tinit.c,v 1.2 1994/05/07 18:13:07 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tlocnm.c b/gnu/libexec/uucp/libuuconf/tlocnm.c
index 8bb834b956b5..b179ac130e31 100644
--- a/gnu/libexec/uucp/libuuconf/tlocnm.c
+++ b/gnu/libexec/uucp/libuuconf/tlocnm.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tlocnm_rcsid[] = "$Id: tlocnm.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tlocnm_rcsid[] = "tlocnm.c,v 1.2 1994/05/07 18:13:08 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tport.c b/gnu/libexec/uucp/libuuconf/tport.c
index 6e46f48b720f..dd88b9fc025f 100644
--- a/gnu/libexec/uucp/libuuconf/tport.c
+++ b/gnu/libexec/uucp/libuuconf/tport.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tport_rcsid[] = "$Id: tport.c,v 1.7 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tport_rcsid[] = "tport.c,v 1.2 1994/05/07 18:13:09 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tportc.c b/gnu/libexec/uucp/libuuconf/tportc.c
index ec15cdfc9a6d..8753bb0bf386 100644
--- a/gnu/libexec/uucp/libuuconf/tportc.c
+++ b/gnu/libexec/uucp/libuuconf/tportc.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tportc_rcsid[] = "$Id: tportc.c,v 1.12 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tportc_rcsid[] = "tportc.c,v 1.2 1994/05/07 18:13:11 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tsinfo.c b/gnu/libexec/uucp/libuuconf/tsinfo.c
index 473e3ffc1b3b..3ba55e3d1f42 100644
--- a/gnu/libexec/uucp/libuuconf/tsinfo.c
+++ b/gnu/libexec/uucp/libuuconf/tsinfo.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tsinfo_rcsid[] = "$Id: tsinfo.c,v 1.11 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tsinfo_rcsid[] = "tsinfo.c,v 1.2 1994/05/07 18:13:12 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/tsnams.c b/gnu/libexec/uucp/libuuconf/tsnams.c
index 70da76fea8bc..13f1221e28c0 100644
--- a/gnu/libexec/uucp/libuuconf/tsnams.c
+++ b/gnu/libexec/uucp/libuuconf/tsnams.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tsnams_rcsid[] = "$Id: tsnams.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tsnams_rcsid[] = "tsnams.c,v 1.2 1994/05/07 18:13:13 ache Exp";
#endif
/* Get all the system names from the Taylor UUCP configuration files.
diff --git a/gnu/libexec/uucp/libuuconf/tsys.c b/gnu/libexec/uucp/libuuconf/tsys.c
index 86f8203a5e89..193a11342260 100644
--- a/gnu/libexec/uucp/libuuconf/tsys.c
+++ b/gnu/libexec/uucp/libuuconf/tsys.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tsys_rcsid[] = "$Id: tsys.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tsys_rcsid[] = "tsys.c,v 1.2 1994/05/07 18:13:14 ache Exp";
#endif
/* Get system information from the Taylor UUCP configuration files.
diff --git a/gnu/libexec/uucp/libuuconf/tval.c b/gnu/libexec/uucp/libuuconf/tval.c
index ba3be13909d4..91f90acf1d24 100644
--- a/gnu/libexec/uucp/libuuconf/tval.c
+++ b/gnu/libexec/uucp/libuuconf/tval.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_tval_rcsid[] = "$Id: tval.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_tval_rcsid[] = "tval.c,v 1.2 1994/05/07 18:13:15 ache Exp";
#endif
/* Validate a login name for a system using Taylor UUCP configuration
diff --git a/gnu/libexec/uucp/libuuconf/ugtlin.c b/gnu/libexec/uucp/libuuconf/ugtlin.c
index 36a52ebe0d60..3382a1177b3b 100644
--- a/gnu/libexec/uucp/libuuconf/ugtlin.c
+++ b/gnu/libexec/uucp/libuuconf/ugtlin.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_ugtlin_rcsid[] = "$Id: ugtlin.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_ugtlin_rcsid[] = "ugtlin.c,v 1.2 1994/05/07 18:13:16 ache Exp";
#endif
/* Read a line from a file with backslash continuations. This updates
diff --git a/gnu/libexec/uucp/libuuconf/unk.c b/gnu/libexec/uucp/libuuconf/unk.c
index 2df924ecc5ee..58083a88e172 100644
--- a/gnu/libexec/uucp/libuuconf/unk.c
+++ b/gnu/libexec/uucp/libuuconf/unk.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_unk_rcsid[] = "$Id: unk.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_unk_rcsid[] = "unk.c,v 1.2 1994/05/07 18:13:18 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/val.c b/gnu/libexec/uucp/libuuconf/val.c
index 76dfab3514c8..a5e03fd6f82d 100644
--- a/gnu/libexec/uucp/libuuconf/val.c
+++ b/gnu/libexec/uucp/libuuconf/val.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_val_rcsid[] = "$Id: val.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_val_rcsid[] = "val.c,v 1.2 1994/05/07 18:13:20 ache Exp";
#endif
/* Validate a login name for a system. */
diff --git a/gnu/libexec/uucp/libuuconf/vinit.c b/gnu/libexec/uucp/libuuconf/vinit.c
index 3e2d507d90a8..5fac728457e2 100644
--- a/gnu/libexec/uucp/libuuconf/vinit.c
+++ b/gnu/libexec/uucp/libuuconf/vinit.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_vinit_rcsid[] = "$Id: vinit.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_vinit_rcsid[] = "vinit.c,v 1.2 1994/05/07 18:13:21 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/vport.c b/gnu/libexec/uucp/libuuconf/vport.c
index 5ce283903f00..e4ec9d81bf11 100644
--- a/gnu/libexec/uucp/libuuconf/vport.c
+++ b/gnu/libexec/uucp/libuuconf/vport.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_vport_rcsid[] = "$Id: vport.c,v 1.7 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_vport_rcsid[] = "vport.c,v 1.2 1994/05/07 18:13:22 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/vsinfo.c b/gnu/libexec/uucp/libuuconf/vsinfo.c
index ac6d3f253768..b06f56fb2dfe 100644
--- a/gnu/libexec/uucp/libuuconf/vsinfo.c
+++ b/gnu/libexec/uucp/libuuconf/vsinfo.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_vsinfo_rcsid[] = "$Id: vsinfo.c,v 1.10 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_vsinfo_rcsid[] = "vsinfo.c,v 1.2 1994/05/07 18:13:23 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/vsnams.c b/gnu/libexec/uucp/libuuconf/vsnams.c
index a52cfcf5eb1c..5a185bc92bdb 100644
--- a/gnu/libexec/uucp/libuuconf/vsnams.c
+++ b/gnu/libexec/uucp/libuuconf/vsnams.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_vsnams_rcsid[] = "$Id: vsnams.c,v 1.4 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_vsnams_rcsid[] = "vsnams.c,v 1.2 1994/05/07 18:13:24 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/libuuconf/vsys.c b/gnu/libexec/uucp/libuuconf/vsys.c
index 4b0a68be6779..11e4206e1b1a 100644
--- a/gnu/libexec/uucp/libuuconf/vsys.c
+++ b/gnu/libexec/uucp/libuuconf/vsys.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char _uuconf_vsys_rcsid[] = "$Id: vsys.c,v 1.3 1994/01/30 21:14:29 ian Rel $";
+const char _uuconf_vsys_rcsid[] = "vsys.c,v 1.2 1994/05/07 18:13:25 ache Exp";
#endif
/* Get system information from the V2 configuration files. This is a
diff --git a/gnu/libexec/uucp/libuucp/Makefile b/gnu/libexec/uucp/libuucp/Makefile
index 33e0a0251850..65bfad30b417 100644
--- a/gnu/libexec/uucp/libuucp/Makefile
+++ b/gnu/libexec/uucp/libuucp/Makefile
@@ -1,5 +1,5 @@
# This is the Makefile for the libuucp subdirectory of Taylor UUCP
-# $Id: Makefile,v 1.2 1993/08/16 16:22:34 jtc Exp $
+# Makefile,v 1.3 1994/05/07 18:13:29 ache Exp
LIB= uucp
SRCS = buffer.c crc.c debug.c escape.c getopt.c getop1.c parse.c spool.c \
diff --git a/gnu/libexec/uucp/libuucp/parse.c b/gnu/libexec/uucp/libuucp/parse.c
index d40da8086b66..b39778529220 100644
--- a/gnu/libexec/uucp/libuucp/parse.c
+++ b/gnu/libexec/uucp/libuucp/parse.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char parse_rcsid[] = "$Id: parse.c,v 1.6 1994/03/26 04:42:39 ian Rel $";
+const char parse_rcsid[] = "parse.c,v 1.2 1994/05/07 18:13:33 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/sample/Makefile b/gnu/libexec/uucp/sample/Makefile
index da218987fce9..76ce0bd5df69 100644
--- a/gnu/libexec/uucp/sample/Makefile
+++ b/gnu/libexec/uucp/sample/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 1993/10/14 12:18:29 rgrimes Exp $
+# Makefile,v 1.2 1994/04/25 16:17:59 jkh Exp
FILES= call.sample config.sample dial.sample dialcode.sample passwd.sample \
port.sample sys1.sample sys2.sample
diff --git a/gnu/libexec/uucp/tstuu.c b/gnu/libexec/uucp/tstuu.c
index d411ae6ac402..f09b1a669cd3 100644
--- a/gnu/libexec/uucp/tstuu.c
+++ b/gnu/libexec/uucp/tstuu.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char tstuu_rcsid[] = "$Id: tstuu.c,v 1.81 1994/01/30 20:53:38 ian Rel $";
+const char tstuu_rcsid[] = "tstuu.c,v 1.2 1994/05/07 18:08:16 ache Exp";
#endif
#include "sysdep.h"
diff --git a/gnu/libexec/uucp/uuchk/Makefile b/gnu/libexec/uucp/uuchk/Makefile
index 46df27ff95b1..5d4e6c920a4a 100644
--- a/gnu/libexec/uucp/uuchk/Makefile
+++ b/gnu/libexec/uucp/uuchk/Makefile
@@ -1,5 +1,5 @@
# Makefile for uuchk
-# $Id: Makefile,v 1.2 1994/05/31 05:11:12 ache Exp $
+# Makefile,v 1.3 1994/05/31 05:46:20 ache Exp
BINDIR= $(sbindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uuchk/uuchk.c b/gnu/libexec/uucp/uuchk/uuchk.c
index a1e69e888f8a..e62be415423f 100644
--- a/gnu/libexec/uucp/uuchk/uuchk.c
+++ b/gnu/libexec/uucp/uuchk/uuchk.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uuchk_rcsid[] = "$Id: uuchk.c,v 1.52 1994/05/02 03:43:02 ian Rel $";
+const char uuchk_rcsid[] = "uuchk.c,v 1.2 1994/05/07 18:13:37 ache Exp";
#endif
#include "getopt.h"
diff --git a/gnu/libexec/uucp/uucico/Makefile b/gnu/libexec/uucp/uucico/Makefile
index 0e7c73c8ed8c..45f510206509 100644
--- a/gnu/libexec/uucp/uucico/Makefile
+++ b/gnu/libexec/uucp/uucico/Makefile
@@ -1,5 +1,5 @@
# Makefile for uucico
-# $Id: Makefile,v 1.5 1994/05/31 05:46:32 ache Exp $
+# Makefile,v 1.6 1994/05/31 15:55:43 ache Exp
BINDIR= $(sbindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uucico/prote.c b/gnu/libexec/uucp/uucico/prote.c
index adb937b7769f..a2535f3cd111 100644
--- a/gnu/libexec/uucp/uucico/prote.c
+++ b/gnu/libexec/uucp/uucico/prote.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char prote_rcsid[] = "$Id: prote.c,v 1.16 1994/01/30 21:01:46 ian Rel $";
+const char prote_rcsid[] = "prote.c,v 1.2 1994/05/07 18:13:43 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/uucico/protf.c b/gnu/libexec/uucp/uucico/protf.c
index a54be9f88cec..22ef4a9fffb8 100644
--- a/gnu/libexec/uucp/uucico/protf.c
+++ b/gnu/libexec/uucp/uucico/protf.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char protf_rcsid[] = "$Id: protf.c,v 1.31 1994/01/30 21:01:46 ian Rel $";
+const char protf_rcsid[] = "protf.c,v 1.2 1994/05/07 18:13:45 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uucico/protg.c b/gnu/libexec/uucp/uucico/protg.c
index b18a26021580..5227b1b7b12a 100644
--- a/gnu/libexec/uucp/uucico/protg.c
+++ b/gnu/libexec/uucp/uucico/protg.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char protg_rcsid[] = "$Id: protg.c,v 1.65 1994/03/26 03:39:05 ian Rel $";
+const char protg_rcsid[] = "protg.c,v 1.2 1994/05/07 18:13:46 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uucico/proti.c b/gnu/libexec/uucp/uucico/proti.c
index 6d9a97a51451..ca3488240a93 100644
--- a/gnu/libexec/uucp/uucico/proti.c
+++ b/gnu/libexec/uucp/uucico/proti.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char proti_rcsid[] = "$Id: proti.c,v 1.29 1994/03/26 03:39:05 ian Rel $";
+const char proti_rcsid[] = "proti.c,v 1.2 1994/05/07 18:13:48 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uucico/protj.c b/gnu/libexec/uucp/uucico/protj.c
index 091099e71ce8..a2f5698cb512 100644
--- a/gnu/libexec/uucp/uucico/protj.c
+++ b/gnu/libexec/uucp/uucico/protj.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char protj_rcsid[] = "$Id: protj.c,v 1.4 1994/01/30 21:01:46 ian Rel $";
+const char protj_rcsid[] = "protj.c,v 1.2 1994/05/07 18:13:50 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uucico/prott.c b/gnu/libexec/uucp/uucico/prott.c
index 26bb73065e00..d44ea9afb3c6 100644
--- a/gnu/libexec/uucp/uucico/prott.c
+++ b/gnu/libexec/uucp/uucico/prott.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char prott_rcsid[] = "$Id: prott.c,v 1.27 1994/01/30 21:01:46 ian Rel $";
+const char prott_rcsid[] = "prott.c,v 1.2 1994/05/07 18:13:51 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/uucico/protz.c b/gnu/libexec/uucp/uucico/protz.c
index 5dd2473fd115..4da6366db44b 100644
--- a/gnu/libexec/uucp/uucico/protz.c
+++ b/gnu/libexec/uucp/uucico/protz.c
@@ -181,7 +181,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char protz_rcsid[] = "$Id: protz.c,v 1.8 1993/12/20 00:44:49 ian Rel $";
+const char protz_rcsid[] = "protz.c,v 1.2 1994/05/07 18:13:52 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/uucico/rec.c b/gnu/libexec/uucp/uucico/rec.c
index d9f907a95183..dba4899686ec 100644
--- a/gnu/libexec/uucp/uucico/rec.c
+++ b/gnu/libexec/uucp/uucico/rec.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char rec_rcsid[] = "$Id: rec.c,v 1.2 1994/05/07 18:13:55 ache Exp $";
+const char rec_rcsid[] = "rec.c,v 1.3 1994/11/06 10:17:11 davidg Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/uucico/send.c b/gnu/libexec/uucp/uucico/send.c
index cf8b5b1bc98c..b20baba02d6d 100644
--- a/gnu/libexec/uucp/uucico/send.c
+++ b/gnu/libexec/uucp/uucico/send.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char send_rcsid[] = "$Id: send.c,v 1.2 1994/05/07 18:13:57 ache Exp $";
+const char send_rcsid[] = "send.c,v 1.3 1994/11/06 10:17:13 davidg Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/uucico/time.c b/gnu/libexec/uucp/uucico/time.c
index a83f7321b339..0b6add97812c 100644
--- a/gnu/libexec/uucp/uucico/time.c
+++ b/gnu/libexec/uucp/uucico/time.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char time_rcsid[] = "$Id: time.c,v 1.19 1994/01/30 21:01:46 ian Rel $";
+const char time_rcsid[] = "time.c,v 1.2 1994/05/07 18:13:58 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uucico/trans.c b/gnu/libexec/uucp/uucico/trans.c
index 9c6766e8dc54..7d6da6be084c 100644
--- a/gnu/libexec/uucp/uucico/trans.c
+++ b/gnu/libexec/uucp/uucico/trans.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char trans_rcsid[] = "$Id: trans.c,v 1.31 1994/01/30 20:59:40 ian Rel $";
+const char trans_rcsid[] = "trans.c,v 1.2 1994/05/07 18:13:59 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/uucico/uucico.8 b/gnu/libexec/uucp/uucico/uucico.8
index a7d2b260b15e..e84c247576cb 100644
--- a/gnu/libexec/uucp/uucico/uucico.8
+++ b/gnu/libexec/uucp/uucico/uucico.8
@@ -1,4 +1,4 @@
-''' $Id: uucico.8,v 1.16 1994/03/26 18:01:37 ian Rel $
+''' uucico.8,v 1.3 1994/05/07 18:14:01 ache Exp
.TH uucico 8 "Taylor UUCP 1.05"
.SH NAME
uucico \- UUCP file transfer daemon
diff --git a/gnu/libexec/uucp/uucico/uucico.c b/gnu/libexec/uucp/uucico/uucico.c
index 90cbcce7b5bc..593148087a23 100644
--- a/gnu/libexec/uucp/uucico/uucico.c
+++ b/gnu/libexec/uucp/uucico/uucico.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uucico_rcsid[] = "$Id: uucico.c,v 1.2 1994/05/07 18:14:02 ache Exp $";
+const char uucico_rcsid[] = "uucico.c,v 1.3 1994/05/25 20:14:52 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uucico/xcmd.c b/gnu/libexec/uucp/uucico/xcmd.c
index b563a53ae49c..7588399ce9bc 100644
--- a/gnu/libexec/uucp/uucico/xcmd.c
+++ b/gnu/libexec/uucp/uucico/xcmd.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char xcmd_rcsid[] = "$Id: xcmd.c,v 1.14 1994/04/04 03:25:12 ian Rel $";
+const char xcmd_rcsid[] = "xcmd.c,v 1.2 1994/05/07 18:14:04 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/uuconv/Makefile b/gnu/libexec/uucp/uuconv/Makefile
index a4c17ef187cc..a3a127b7ba09 100644
--- a/gnu/libexec/uucp/uuconv/Makefile
+++ b/gnu/libexec/uucp/uuconv/Makefile
@@ -1,5 +1,5 @@
# Makefile for uuconv
-# $Id: Makefile,v 1.2 1994/05/31 05:13:08 ache Exp $
+# Makefile,v 1.3 1994/05/31 05:46:34 ache Exp
BINDIR= $(sbindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uuconv/uuconv.c b/gnu/libexec/uucp/uuconv/uuconv.c
index 1f5d94834290..de3afa4ab216 100644
--- a/gnu/libexec/uucp/uuconv/uuconv.c
+++ b/gnu/libexec/uucp/uuconv/uuconv.c
@@ -26,7 +26,7 @@
#include "uucnfi.h"
#if USE_RCS_ID
-const char uuconv_rcsid[] = "$Id: uuconv.c,v 1.22 1994/03/29 01:09:32 ian Rel $";
+const char uuconv_rcsid[] = "uuconv.c,v 1.2 1994/05/07 18:14:06 ache Exp";
#endif
#include "getopt.h"
diff --git a/gnu/libexec/uucp/uucp/Makefile b/gnu/libexec/uucp/uucp/Makefile
index 4cb4afa8138a..0096e8604b77 100644
--- a/gnu/libexec/uucp/uucp/Makefile
+++ b/gnu/libexec/uucp/uucp/Makefile
@@ -1,5 +1,5 @@
# Makefile for uucp
-# $Id: Makefile,v 1.2 1994/05/31 05:37:12 ache Exp $
+# Makefile,v 1.3 1994/05/31 07:37:14 ache Exp
BINDIR= $(bindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uucp/uucp.1 b/gnu/libexec/uucp/uucp/uucp.1
index 7089336f2d48..a71cacff649f 100644
--- a/gnu/libexec/uucp/uucp/uucp.1
+++ b/gnu/libexec/uucp/uucp/uucp.1
@@ -1,4 +1,4 @@
-''' $Id: uucp.1,v 1.9 1993/09/11 22:25:50 ian Rel $
+''' uucp.1,v 1.2 1994/05/07 18:14:08 ache Exp
.TH uucp 1 "Taylor UUCP 1.05"
.SH NAME
uucp \- Unix to Unix copy
diff --git a/gnu/libexec/uucp/uucp/uucp.c b/gnu/libexec/uucp/uucp/uucp.c
index 929f93a745a3..3a9846cb2f90 100644
--- a/gnu/libexec/uucp/uucp/uucp.c
+++ b/gnu/libexec/uucp/uucp/uucp.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uucp_rcsid[] = "$Id: uucp.c,v 1.57 1994/01/30 20:59:40 ian Rel $";
+const char uucp_rcsid[] = "uucp.c,v 1.2 1994/05/07 18:14:10 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uulog/Makefile b/gnu/libexec/uucp/uulog/Makefile
index 321656f3dcf1..3b88c782a58f 100644
--- a/gnu/libexec/uucp/uulog/Makefile
+++ b/gnu/libexec/uucp/uulog/Makefile
@@ -1,5 +1,5 @@
# Makefile for uulog
-# $Id: Makefile,v 1.2 1993/08/05 16:15:14 jtc Exp $
+# Makefile,v 1.1 1993/08/05 18:27:39 conklin Exp
BINDIR= $(bindir)
diff --git a/gnu/libexec/uucp/uulog/uulog.c b/gnu/libexec/uucp/uulog/uulog.c
index 44e33142d0bc..6a65d9824e08 100644
--- a/gnu/libexec/uucp/uulog/uulog.c
+++ b/gnu/libexec/uucp/uulog/uulog.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uulog_rcsid[] = "$Id: uulog.c,v 1.21 1994/01/30 20:59:40 ian Rel $";
+const char uulog_rcsid[] = "uulog.c,v 1.2 1994/05/07 18:14:12 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uuname/Makefile b/gnu/libexec/uucp/uuname/Makefile
index 5e7b314ba11e..510cc16a9a5f 100644
--- a/gnu/libexec/uucp/uuname/Makefile
+++ b/gnu/libexec/uucp/uuname/Makefile
@@ -1,5 +1,5 @@
# Makefile for uuname
-# $Id: Makefile,v 1.2 1993/08/05 16:15:16 jtc Exp $
+# Makefile,v 1.1 1993/08/05 18:27:42 conklin Exp
BINDIR= $(bindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uuname/uuname.c b/gnu/libexec/uucp/uuname/uuname.c
index 7d0d9b115a48..11621a0f0e1d 100644
--- a/gnu/libexec/uucp/uuname/uuname.c
+++ b/gnu/libexec/uucp/uuname/uuname.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uuname_rcsid[] = "$Id: uuname.c,v 1.17 1994/01/30 20:59:40 ian Rel $";
+const char uuname_rcsid[] = "uuname.c,v 1.2 1994/05/07 18:14:13 ache Exp";
#endif
#include "getopt.h"
diff --git a/gnu/libexec/uucp/uupick/Makefile b/gnu/libexec/uucp/uupick/Makefile
index c9a431219d84..e1c73c957dac 100644
--- a/gnu/libexec/uucp/uupick/Makefile
+++ b/gnu/libexec/uucp/uupick/Makefile
@@ -1,5 +1,5 @@
# Makefile for uupick
-# $Id: Makefile,v 1.2 1993/08/05 16:15:19 jtc Exp $
+# Makefile,v 1.1 1993/08/05 18:27:46 conklin Exp
BINDIR= $(bindir)
diff --git a/gnu/libexec/uucp/uupick/uupick.c b/gnu/libexec/uucp/uupick/uupick.c
index cb27f7db04c0..46de1ee8864f 100644
--- a/gnu/libexec/uucp/uupick/uupick.c
+++ b/gnu/libexec/uucp/uupick/uupick.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uupick_rcsid[] = "$Id: uupick.c,v 1.10 1994/01/30 20:59:40 ian Rel $";
+const char uupick_rcsid[] = "uupick.c,v 1.2 1994/05/07 18:14:15 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/libexec/uucp/uusched/Makefile b/gnu/libexec/uucp/uusched/Makefile
index 6135e5380e2f..c8c18a763e9b 100644
--- a/gnu/libexec/uucp/uusched/Makefile
+++ b/gnu/libexec/uucp/uusched/Makefile
@@ -1,5 +1,5 @@
# Makefile for uusched
-# $Id: Makefile,v 1.1 1993/08/05 18:27:55 conklin Exp $
+# Makefile,v 1.2 1993/08/06 23:26:18 rgrimes Exp
BINDIR= $(bindir)
diff --git a/gnu/libexec/uucp/uustat/Makefile b/gnu/libexec/uucp/uustat/Makefile
index 7451292ceaa4..4387ac7b2f3c 100644
--- a/gnu/libexec/uucp/uustat/Makefile
+++ b/gnu/libexec/uucp/uustat/Makefile
@@ -1,5 +1,5 @@
# Makefile for uustat
-# $Id: Makefile,v 1.2 1993/08/05 16:15:22 jtc Exp $
+# Makefile,v 1.1 1993/08/05 18:28:01 conklin Exp
BINDIR= $(bindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uustat/uustat.1 b/gnu/libexec/uucp/uustat/uustat.1
index b6110ea50a97..dc93932023f1 100644
--- a/gnu/libexec/uucp/uustat/uustat.1
+++ b/gnu/libexec/uucp/uustat/uustat.1
@@ -1,4 +1,4 @@
-''' $Id: uustat.1,v 1.11 1994/01/03 04:04:38 ian Rel $
+''' uustat.1,v 1.2 1994/05/07 18:14:22 ache Exp
.TH uustat 1 "Taylor UUCP 1.05"
.SH NAME
uustat \- UUCP status inquiry and control
diff --git a/gnu/libexec/uucp/uustat/uustat.c b/gnu/libexec/uucp/uustat/uustat.c
index 7649dd47b393..8c73e1b78fad 100644
--- a/gnu/libexec/uucp/uustat/uustat.c
+++ b/gnu/libexec/uucp/uustat/uustat.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uustat_rcsid[] = "$Id: uustat.c,v 1.44 1994/01/30 20:59:40 ian Rel $";
+const char uustat_rcsid[] = "uustat.c,v 1.2 1994/05/07 18:14:24 ache Exp";
#endif
#include <ctype.h>
diff --git a/gnu/libexec/uucp/uuto/Makefile b/gnu/libexec/uucp/uuto/Makefile
index 8c3437ec0448..8d3fbb682c56 100644
--- a/gnu/libexec/uucp/uuto/Makefile
+++ b/gnu/libexec/uucp/uuto/Makefile
@@ -1,5 +1,5 @@
# Makefile for uuto
-# $Id: Makefile,v 1.1 1993/08/05 18:28:09 conklin Exp $
+# Makefile,v 1.2 1993/08/06 23:28:02 rgrimes Exp
BINDIR= $(bindir)
diff --git a/gnu/libexec/uucp/uux/Makefile b/gnu/libexec/uucp/uux/Makefile
index 4ee45a431455..4dd42a9455e7 100644
--- a/gnu/libexec/uucp/uux/Makefile
+++ b/gnu/libexec/uucp/uux/Makefile
@@ -1,5 +1,5 @@
# Makefile for uux
-# $Id: Makefile,v 1.2 1994/05/31 05:46:38 ache Exp $
+# Makefile,v 1.3 1994/05/31 07:37:25 ache Exp
BINDIR= $(bindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uux/uux.1 b/gnu/libexec/uucp/uux/uux.1
index 8bf0cbf1fac2..3686438f8433 100644
--- a/gnu/libexec/uucp/uux/uux.1
+++ b/gnu/libexec/uucp/uux/uux.1
@@ -1,4 +1,4 @@
-''' $Id: uux.1,v 1.10 1993/09/11 22:25:50 ian Rel $
+''' uux.1,v 1.2 1994/05/07 18:14:33 ache Exp
.TH uux 1 "Taylor UUCP 1.05"
.SH NAME
uux \- Remote command execution over UUCP
diff --git a/gnu/libexec/uucp/uux/uux.c b/gnu/libexec/uucp/uux/uux.c
index ef5c90ad20d9..ea5d0ec90c0b 100644
--- a/gnu/libexec/uucp/uux/uux.c
+++ b/gnu/libexec/uucp/uux/uux.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uux_rcsid[] = "$Id: uux.c,v 1.4 1994/05/07 18:14:35 ache Exp $";
+const char uux_rcsid[] = "uux.c,v 1.5 1994/10/02 23:09:41 ache Exp";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/uuxqt/Makefile b/gnu/libexec/uucp/uuxqt/Makefile
index 3d2472754b8d..d928f9f29f45 100644
--- a/gnu/libexec/uucp/uuxqt/Makefile
+++ b/gnu/libexec/uucp/uuxqt/Makefile
@@ -1,5 +1,5 @@
# Makefile for uuxqt
-# $Id: Makefile,v 1.4 1994/05/31 05:09:03 ache Exp $
+# Makefile,v 1.5 1994/05/31 05:46:42 ache Exp
BINDIR= $(sbindir)
BINOWN= $(owner)
diff --git a/gnu/libexec/uucp/uuxqt/uuxqt.8 b/gnu/libexec/uucp/uuxqt/uuxqt.8
index 734d1631d674..c311c00bd479 100644
--- a/gnu/libexec/uucp/uuxqt/uuxqt.8
+++ b/gnu/libexec/uucp/uuxqt/uuxqt.8
@@ -1,4 +1,4 @@
-''' $Id: uuxqt.8,v 1.7 1993/09/11 22:25:50 ian Rel $
+''' uuxqt.8,v 1.2 1994/05/07 18:14:41 ache Exp
.TH uuxqt 8 "Taylor UUCP 1.05"
.SH NAME
uuxqt \- UUCP execution daemon
diff --git a/gnu/libexec/uucp/uuxqt/uuxqt.c b/gnu/libexec/uucp/uuxqt/uuxqt.c
index 890aa4326815..e13c9fc51e2d 100644
--- a/gnu/libexec/uucp/uuxqt/uuxqt.c
+++ b/gnu/libexec/uucp/uuxqt/uuxqt.c
@@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char uuxqt_rcsid[] = "$Id: uuxqt.c,v 1.2 1994/05/07 18:14:43 ache Exp $";
+const char uuxqt_rcsid[] = "uuxqt.c,v 1.3 1994/10/22 03:51:36 ache Exp";
#endif
#include <errno.h>
diff --git a/gnu/usr.bin/Makefile b/gnu/usr.bin/Makefile
index 497da92f78e7..568f19e31f2b 100644
--- a/gnu/usr.bin/Makefile
+++ b/gnu/usr.bin/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.11 1994/10/25 16:59:57 bde Exp $
+# Makefile,v 1.12 1994/11/07 08:22:17 davidg Exp
SUBDIR= as awk bc cc cpio cvs dc dialog diff diff3 gdb grep groff gzip kgdb ld \
man patch perl ptx rcs sdiff send-pr sort tar texinfo
diff --git a/gnu/usr.bin/Makefile.inc b/gnu/usr.bin/Makefile.inc
index 5371a22cca25..e6f51116060d 100644
--- a/gnu/usr.bin/Makefile.inc
+++ b/gnu/usr.bin/Makefile.inc
@@ -1,3 +1,3 @@
-# $Id$
+# Makefile.inc,v 1.1 1994/01/30 00:31:51 rgrimes Exp
BINDIR?= /usr/bin
diff --git a/gnu/usr.bin/as/Makefile b/gnu/usr.bin/as/Makefile
index fd4dc30f17cb..0284712672a7 100644
--- a/gnu/usr.bin/as/Makefile
+++ b/gnu/usr.bin/as/Makefile
@@ -1,5 +1,5 @@
# from: @(#)Makefile 6.1 (Berkeley) 3/3/91
-# $Id: Makefile,v 1.4 1994/08/28 17:43:37 bde Exp $
+# Makefile,v 1.5 1994/08/29 17:38:17 davidg Exp
.include "config/Makefile.$(MACHINE)"
diff --git a/gnu/usr.bin/as/app.c b/gnu/usr.bin/as/app.c
index 4c89a77607a8..91c0b70f5a63 100644
--- a/gnu/usr.bin/as/app.c
+++ b/gnu/usr.bin/as/app.c
@@ -27,7 +27,7 @@
This needs better error-handling.
*/
#ifndef lint
-static char rcsid[] = "$Id: app.c,v 1.3 1993/10/02 20:57:12 pk Exp $";
+static char rcsid[] = "app.c,v 1.2 1993/11/03 00:51:05 paul Exp";
#endif
#include <stdio.h>
diff --git a/gnu/usr.bin/as/as.c b/gnu/usr.bin/as/as.c
index a9cbb7074c70..57855b00d6c7 100644
--- a/gnu/usr.bin/as/as.c
+++ b/gnu/usr.bin/as/as.c
@@ -32,7 +32,7 @@
*
*/
#ifndef lint
-static char rcsid[] = "$Id: as.c,v 1.3 1993/10/02 20:57:15 pk Exp $";
+static char rcsid[] = "as.c,v 1.2 1993/11/03 00:51:09 paul Exp";
#endif
#include <stdio.h>
diff --git a/gnu/usr.bin/as/as.h b/gnu/usr.bin/as/as.h
index 7b1e27d2b1ad..5ecc6082fb07 100644
--- a/gnu/usr.bin/as/as.h
+++ b/gnu/usr.bin/as/as.h
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: as.h,v 1.3 1993/10/02 20:57:16 pk Exp $
+ * as.h,v 1.2 1993/11/03 00:51:11 paul Exp
*/
#define GAS 1
diff --git a/gnu/usr.bin/as/atof-generic.c b/gnu/usr.bin/as/atof-generic.c
index b4e0971c8a7b..91f8a2b5ebcc 100644
--- a/gnu/usr.bin/as/atof-generic.c
+++ b/gnu/usr.bin/as/atof-generic.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: atof-generic.c,v 1.3 1993/10/02 20:57:17 pk Exp $";
+static char rcsid[] = "atof-generic.c,v 1.2 1993/11/03 00:51:14 paul Exp";
#endif
#include <ctype.h>
diff --git a/gnu/usr.bin/as/bignum-copy.c b/gnu/usr.bin/as/bignum-copy.c
index 08c92f8dc886..567a988010fd 100644
--- a/gnu/usr.bin/as/bignum-copy.c
+++ b/gnu/usr.bin/as/bignum-copy.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: bignum-copy.c,v 1.3 1993/10/02 20:57:18 pk Exp $";
+static char rcsid[] = "bignum-copy.c,v 1.2 1993/11/03 00:51:16 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/bignum.h b/gnu/usr.bin/as/bignum.h
index d95ca9a039c6..7510f4e1ca57 100644
--- a/gnu/usr.bin/as/bignum.h
+++ b/gnu/usr.bin/as/bignum.h
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: bignum.h,v 1.3 1993/10/02 20:57:19 pk Exp $
+ * bignum.h,v 1.2 1993/11/03 00:51:18 paul Exp
*/
/***********************************************************************\
diff --git a/gnu/usr.bin/as/bit_fix.h b/gnu/usr.bin/as/bit_fix.h
index e72d6d69c15a..6aa214ee7252 100644
--- a/gnu/usr.bin/as/bit_fix.h
+++ b/gnu/usr.bin/as/bit_fix.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: bit_fix.h,v 1.1 1993/10/02 20:57:19 pk Exp $
+ * bit_fix.h,v 1.1 1993/11/03 00:51:19 paul Exp
*/
diff --git a/gnu/usr.bin/as/cond.c b/gnu/usr.bin/as/cond.c
index ad98201ad624..e0857b65bfc7 100644
--- a/gnu/usr.bin/as/cond.c
+++ b/gnu/usr.bin/as/cond.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: cond.c,v 1.1 1993/10/02 20:57:20 pk Exp $";
+static char rcsid[] = "cond.c,v 1.1 1993/11/03 00:51:20 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/config/Makefile.hp300 b/gnu/usr.bin/as/config/Makefile.hp300
index 4261d35b39bc..d690e69fc8a6 100644
--- a/gnu/usr.bin/as/config/Makefile.hp300
+++ b/gnu/usr.bin/as/config/Makefile.hp300
@@ -1,5 +1,5 @@
# from: @(#)Makefile.hp300 6.1 (Berkeley) 3/3/91
-# $Id: Makefile.hp300,v 1.4 1993/10/16 03:23:04 cgd Exp $
+# Makefile.hp300,v 1.1 1993/11/03 00:52:56 paul Exp
CFLAGS+= -Dm68851
SRCS+= tc-m68k.c atof-ieee.c
diff --git a/gnu/usr.bin/as/config/Makefile.i386 b/gnu/usr.bin/as/config/Makefile.i386
index bbae01707c5c..0b6d6ccc59e3 100644
--- a/gnu/usr.bin/as/config/Makefile.i386
+++ b/gnu/usr.bin/as/config/Makefile.i386
@@ -1,5 +1,5 @@
# from: @(#)Makefile.i386 6.1 (Berkeley) 3/3/91
-# $Id: Makefile.i386,v 1.3 1993/10/02 20:58:21 pk Exp $
+# Makefile.i386,v 1.2 1993/11/03 00:52:58 paul Exp
CFLAGS+= -DNON_BROKEN_WORDS
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
index d4b22aba6c80..c0d332c11538 100644
--- a/gnu/usr.bin/as/config/Makefile.pc532
+++ b/gnu/usr.bin/as/config/Makefile.pc532
@@ -1,4 +1,4 @@
-# $Id: Makefile.pc532,v 1.1 1993/10/16 03:23:37 cgd Exp $
+# Makefile.pc532,v 1.1 1993/11/03 00:52:59 paul Exp
SRCS+= tc-ns32k.c atof-ns32k.c
diff --git a/gnu/usr.bin/as/config/Makefile.sparc b/gnu/usr.bin/as/config/Makefile.sparc
index c9d9af1455fa..03b516ae360c 100644
--- a/gnu/usr.bin/as/config/Makefile.sparc
+++ b/gnu/usr.bin/as/config/Makefile.sparc
@@ -1,5 +1,5 @@
# from: @(#)Makefile.i386 6.1 (Berkeley) 3/3/91
-# $Id: Makefile.sparc,v 1.1 1993/10/02 20:58:22 pk Exp $
+# Makefile.sparc,v 1.1 1993/11/03 00:53:00 paul Exp
CFLAGS+= -DNON_BROKEN_WORDS
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
index f62b087d3df3..995ae5693e10 100644
--- a/gnu/usr.bin/as/config/Makefile.vax
+++ b/gnu/usr.bin/as/config/Makefile.vax
@@ -1,4 +1,4 @@
# from: @(#)Makefile.vax 6.1 (Berkeley) 3/3/91
-# $Id: Makefile.vax,v 1.3 1993/10/02 20:58:23 pk Exp $
+# Makefile.vax,v 1.1 1993/11/03 00:53:01 paul Exp
SRCS+= tc-vax.c atof-vax.c
diff --git a/gnu/usr.bin/as/config/atof-ieee.c b/gnu/usr.bin/as/config/atof-ieee.c
index 18941cc333b9..5870adbec525 100644
--- a/gnu/usr.bin/as/config/atof-ieee.c
+++ b/gnu/usr.bin/as/config/atof-ieee.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: atof-ieee.c,v 1.3 1993/10/02 20:58:25 pk Exp $";
+static char rcsid[] = "atof-ieee.c,v 1.2 1993/11/03 00:53:04 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/config/ho-i386.h b/gnu/usr.bin/as/config/ho-i386.h
index 6941b7e29550..a0f7f989752a 100644
--- a/gnu/usr.bin/as/config/ho-i386.h
+++ b/gnu/usr.bin/as/config/ho-i386.h
@@ -17,7 +17,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: ho-i386.h,v 1.1 1993/10/02 20:58:36 pk Exp $
+ * ho-i386.h,v 1.1 1993/11/03 00:53:21 paul Exp
*/
diff --git a/gnu/usr.bin/as/config/obj-aout.h b/gnu/usr.bin/as/config/obj-aout.h
index af3d9b0fa124..c9ef1e3bb93a 100644
--- a/gnu/usr.bin/as/config/obj-aout.h
+++ b/gnu/usr.bin/as/config/obj-aout.h
@@ -17,7 +17,7 @@
License along with GAS; see the file COPYING. If not, write
to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: obj-aout.h,v 1.1 1993/11/03 00:53:50 paul Exp $
+ * obj-aout.h,v 1.2 1993/11/30 20:57:40 jkh Exp
*/
diff --git a/gnu/usr.bin/as/config/tc-i386.c b/gnu/usr.bin/as/config/tc-i386.c
index 84848d2ec233..c65925dc8ea1 100644
--- a/gnu/usr.bin/as/config/tc-i386.c
+++ b/gnu/usr.bin/as/config/tc-i386.c
@@ -25,7 +25,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: tc-i386.c,v 1.1 1993/11/03 00:54:23 paul Exp $";
+static char rcsid[] = "tc-i386.c,v 1.2 1993/11/30 20:57:41 jkh Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/config/tc-i386.h b/gnu/usr.bin/as/config/tc-i386.h
index b9ac3fe36bb6..52a37b4b5dd4 100644
--- a/gnu/usr.bin/as/config/tc-i386.h
+++ b/gnu/usr.bin/as/config/tc-i386.h
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: tc-i386.h,v 1.1 1993/10/02 20:59:21 pk Exp $
+ * tc-i386.h,v 1.1 1993/11/03 00:54:25 paul Exp
*/
#ifndef TC_I386
diff --git a/gnu/usr.bin/as/config/tc-sparc.c b/gnu/usr.bin/as/config/tc-sparc.c
index ae5002701ca0..a8182be1ae1c 100644
--- a/gnu/usr.bin/as/config/tc-sparc.c
+++ b/gnu/usr.bin/as/config/tc-sparc.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: tc-sparc.c,v 1.1 1993/11/03 00:54:52 paul Exp $";
+static char rcsid[] = "tc-sparc.c,v 1.2 1993/12/12 17:02:13 jkh Exp";
#endif
#define cypress 1234
diff --git a/gnu/usr.bin/as/config/tc-sparc.h b/gnu/usr.bin/as/config/tc-sparc.h
index 27355a70a822..8f4bbaf0e00b 100644
--- a/gnu/usr.bin/as/config/tc-sparc.h
+++ b/gnu/usr.bin/as/config/tc-sparc.h
@@ -18,7 +18,7 @@
to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: tc-sparc.h,v 1.1 1993/10/02 20:59:41 pk Exp $
+ * tc-sparc.h,v 1.1 1993/11/03 00:54:54 paul Exp
*/
#define TC_SPARC 1
diff --git a/gnu/usr.bin/as/config/te-generic.h b/gnu/usr.bin/as/config/te-generic.h
index f72d5ee95fea..1998d3fe087f 100644
--- a/gnu/usr.bin/as/config/te-generic.h
+++ b/gnu/usr.bin/as/config/te-generic.h
@@ -6,7 +6,7 @@
* compile, and copying as an aid for testing and porting. xoxorich.
*/
/*
- * $Id: te-generic.h,v 1.1 1993/10/02 20:59:49 pk Exp $
+ * te-generic.h,v 1.1 1993/11/03 00:55:03 paul Exp
*/
diff --git a/gnu/usr.bin/as/debug.c b/gnu/usr.bin/as/debug.c
index 30717ffd2769..935f61e5dd68 100644
--- a/gnu/usr.bin/as/debug.c
+++ b/gnu/usr.bin/as/debug.c
@@ -21,7 +21,7 @@
/* Routines for debug use only. */
#ifndef lint
-static char rcsid[] = "$Id: debug.c,v 1.1 1993/10/02 20:57:24 pk Exp $";
+static char rcsid[] = "debug.c,v 1.1 1993/11/03 00:51:26 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/doc/all.m4 b/gnu/usr.bin/as/doc/all.m4
index 3d4e7fd2f2f6..2759030b24cb 100644
--- a/gnu/usr.bin/as/doc/all.m4
+++ b/gnu/usr.bin/as/doc/all.m4
@@ -1,5 +1,5 @@
_divert__(-1)
-<$Id: all.m4,v 1.1 1993/10/02 21:00:13 pk Exp $>
+<all.m4,v 1.1 1993/11/03 00:55:21 paul Exp>
_define__(<_ALL_ARCH__>,<1>)
_define__(<_GENERIC__>,<1>) In case none.m4 changes its mind abt default
diff --git a/gnu/usr.bin/as/doc/as.texinfo b/gnu/usr.bin/as/doc/as.texinfo
index c9e0f575fa33..ceb1535590c9 100644
--- a/gnu/usr.bin/as/doc/as.texinfo
+++ b/gnu/usr.bin/as/doc/as.texinfo
@@ -1,6 +1,6 @@
_dnl__ -*-Texinfo-*-
_dnl__ Copyright (c) 1991 1992 Free Software Foundation, Inc.
-_dnl__ $Id: as.texinfo,v 1.1 1993/10/02 21:00:15 pk Exp $
+_dnl__ as.texinfo,v 1.1 1993/11/03 00:55:23 paul Exp
\input texinfo @c -*-Texinfo-*-
@c Copyright (c) 1991 1992 Free Software Foundation, Inc.
@c %**start of header
@@ -86,7 +86,7 @@ done.
@page
@tex
\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
-\xdef\manvers{\$Revision: 1.1 $} % For use in headers, footers too
+\xdef\manvers{\1.1} % For use in headers, footers too
{\parskip=0pt
\hfill \manvers\par
\hfill \TeX{}info \texinfoversion\par
diff --git a/gnu/usr.bin/as/doc/gen.m4 b/gnu/usr.bin/as/doc/gen.m4
index bf444a63037f..779947a1dedd 100644
--- a/gnu/usr.bin/as/doc/gen.m4
+++ b/gnu/usr.bin/as/doc/gen.m4
@@ -1,5 +1,5 @@
_divert__(-1)
-<$Id: gen.m4,v 1.1 1993/10/02 21:00:19 pk Exp $>
+<gen.m4,v 1.1 1993/11/03 00:55:32 paul Exp>
_define__(<_GENERIC__>,<1>) In case none.m4 changes its mind abt default
_define__(<_AOUT__>,<1>)
diff --git a/gnu/usr.bin/as/doc/none.m4 b/gnu/usr.bin/as/doc/none.m4
index dfa17d3c356f..8d5ae27b494a 100644
--- a/gnu/usr.bin/as/doc/none.m4
+++ b/gnu/usr.bin/as/doc/none.m4
@@ -1,5 +1,5 @@
_divert__(-1)
-<$Id: none.m4,v 1.1 1993/10/02 21:00:24 pk Exp $>
+<none.m4,v 1.1 1993/11/03 00:55:39 paul Exp>
Switches:
diff --git a/gnu/usr.bin/as/doc/pretex.m4 b/gnu/usr.bin/as/doc/pretex.m4
index 9a9696fb0dd2..a82915b9d667 100644
--- a/gnu/usr.bin/as/doc/pretex.m4
+++ b/gnu/usr.bin/as/doc/pretex.m4
@@ -2,7 +2,7 @@ divert(-1) -*-Text-*-
` Copyright (c) 1991 Free Software Foundation, Inc.'
` This file defines and documents the M4 macros used '
` to preprocess some GNU manuals'
-` $Id: pretex.m4,v 1.1 1993/10/02 21:00:25 pk Exp $'
+` pretex.m4,v 1.1 1993/11/03 00:55:40 paul Exp'
I. INTRODUCTION
diff --git a/gnu/usr.bin/as/doc/vintage.m4 b/gnu/usr.bin/as/doc/vintage.m4
index d5913be64f53..3e41180009d5 100644
--- a/gnu/usr.bin/as/doc/vintage.m4
+++ b/gnu/usr.bin/as/doc/vintage.m4
@@ -1,5 +1,5 @@
_divert__(-1)
-<$Id: vintage.m4,v 1.1 1993/10/02 21:00:29 pk Exp $>
+<vintage.m4,v 1.1 1993/11/03 00:55:45 paul Exp>
_define__(<_ALL_ARCH__>,<1>)
_define__(<_GENERIC__>,<1>) In case none.m4 changes its mind abt default
diff --git a/gnu/usr.bin/as/expr.c b/gnu/usr.bin/as/expr.c
index 413917d89c8c..1ed8da07c230 100644
--- a/gnu/usr.bin/as/expr.c
+++ b/gnu/usr.bin/as/expr.c
@@ -25,7 +25,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: expr.c,v 1.3 1993/10/02 20:57:26 pk Exp $";
+static char rcsid[] = "expr.c,v 1.2 1993/11/03 00:51:28 paul Exp";
#endif
#include <ctype.h>
diff --git a/gnu/usr.bin/as/expr.h b/gnu/usr.bin/as/expr.h
index 2706d4dce03a..0efad0cdcbf1 100644
--- a/gnu/usr.bin/as/expr.h
+++ b/gnu/usr.bin/as/expr.h
@@ -17,7 +17,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: expr.h,v 1.3 1993/10/02 20:57:27 pk Exp $
+ * expr.h,v 1.2 1993/11/03 00:51:31 paul Exp
*/
diff --git a/gnu/usr.bin/as/flo-const.c b/gnu/usr.bin/as/flo-const.c
index 28d8008d8c79..25c0cee4a30f 100644
--- a/gnu/usr.bin/as/flo-const.c
+++ b/gnu/usr.bin/as/flo-const.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: flo-const.c,v 1.1 1993/10/02 20:57:28 pk Exp $";
+static char rcsid[] = "flo-const.c,v 1.1 1993/11/03 00:51:32 paul Exp";
#endif
#include "flonum.h"
diff --git a/gnu/usr.bin/as/flo-copy.c b/gnu/usr.bin/as/flo-copy.c
index 8fcdb5207c95..18e11ef541e7 100644
--- a/gnu/usr.bin/as/flo-copy.c
+++ b/gnu/usr.bin/as/flo-copy.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: flo-copy.c,v 1.1 1993/10/02 20:57:29 pk Exp $";
+static char rcsid[] = "flo-copy.c,v 1.1 1993/11/03 00:51:34 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/flonum-mult.c b/gnu/usr.bin/as/flonum-mult.c
index 41e90bdcf24a..b3abdbeb58a9 100644
--- a/gnu/usr.bin/as/flonum-mult.c
+++ b/gnu/usr.bin/as/flonum-mult.c
@@ -19,7 +19,7 @@
notice and this notice must be preserved on all copies. */
#ifndef lint
-static char rcsid[] = "$Id: flonum-mult.c,v 1.3 1993/10/02 20:57:30 pk Exp $";
+static char rcsid[] = "flonum-mult.c,v 1.2 1993/11/03 00:51:36 paul Exp";
#endif
#include "flonum.h"
diff --git a/gnu/usr.bin/as/flonum.h b/gnu/usr.bin/as/flonum.h
index a1a8f08cbfd3..d4d9cb5eff9f 100644
--- a/gnu/usr.bin/as/flonum.h
+++ b/gnu/usr.bin/as/flonum.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: flonum.h,v 1.3 1993/10/02 20:57:31 pk Exp $
+ * flonum.h,v 1.2 1993/11/03 00:51:37 paul Exp
*/
diff --git a/gnu/usr.bin/as/frags.c b/gnu/usr.bin/as/frags.c
index 208aa7db2f2f..3edb78f523d0 100644
--- a/gnu/usr.bin/as/frags.c
+++ b/gnu/usr.bin/as/frags.c
@@ -19,7 +19,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: frags.c,v 1.3 1993/10/02 20:57:31 pk Exp $";
+static char rcsid[] = "frags.c,v 1.2 1993/11/03 00:51:39 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/frags.h b/gnu/usr.bin/as/frags.h
index 4532dda10bd9..8504f8b31a1a 100644
--- a/gnu/usr.bin/as/frags.h
+++ b/gnu/usr.bin/as/frags.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: frags.h,v 1.3 1993/10/02 20:57:32 pk Exp $
+ * frags.h,v 1.2 1993/11/03 00:51:40 paul Exp
*/
diff --git a/gnu/usr.bin/as/hash.c b/gnu/usr.bin/as/hash.c
index 68a5f14a849b..f8d25f993853 100644
--- a/gnu/usr.bin/as/hash.c
+++ b/gnu/usr.bin/as/hash.c
@@ -123,7 +123,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: hash.c,v 1.3 1993/10/02 20:57:34 pk Exp $";
+static char rcsid[] = "hash.c,v 1.2 1993/11/03 00:51:44 paul Exp";
#endif
#include <stdio.h>
diff --git a/gnu/usr.bin/as/hash.h b/gnu/usr.bin/as/hash.h
index 69185616baee..e8c7f92fae60 100644
--- a/gnu/usr.bin/as/hash.h
+++ b/gnu/usr.bin/as/hash.h
@@ -17,7 +17,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: hash.h,v 1.3 1993/10/02 20:57:35 pk Exp $
+ * hash.h,v 1.2 1993/11/03 00:51:46 paul Exp
*/
diff --git a/gnu/usr.bin/as/hex-value.c b/gnu/usr.bin/as/hex-value.c
index d27d4b3634eb..66d5dd4b6fb2 100644
--- a/gnu/usr.bin/as/hex-value.c
+++ b/gnu/usr.bin/as/hex-value.c
@@ -23,7 +23,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: hex-value.c,v 1.3 1993/10/02 20:57:36 pk Exp $";
+static char rcsid[] = "hex-value.c,v 1.2 1993/11/03 00:51:47 paul Exp";
#endif
#define __ (42) /* blatently illegal digit value */
diff --git a/gnu/usr.bin/as/input-file.c b/gnu/usr.bin/as/input-file.c
index 3b124cc9fe85..7e06c895b138 100644
--- a/gnu/usr.bin/as/input-file.c
+++ b/gnu/usr.bin/as/input-file.c
@@ -25,7 +25,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: input-file.c,v 1.3 1993/10/02 20:57:37 pk Exp $";
+static char rcsid[] = "input-file.c,v 1.2 1993/11/03 00:51:48 paul Exp";
#endif
#ifdef USG
diff --git a/gnu/usr.bin/as/input-file.h b/gnu/usr.bin/as/input-file.h
index 5c88c7c82be0..64ed1db6e691 100644
--- a/gnu/usr.bin/as/input-file.h
+++ b/gnu/usr.bin/as/input-file.h
@@ -20,7 +20,7 @@
/*"input_file.c":Operating-system dependant functions to read source files.*/
/*
- * $Id: input-file.h,v 1.3 1993/10/02 20:57:38 pk Exp $
+ * input-file.h,v 1.2 1993/11/03 00:51:50 paul Exp
*/
diff --git a/gnu/usr.bin/as/input-scrub.c b/gnu/usr.bin/as/input-scrub.c
index 73df1a2246b3..bf8067a79eb2 100644
--- a/gnu/usr.bin/as/input-scrub.c
+++ b/gnu/usr.bin/as/input-scrub.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: input-scrub.c,v 1.3 1993/10/02 20:57:39 pk Exp $";
+static char rcsid[] = "input-scrub.c,v 1.2 1993/11/03 00:51:51 paul Exp";
#endif
#include <errno.h> /* Need this to make errno declaration right */
diff --git a/gnu/usr.bin/as/listing.c b/gnu/usr.bin/as/listing.c
index 2f8b1f02dc3d..cbfed89305ee 100644
--- a/gnu/usr.bin/as/listing.c
+++ b/gnu/usr.bin/as/listing.c
@@ -92,7 +92,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: listing.c,v 1.1 1993/10/02 20:57:40 pk Exp $";
+static char rcsid[] = "listing.c,v 1.1 1993/11/03 00:51:54 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/listing.h b/gnu/usr.bin/as/listing.h
index 37a8e8793c1f..42ed45b58ad3 100644
--- a/gnu/usr.bin/as/listing.h
+++ b/gnu/usr.bin/as/listing.h
@@ -17,7 +17,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: listing.h,v 1.1 1993/10/02 20:57:41 pk Exp $
+ * listing.h,v 1.1 1993/11/03 00:51:56 paul Exp
*/
diff --git a/gnu/usr.bin/as/makefile.dos b/gnu/usr.bin/as/makefile.dos
index 89c74c787361..ad162dc55355 100644
--- a/gnu/usr.bin/as/makefile.dos
+++ b/gnu/usr.bin/as/makefile.dos
@@ -17,7 +17,7 @@
#along with GNU GAS; see the file COPYING. If not, write to
#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# $Id: makefile.dos,v 1.1 1993/10/02 20:57:43 pk Exp $
+# makefile.dos,v 1.1 1993/11/03 00:51:59 paul Exp
# The targets for external use include:
# all, doc, proto, install, uninstall, includes, TAGS,
diff --git a/gnu/usr.bin/as/messages.c b/gnu/usr.bin/as/messages.c
index b1ba3f764a2d..0f1109b77393 100644
--- a/gnu/usr.bin/as/messages.c
+++ b/gnu/usr.bin/as/messages.c
@@ -18,7 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: messages.c,v 1.3 1993/10/02 20:57:45 pk Exp $";
+static char rcsid[] = "messages.c,v 1.2 1993/11/03 00:52:01 paul Exp";
#endif
#include <stdio.h> /* define stderr */
diff --git a/gnu/usr.bin/as/obj.h b/gnu/usr.bin/as/obj.h
index ac5b15822cdd..cf5dea87f196 100644
--- a/gnu/usr.bin/as/obj.h
+++ b/gnu/usr.bin/as/obj.h
@@ -19,7 +19,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: obj.h,v 1.1 1993/10/02 20:57:45 pk Exp $
+ * obj.h,v 1.1 1993/11/03 00:52:03 paul Exp
*/
diff --git a/gnu/usr.bin/as/obstack.c b/gnu/usr.bin/as/obstack.c
index d7302ea1f5d4..13987df73e15 100644
--- a/gnu/usr.bin/as/obstack.c
+++ b/gnu/usr.bin/as/obstack.c
@@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: obstack.c,v 1.3 1993/10/02 20:57:47 pk Exp $";
+static char rcsid[] = "obstack.c,v 1.2 1993/11/03 00:52:04 paul Exp";
#endif
#include "obstack.h"
diff --git a/gnu/usr.bin/as/obstack.h b/gnu/usr.bin/as/obstack.h
index 880015f9eaa4..a15b470d1891 100644
--- a/gnu/usr.bin/as/obstack.h
+++ b/gnu/usr.bin/as/obstack.h
@@ -15,7 +15,7 @@ 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. */
/*
- * $Id: obstack.h,v 1.3 1993/10/02 20:57:48 pk Exp $
+ * obstack.h,v 1.2 1993/11/03 00:52:06 paul Exp
*/
diff --git a/gnu/usr.bin/as/opcode/a29k.h b/gnu/usr.bin/as/opcode/a29k.h
index 8c3616747f09..33cb489b8916 100644
--- a/gnu/usr.bin/as/opcode/a29k.h
+++ b/gnu/usr.bin/as/opcode/a29k.h
@@ -284,7 +284,10 @@ static CONST struct a29k_opcode a29k_opcodes[] =
CONST unsigned int num_opcodes = (((sizeof a29k_opcodes) / (sizeof a29k_opcodes[0])) - 1);
/*
- * $Log: a29k.h,v $
+ * a29k.h,v
+ * Revision 1.1 1993/11/03 00:55:48 paul
+ * Brought over NetBSD's gas ready for pk's shared libs.
+ *
* Revision 1.1 1993/10/02 21:00:40 pk
* GNU gas 1.92.3 based assembler supporting PIC code (for i386 and sparc).
*
diff --git a/gnu/usr.bin/as/opcode/i386.h b/gnu/usr.bin/as/opcode/i386.h
index cc8fe1ca36c1..e357376b638e 100644
--- a/gnu/usr.bin/as/opcode/i386.h
+++ b/gnu/usr.bin/as/opcode/i386.h
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* $Id: i386.h,v 1.2 1993/10/04 22:53:32 pk Exp $ */
+/* i386.h,v 1.1 1993/11/03 00:55:51 paul Exp */
static const template i386_optab[] = {
diff --git a/gnu/usr.bin/as/opcode/i960.h b/gnu/usr.bin/as/opcode/i960.h
index e9c8cb4bef29..f8e7d1009757 100644
--- a/gnu/usr.bin/as/opcode/i960.h
+++ b/gnu/usr.bin/as/opcode/i960.h
@@ -18,7 +18,7 @@
* appropriate.
*/
-/* $Id: i960.h,v 1.1 1993/10/02 21:00:44 pk Exp $ */
+/* i960.h,v 1.1 1993/11/03 00:55:56 paul Exp */
#define CTRL 0
#define COBR 1
diff --git a/gnu/usr.bin/as/opcode/sparc.h b/gnu/usr.bin/as/opcode/sparc.h
index 3c52464e6a91..26bbb629edde 100644
--- a/gnu/usr.bin/as/opcode/sparc.h
+++ b/gnu/usr.bin/as/opcode/sparc.h
@@ -20,7 +20,7 @@ along with GAS or GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: sparc.h,v 1.1 1993/10/02 21:00:55 pk Exp $
+ * sparc.h,v 1.1 1993/11/03 00:56:11 paul Exp
*/
/* FIXME-someday: perhaps the ,a's and such should be embedded in the
diff --git a/gnu/usr.bin/as/output-file.c b/gnu/usr.bin/as/output-file.c
index 7439e86953ac..8cbaa6c8fed6 100644
--- a/gnu/usr.bin/as/output-file.c
+++ b/gnu/usr.bin/as/output-file.c
@@ -27,7 +27,7 @@
/* note that we do need config info. xoxorich. */
#ifndef lint
-static char rcsid[] = "$Id: output-file.c,v 1.3 1993/10/02 20:57:49 pk Exp $";
+static char rcsid[] = "output-file.c,v 1.2 1993/11/03 00:52:08 paul Exp";
#endif
#include <stdio.h>
diff --git a/gnu/usr.bin/as/output-file.h b/gnu/usr.bin/as/output-file.h
index e7d7b971e570..a8c31f7b524c 100644
--- a/gnu/usr.bin/as/output-file.h
+++ b/gnu/usr.bin/as/output-file.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: output-file.h,v 1.1 1993/10/02 20:57:49 pk Exp $
+ * output-file.h,v 1.1 1993/11/03 00:52:10 paul Exp
*/
diff --git a/gnu/usr.bin/as/read.c b/gnu/usr.bin/as/read.c
index cf3c416ea017..9fece970c791 100644
--- a/gnu/usr.bin/as/read.c
+++ b/gnu/usr.bin/as/read.c
@@ -19,7 +19,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: read.c,v 1.3 1993/11/30 20:55:43 jkh Exp $";
+static char rcsid[] = "read.c,v 1.4 1993/12/12 17:01:16 jkh Exp";
#endif
#define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will
diff --git a/gnu/usr.bin/as/read.h b/gnu/usr.bin/as/read.h
index b03fbab824c3..b411f254edf1 100644
--- a/gnu/usr.bin/as/read.h
+++ b/gnu/usr.bin/as/read.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: read.h,v 1.2 1993/11/03 00:52:16 paul Exp $
+ * read.h,v 1.3 1993/11/30 20:55:45 jkh Exp
*/
diff --git a/gnu/usr.bin/as/struc-symbol.h b/gnu/usr.bin/as/struc-symbol.h
index e0030cd1dd09..11f94be47ba8 100644
--- a/gnu/usr.bin/as/struc-symbol.h
+++ b/gnu/usr.bin/as/struc-symbol.h
@@ -17,7 +17,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: struc-symbol.h,v 1.2 1993/11/03 00:52:18 paul Exp $
+ * struc-symbol.h,v 1.3 1993/11/30 20:55:46 jkh Exp
*/
diff --git a/gnu/usr.bin/as/subsegs.c b/gnu/usr.bin/as/subsegs.c
index af2d4e7db12f..eaf1e053b78f 100644
--- a/gnu/usr.bin/as/subsegs.c
+++ b/gnu/usr.bin/as/subsegs.c
@@ -22,7 +22,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: subsegs.c,v 1.3 1993/10/02 20:57:54 pk Exp $";
+static char rcsid[] = "subsegs.c,v 1.2 1993/11/03 00:52:19 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/subsegs.h b/gnu/usr.bin/as/subsegs.h
index 4b8e3ce5b456..2a790408e148 100644
--- a/gnu/usr.bin/as/subsegs.h
+++ b/gnu/usr.bin/as/subsegs.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: subsegs.h,v 1.3 1993/10/02 20:57:55 pk Exp $
+ * subsegs.h,v 1.2 1993/11/03 00:52:20 paul Exp
*/
diff --git a/gnu/usr.bin/as/symbols.c b/gnu/usr.bin/as/symbols.c
index 066f54e33f74..2ba4be5bd002 100644
--- a/gnu/usr.bin/as/symbols.c
+++ b/gnu/usr.bin/as/symbols.c
@@ -19,7 +19,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef lint
-static char rcsid[] = "$Id: symbols.c,v 1.3 1993/10/02 20:57:56 pk Exp $";
+static char rcsid[] = "symbols.c,v 1.2 1993/11/03 00:52:22 paul Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/symbols.h b/gnu/usr.bin/as/symbols.h
index 535933f39b02..a7aa79f3ffbd 100644
--- a/gnu/usr.bin/as/symbols.h
+++ b/gnu/usr.bin/as/symbols.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: symbols.h,v 1.3 1993/10/02 20:57:57 pk Exp $
+ * symbols.h,v 1.2 1993/11/03 00:52:23 paul Exp
*/
diff --git a/gnu/usr.bin/as/tc.h b/gnu/usr.bin/as/tc.h
index f36629c71702..0e9b871a9b37 100644
--- a/gnu/usr.bin/as/tc.h
+++ b/gnu/usr.bin/as/tc.h
@@ -18,7 +18,7 @@
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id: tc.h,v 1.1 1993/10/02 20:57:58 pk Exp $
+ * tc.h,v 1.1 1993/11/03 00:52:25 paul Exp
*/
diff --git a/gnu/usr.bin/as/testscripts/doboth b/gnu/usr.bin/as/testscripts/doboth
index 6b46a03eb125..da50da6281b0 100755
--- a/gnu/usr.bin/as/testscripts/doboth
+++ b/gnu/usr.bin/as/testscripts/doboth
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Id: doboth,v 1.1 1993/10/02 21:01:07 pk Exp $
+# doboth,v 1.1 1993/11/03 00:56:17 paul Exp
x=$1 ; shift
y=$1 ; shift
diff --git a/gnu/usr.bin/as/testscripts/doobjcmp b/gnu/usr.bin/as/testscripts/doobjcmp
index 6c90cf9a05ff..bc675302ec2f 100755
--- a/gnu/usr.bin/as/testscripts/doobjcmp
+++ b/gnu/usr.bin/as/testscripts/doobjcmp
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Id: doobjcmp,v 1.1 1993/10/02 21:01:08 pk Exp $
+# doobjcmp,v 1.1 1993/11/03 00:56:18 paul Exp
# compare two object files, in depth.
x=$1
diff --git a/gnu/usr.bin/as/testscripts/dostriptest b/gnu/usr.bin/as/testscripts/dostriptest
index aa734c0c2b9f..3a4bae285815 100755
--- a/gnu/usr.bin/as/testscripts/dostriptest
+++ b/gnu/usr.bin/as/testscripts/dostriptest
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Id: dostriptest,v 1.1 1993/10/02 21:01:09 pk Exp $
+# dostriptest,v 1.1 1993/11/03 00:56:19 paul Exp
x=striptest.xx.$$
y=striptest.yy.$$
diff --git a/gnu/usr.bin/as/testscripts/dotest b/gnu/usr.bin/as/testscripts/dotest
index 051ee11ef790..a46c667b64a8 100755
--- a/gnu/usr.bin/as/testscripts/dotest
+++ b/gnu/usr.bin/as/testscripts/dotest
@@ -1,6 +1,6 @@
#!/bin/sh
# ad hoc debug tool
-# $Id: dotest,v 1.1 1993/10/02 21:01:10 pk Exp $
+# dotest,v 1.1 1993/11/03 00:56:21 paul Exp
x=$1
y=$2
diff --git a/gnu/usr.bin/as/testscripts/dounsortreloc b/gnu/usr.bin/as/testscripts/dounsortreloc
index 0a4771c6425e..ab8a604fde71 100755
--- a/gnu/usr.bin/as/testscripts/dounsortreloc
+++ b/gnu/usr.bin/as/testscripts/dounsortreloc
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Id: dounsortreloc,v 1.1 1993/10/02 21:01:11 pk Exp $
+# dounsortreloc,v 1.1 1993/11/03 00:56:22 paul Exp
# 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.
diff --git a/gnu/usr.bin/as/testscripts/dounsortsymbols b/gnu/usr.bin/as/testscripts/dounsortsymbols
index 2dc5acd65e00..82cfbe84f935 100755
--- a/gnu/usr.bin/as/testscripts/dounsortsymbols
+++ b/gnu/usr.bin/as/testscripts/dounsortsymbols
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Id: dounsortsymbols,v 1.1 1993/10/02 21:01:12 pk Exp $
+# dounsortsymbols,v 1.1 1993/11/03 00:56:24 paul Exp
# 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.
diff --git a/gnu/usr.bin/as/version.c b/gnu/usr.bin/as/version.c
index b3711c4db191..f6b0b5f33a0e 100644
--- a/gnu/usr.bin/as/version.c
+++ b/gnu/usr.bin/as/version.c
@@ -16,10 +16,10 @@ const
*/
#ifndef lint
-static char rcsid[] = "$Id: version.c,v 1.2 1993/11/03 00:52:27 paul Exp $";
+static char rcsid[] = "version.c,v 1.3 1994/02/14 21:18:05 nate Exp";
#endif
-char version_string[] = "GNU assembler version 1.92.3, FreeBSD $Revision: 1.2 $\n";
+char version_string[] = "GNU assembler version 1.92.3, FreeBSD 1.3\n";
#ifdef HO_VMS
dummy3()
diff --git a/gnu/usr.bin/as/write.c b/gnu/usr.bin/as/write.c
index dd139f7e82dc..85c752953dbf 100644
--- a/gnu/usr.bin/as/write.c
+++ b/gnu/usr.bin/as/write.c
@@ -21,7 +21,7 @@
/* This thing should be set up to do byteordering correctly. But... */
#ifndef lint
-static char rcsid[] = "$Id: write.c,v 1.4 1993/12/12 17:01:24 jkh Exp $";
+static char rcsid[] = "write.c,v 1.5 1994/02/20 16:06:12 rgrimes Exp";
#endif
#include "as.h"
diff --git a/gnu/usr.bin/as/xmalloc.c b/gnu/usr.bin/as/xmalloc.c
index 6962484eca59..c1dd41b1404a 100644
--- a/gnu/usr.bin/as/xmalloc.c
+++ b/gnu/usr.bin/as/xmalloc.c
@@ -42,7 +42,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: xmalloc.c,v 1.3 1993/10/02 20:58:02 pk Exp $";
+static char rcsid[] = "xmalloc.c,v 1.2 1993/11/03 00:52:32 paul Exp";
#endif
#include <stdio.h>
diff --git a/gnu/usr.bin/as/xrealloc.c b/gnu/usr.bin/as/xrealloc.c
index 1b26f437686f..45822e416214 100644
--- a/gnu/usr.bin/as/xrealloc.c
+++ b/gnu/usr.bin/as/xrealloc.c
@@ -43,7 +43,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: xrealloc.c,v 1.3 1993/10/02 20:58:03 pk Exp $";
+static char rcsid[] = "xrealloc.c,v 1.2 1993/11/03 00:52:34 paul Exp";
#endif
diff --git a/gnu/usr.bin/bc/scan.c b/gnu/usr.bin/bc/scan.c
index 59aa6e536e17..1e13868e2985 100644
--- a/gnu/usr.bin/bc/scan.c
+++ b/gnu/usr.bin/bc/scan.c
@@ -1,7 +1,7 @@
/* A lexical scanner generated by flex */
/* scanner skeleton version:
- * $Header: /usr/fsys/odin/a/vern/flex/RCS/flex.skel,v 2.16 90/08/03 14:09:36 vern Exp $
+ * /home/ncvs/src/gnu/usr.bin/bc/scan.c,v 1.1.1.1 1993/06/19 00:26:18 paul Exp
*/
#define FLEX_SCANNER
diff --git a/gnu/usr.bin/cc/Makefile b/gnu/usr.bin/cc/Makefile
index 608c9b129c98..478b453989e5 100644
--- a/gnu/usr.bin/cc/Makefile
+++ b/gnu/usr.bin/cc/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.4 1994/11/15 04:51:20 phk Exp
#
PGMDIR= cc_int cpp cc1 cc cc1plus c++ f77 libgcc
diff --git a/gnu/usr.bin/cc/Makefile.inc b/gnu/usr.bin/cc/Makefile.inc
index fb959378d91a..3572ec0aa527 100644
--- a/gnu/usr.bin/cc/Makefile.inc
+++ b/gnu/usr.bin/cc/Makefile.inc
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile.inc,v 1.10 1994/11/15 04:51:21 phk Exp
#
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../include
diff --git a/gnu/usr.bin/cc/README b/gnu/usr.bin/cc/README
index e47729a5d750..b0a109c808f9 100644
--- a/gnu/usr.bin/cc/README
+++ b/gnu/usr.bin/cc/README
@@ -1,5 +1,5 @@
-$Id$
+README,v 1.3 1994/11/15 04:51:22 phk Exp
This directory contains gcc in a form that uses "bmake" makefiles.
This is not the place you want to start, if you want to hack gcc.
diff --git a/gnu/usr.bin/cc/c++/Makefile b/gnu/usr.bin/cc/c++/Makefile
index 5557c627dfdc..2cb06c60ff23 100644
--- a/gnu/usr.bin/cc/c++/Makefile
+++ b/gnu/usr.bin/cc/c++/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.5 1994/11/15 04:51:26 phk Exp
#
PROG = c++
diff --git a/gnu/usr.bin/cc/cc/Makefile b/gnu/usr.bin/cc/cc/Makefile
index 8da044cd90fc..ee020c57aaf2 100644
--- a/gnu/usr.bin/cc/cc/Makefile
+++ b/gnu/usr.bin/cc/cc/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.7 1994/11/15 04:51:27 phk Exp
#
PROG = cc
diff --git a/gnu/usr.bin/cc/cc/cc.1 b/gnu/usr.bin/cc/cc/cc.1
index 223115c43801..da14c143c547 100644
--- a/gnu/usr.bin/cc/cc/cc.1
+++ b/gnu/usr.bin/cc/cc/cc.1
@@ -20,7 +20,7 @@
.if n .sp
.if t .sp 0.4
..
-.Id $Id: gcc.1,v 1.4 1993/10/13 23:19:12 pesch Exp $
+.Id cc.1,v 1.2 1994/11/15 04:51:29 phk Exp
.TH GCC 1 "\*(Dt" "GNU Tools" "GNU Tools"
.SH NAME
gcc, g++ \- GNU project C and C++ Compiler (v2.6)
diff --git a/gnu/usr.bin/cc/cc1/Makefile b/gnu/usr.bin/cc/cc1/Makefile
index 3ef760833356..1fcc13e81306 100644
--- a/gnu/usr.bin/cc/cc1/Makefile
+++ b/gnu/usr.bin/cc/cc1/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.5 1994/11/15 04:51:32 phk Exp
#
PROG = cc1
diff --git a/gnu/usr.bin/cc/cc1plus/Makefile b/gnu/usr.bin/cc/cc1plus/Makefile
index 22bdba3606db..545deafcfd04 100644
--- a/gnu/usr.bin/cc/cc1plus/Makefile
+++ b/gnu/usr.bin/cc/cc1plus/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.5 1994/11/15 04:51:37 phk Exp
#
PROG = cc1plus
diff --git a/gnu/usr.bin/cc/cc_int/Makefile b/gnu/usr.bin/cc/cc_int/Makefile
index 29c66153578a..52fc5c86dab1 100644
--- a/gnu/usr.bin/cc/cc_int/Makefile
+++ b/gnu/usr.bin/cc/cc_int/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.7 1994/11/15 04:51:40 phk Exp
#
SRCS = aux-output.c bc-emit.c bc-optab.c c-common.c caller-save.c calls.c combine.c convert.c cse.c dbxout.c dwarfout.c emit-rtl.c explow.c expmed.c expr.c final.c flow.c fold-const.c function.c getpwd.c global.c insn-attrtab.c insn-emit.c insn-extract.c insn-opinit.c insn-output.c insn-peep.c insn-recog.c integrate.c jump.c local-alloc.c loop.c obstack.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 sched.c sdbout.c stmt.c stor-layout.c stupid.c toplev.c tree.c unroll.c varasm.c version.c xcoffout.c
diff --git a/gnu/usr.bin/cc/cpp/Makefile b/gnu/usr.bin/cc/cpp/Makefile
index 43ec78c3a49f..3befdcff6f25 100644
--- a/gnu/usr.bin/cc/cpp/Makefile
+++ b/gnu/usr.bin/cc/cpp/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.4 1994/11/15 04:52:05 phk Exp
#
PROG = cpp
diff --git a/gnu/usr.bin/cc/f77/Makefile b/gnu/usr.bin/cc/f77/Makefile
index 4af4448ad0f7..69afcb36b602 100644
--- a/gnu/usr.bin/cc/f77/Makefile
+++ b/gnu/usr.bin/cc/f77/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.3 1994/09/18 22:35:43 wollman Exp $
+# Makefile,v 1.1 1994/10/25 14:36:49 ljo Exp
#
PROG = f77
diff --git a/gnu/usr.bin/cc/libgcc/Makefile b/gnu/usr.bin/cc/libgcc/Makefile
index 78e28095758f..7a610db99f2e 100644
--- a/gnu/usr.bin/cc/libgcc/Makefile
+++ b/gnu/usr.bin/cc/libgcc/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# Makefile,v 1.4 1994/11/15 04:52:14 phk Exp
#
LIB= gcc
diff --git a/gnu/usr.bin/cvs/contrib/pcl-cvs/texinfo.tex b/gnu/usr.bin/cvs/contrib/pcl-cvs/texinfo.tex
new file mode 100644
index 000000000000..05a11d141c29
--- /dev/null
+++ b/gnu/usr.bin/cvs/contrib/pcl-cvs/texinfo.tex
@@ -0,0 +1,3230 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 1986, 1988, 1990, 1991 Free Software Foundation, Inc.
+
+%This texinfo.tex 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 texinfo.tex 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 texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+\def\texinfoversion{2.63}
+\message{Loading texinfo package [Version \texinfoversion]:}
+\message{}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ } % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.
+% The argument can be delimited with [...] or with "..." or braces
+% or it can be a whole line.
+% #1 should be a macro which expects
+% an ordinary undelimited TeX argument.
+
+\def\parsearg #1{\let\next=#1\begingroup\obeylines\futurelet\temp\parseargx}
+
+\def\parseargx{%
+\ifx \obeyedspace\temp \aftergroup\parseargdiscardspace \else%
+\aftergroup \parseargline %
+\fi \endgroup}
+
+{\obeyspaces %
+\gdef\parseargdiscardspace {\begingroup\obeylines\futurelet\temp\parseargx}}
+
+\gdef\obeyedspace{\ }
+
+\def\parseargline{\begingroup \obeylines \parsearglinex}
+{\obeylines %
+\gdef\parsearglinex #1^^M{\endgroup \next {#1}}}
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+%% @end foo executes the definition of \Efoo.
+%% foo can be delimited by doublequotes or brackets.
+
+\def\end{\parsearg\endxxx}
+
+\def\endxxx #1{%
+\expandafter\ifx\csname E#1\endcsname\relax
+\expandafter\ifx\csname #1\endcsname\relax
+\errmessage{Undefined command @end #1}\else
+\errorE{#1}\fi\fi
+\csname E#1\endcsname}
+\def\errorE#1{
+{\errhelp=\EMsimple \errmessage{@end #1 not within #1 environment}}}
+
+% Single-spacing is done by various environments.
+
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+{\advance \baselineskip by -\singlespaceskip
+\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% Define @` and @' to be the same as ` and '
+% but suppressing ligatures.
+\def\`{{`}}
+\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break
+\def\w #1{\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page.
+
+\def\group{\begingroup% \inENV ???
+\ifnum\catcode13=\active \else
+\errmessage{@group invalid in context where filling is enabled}\fi
+\def \Egroup{\egroup\endgroup}
+\vbox\bgroup}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+\def\needx #1{\par %
+% This method tries to make TeX break the page naturally
+% if the depth of the box does not fit.
+{\baselineskip=0pt%
+\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+\prevdepth=-1000pt
+}}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+\def\exdent{\errmessage{@exdent in filled text}}
+ % @lisp, etc, define \exdent locally from \internalexdent
+
+{\obeyspaces
+\gdef\internalexdent{\parsearg\exdentzzz}}
+
+\def\exdentzzz #1{{\advance \leftskip by -\lispnarrowing
+\advance \hsize by -\leftskip
+\advance \hsize by -\rightskip
+\leftline{{\rm#1}}}}
+
+% @include file insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+\def\includezzz #1{{\def\thisfile{#1}\input #1
+}}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+\def\ignore{\begingroup\ignoresections
+% Make sure that spaces turn into tokens that match what \ignorexxx wants.
+\catcode32=10
+\ignorexxx}
+\long\def\ignorexxx #1\end ignore{\endgroup\ignorespaces}
+
+\def\direntry{\begingroup\direntryxxx}
+\long\def\direntryxxx #1\end direntry{\endgroup\ignorespaces}
+
+% Conditionals to test whether a flag is set.
+
+\def\ifset{\begingroup\ignoresections\parsearg\ifsetxxx}
+
+\def\ifsetxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\ifsetfail
+\else \let\temp=\relax \fi
+\temp}
+\def\Eifset{}
+\def\ifsetfail{\begingroup\ignoresections\ifsetfailxxx}
+\long\def\ifsetfailxxx #1\end ifset{\endgroup\ignorespaces}
+
+\def\ifclear{\begingroup\ignoresections\parsearg\ifclearxxx}
+
+\def\ifclearxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\relax
+\else \let\temp=\ifclearfail \fi
+\temp}
+\def\Eifclear{}
+\def\ifclearfail{\begingroup\ignoresections\ifclearfailxxx}
+\long\def\ifclearfailxxx #1\end ifclear{\endgroup\ignorespaces}
+
+% @set foo to set the flag named foo.
+% @clear foo to clear the flag named foo.
+\def\set{\parsearg\setxxx}
+\def\setxxx #1{
+\expandafter\let\csname IF#1\endcsname=\set}
+
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx #1{
+\expandafter\let\csname IF#1\endcsname=\relax}
+
+% Some texinfo constructs that are trivial in tex
+
+\def\iftex{}
+\def\Eiftex{}
+\def\ifinfo{\begingroup\ignoresections\ifinfoxxx}
+\long\def\ifinfoxxx #1\end ifinfo{\endgroup\ignorespaces}
+
+\long\def\menu #1\end menu{}
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\losespace#3{}},
+ node \samp{\losespace#1{}}}
+\def\losespace #1{#1}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\font\textrm=cmr12
+\font\texttt=cmtt12
+\else
+\font\textrm=cmr10 scaled \mainmagstep
+\font\texttt=cmtt10 scaled \mainmagstep
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\textbf=cmb10 scaled \mainmagstep
+\font\textit=cmti10 scaled \mainmagstep
+\font\textsl=cmsl10 scaled \mainmagstep
+\font\textsf=cmss10 scaled \mainmagstep
+\font\textsc=cmcsc10 scaled \mainmagstep
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\font\ninett=cmtt9
+\font\indrm=cmr9
+\font\indit=cmsl9
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\let\indsc=\indrm
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+\font\chapsc=cmcsc10 scaled\magstep3
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+\font\secsc=cmcsc10 scaled\magstep2
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad.
+% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+\font\ssecsc=cmcsc10 scaled \magstep1
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current. Plain TeX does, for example,
+% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need
+% to redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+ \resetmathfonts}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+ \resetmathfonts}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+ \resetmathfonts}
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
+ \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\font\shortcontrm=cmr12
+\font\shortcontbf=cmbx12
+\font\shortcontsl=cmsl12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+\def\t#1{{\tt \exhyphenpenalty=10000\rawbackslash \frenchspacing #1}\null}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \exhyphenpenalty=10000\uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\newdimen\tclosesave
+\newdimen\tcloserm
+\def\tclose#1{{\rm \tcloserm=\fontdimen2\font \tt \tclosesave=\fontdimen2\font
+\fontdimen2\font=\tcloserm
+% prevent breaking lines at hyphens.
+\exhyphenpenalty=10000
+\def\ {{\fontdimen2\font=\tclosesave{} }}%
+ \rawbackslash \frenchspacing #1\fontdimen2\font=\tclosesave}\null}
+\let\code=\tclose
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newtoks\realeverypar
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table and @ftable define @item, @itemx, etc., with these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ \parskip=0in
+ \par
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0
+ \nobreak
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}%
+ \fi
+ \endgroup
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\endgroup\afterenvbreak}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\endgroup\afterenvbreak}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\endgroup\afterenvbreak}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\def\doind #1#2{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+ \tex
+ \dobreak \chapheadingskip {10000}
+ \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+ \catcode`\$=\other\catcode`\_=\other
+ \catcode`\~=\other
+ %
+ % The following don't help, since the chars were translated
+ % when the raw index was written, and their fonts were discarded
+ % due to \indexnofonts.
+ %\catcode`\"=\active
+ %\catcode`\^=\active
+ %\catcode`\_=\active
+ %\catcode`\|=\active
+ %\catcode`\<=\active
+ %\catcode`\>=\active
+ % %
+ \def\indexbackslash{\rawbackslashxx}
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+ \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+\def\entry #1#2{
+{\parfillskip=0in \parskip=0in \parindent=0in
+\hangindent=1in \hangafter=1%
+\noindent\hbox{#1}\indexdotfill #2\par
+}}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXBook, page 416
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize \doublecolumnhsize = 3.11in
+\newdimen\doublecolumnvsize \doublecolumnvsize = 19.1in
+\newdimen\availdimen@
+
+\def\begindoublecolumns{\begingroup
+ \output={\global\setbox\partialpage=
+ \vbox{\unvbox255\kern -\topskip \kern \baselineskip}}\eject
+ \output={\doublecolumnout}%
+ \hsize=\doublecolumnhsize \vsize=\doublecolumnvsize}
+\def\enddoublecolumns{\output={\balancecolumns}\eject
+ \endgroup \pagegoal=\vsize}
+
+\def\doublecolumnout{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+% changes it to set cropmarks (P. A. MacKay, 12 Nov. 1986)
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\balancecolumns{%
+% Unset the glue.
+ \setbox255=\vbox{\unvbox255}
+ \dimen@=\ht255
+ \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpage
+% If the remaining data is too big for one page,
+% output one page normally, then work with what remains.
+ \ifdim \dimen@>\availdimen@
+ {
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ }
+% Recompute size of what remains, in case we just output some of it.
+ \dimen@=\ht255
+ \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2
+ \fi
+ \setbox0=\vbox{\unvbox255}
+ \splittopskip=\topskip
+ {\vbadness=10000 \loop \global\setbox3=\copy0
+ \global\setbox1=\vsplit3 to\dimen@
+ \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}
+ \setbox0=\vbox to\dimen@{\unvbox1} \setbox2=\vbox to\dimen@{\unvbox3}
+ \pagesofar}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapterzzz}
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixzzz}
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+\outer\def\top{\parsearg\unnumberedzzz}
+\outer\def\unnumbered{\parsearg\unnumberedzzz}
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0 \message{(#1)}
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\seczzz}
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsection{\parsearg\appendixsectionzzz}
+\outer\def\appendixsec{\parsearg\appendixsectionzzz}
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedseczzz}
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubseczzz}
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubseczzz}
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubseczzz}
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubseczzz}
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #2\enspace #1}%
+ }%
+ \bigskip
+ \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ \ifnum \pageno>0
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{Table of Contents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{Short Contents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\strut\raggedright
+ {#2\labelspace #1}\dotfill\doshortpageno{#3}}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{%
+ \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\strut\raggedright
+ #1\dotfill\doshortpageno{#2}}%
+}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ % This \vbox (and similar ones in dosecentry etc.) used to be a
+ % \line; changed to permit linebreaks for long headings. See
+ % comments above \majorheading. Here we also use \strut to
+ % keep the top end of the vbox from jamming up against the previous
+ % entry in the table of contents.
+ \vbox{\chapentryfonts
+ \hyphenpenalty=10000\tolerance=5000 % this line and next introduced
+ \parindent=0pt\strut\raggedright % with \line -> \vbox change
+ #1\dotfill
+ \dopageno{#2}}%
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{%
+ \vbox{\secentryfonts \leftskip=\tocindent
+ \hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\strut\raggedright #1\dotfill
+ \dopageno{#2}}%
+}
+
+\def\dosubsecentry#1#2{%
+ \vbox{\subsecentryfonts \leftskip=2\tocindent
+ \hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\strut\raggedright #1\dotfill
+ \dopageno{#2}}%
+}
+
+\def\dosubsubsecentry#1#2{%
+ \vbox{\subsubsecentryfonts \leftskip=3\tocindent
+ \hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\strut\raggedright #1\dotfill
+ \dopageno{#2}}%
+}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+{\tentt
+\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+ depth .1ex\hfil}
+}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\copy\dblarrowbox}
+\def\expansion{\leavevmode\raise.1ex\copy\longdblarrowbox}
+\def\print{\leavevmode\lower.1ex\copy\pushcharbox}
+
+\def\equiv{\leavevmode\lower.1ex\copy\equivbox}
+
+% Does anyone really want this?
+% \def\bull{\leavevmode\copy\bullbox}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^M gets inside @lisp
+% phr: changed space to \null, to avoid overfull hbox problems.
+{\obeyspaces%
+\gdef\lisppar{\null\endgraf}}
+
+% Cause \obeyspaces to make each Space cause a word-separation
+% rather than the default which is that it acts punctuation.
+% This is because space in tt font looks funny.
+{\obeyspaces %
+\gdef\sepspaces{\def {\ }}}
+
+\newskip\aboveenvskipamount \aboveenvskipamount= 0pt
+\def\aboveenvbreak{{\advance\aboveenvskipamount by \parskip
+\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}}
+
+\def\afterenvbreak{\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+\def\lisp{\aboveenvbreak
+\begingroup\inENV % This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Elisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\let\nonarrowing=\relax
+\fi
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \tt \rawbackslash
+\def\next##1{}\next}
+
+
+\let\example=\lisp
+\def\Eexample{\Elisp}
+
+\let\smallexample=\lisp
+\def\Esmallexample{\Elisp}
+
+% Macro for 9 pt. examples, necessary to print with 5" lines.
+% From Pavel@xerox. This is not really used unless the
+% @smallbook command is given.
+
+\def\smalllispx{\aboveenvbreak\begingroup\inENV
+% This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Esmalllisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\let\nonarrowing=\relax
+\fi
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslash
+\def\next##1{}\next}
+
+% This is @display; same as @lisp except use roman font.
+
+\def\display{\begingroup\inENV %This group ends at the end of the @display body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Edisplay{\endgroup\afterenvbreak}%
+\parskip=0pt
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\let\nonarrowing=\relax
+\fi
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% This is @format; same as @lisp except use roman font and don't narrow margins
+
+\def\format{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Eformat{\endgroup\afterenvbreak}
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @flushleft and @flushright
+
+\def\flushleft{%
+\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushleft{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+\def\flushright{%
+\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushright{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\advance \leftskip by 0pt plus 1fill
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @quotation - narrow the margins.
+
+\def\quotation{%
+\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\def\Equotation{\par\endgroup\afterenvbreak}%
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\advance \rightskip by \lispnarrowing
+\let\nonarrowing=\relax
+\fi}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+\def\defvrparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\begingroup\obeylines\spacesplit{#3{#4}}}
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\defvrparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names. Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss. Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+\long\gdef\footnote #1{\global\advance \footnoteno by \@ne
+\unskip
+\edef\thisfootno{$^{\the\footnoteno}$}%
+\let\@sf\empty
+\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+\thisfootno\@sf \footnotezzz{#1}}
+% \parsearg\footnotezzz}
+
+\long\gdef\footnotezzz #1{\insert\footins{
+\interlinepenalty\interfootnotelinepenalty
+\splittopskip\ht\strutbox % top baseline for broken footnotes
+\splitmaxdepth\dp\strutbox \floatingpenalty\@MM
+\leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
+\footstrut\parindent=\defaultparindent\hang\textindent{\thisfootno}#1\strut}}
+
+}%end \catcode `\@=11
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\baselineskip 15pt
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=20000
+\clubpenalty=2000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined \else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+\global\lispnarrowing = 0.3in
+\global\baselineskip 12pt
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\doublecolumnhsize=2.4in \global\doublecolumnvsize=15.0in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\baselineskip=12pt
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+\global\doublecolumnhsize=\hsize
+\global\divide\doublecolumnhsize by 2
+\global\advance\doublecolumnhsize by -0.1in
+\global\doublecolumnvsize=\vsize
+\global\multiply\doublecolumnvsize by 2
+\global\advance\doublecolumnvsize by 0.1in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+%% For a final copy, take out the rectangles
+%% that mark overfull boxes (in case you have decided
+%% that the text looks ok even though it passes the margin).
+\def\finalout{\overfullrule=0pt}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+% \lvvmode is equivalent in function to \leavevmode.
+% Using \leavevmode runs into trouble when written out to
+% an index file due to the expansion of \leavevmode into ``\unhbox
+% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
+% magic tricks with @.
+\def\lvvmode{\vbox to 0pt{}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/gnu/usr.bin/cvs/cvsinit/Makefile b/gnu/usr.bin/cvs/cvsinit/Makefile
index da498fc8665c..ab20bf893cb2 100644
--- a/gnu/usr.bin/cvs/cvsinit/Makefile
+++ b/gnu/usr.bin/cvs/cvsinit/Makefile
@@ -1,4 +1,4 @@
-# $Id$
+# Makefile,v 1.1 1994/10/22 04:51:39 nate Exp
afterinstall:
install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
diff --git a/gnu/usr.bin/dc/texinfo.tex b/gnu/usr.bin/dc/texinfo.tex
new file mode 100644
index 000000000000..ce8124ecb7bd
--- /dev/null
+++ b/gnu/usr.bin/dc/texinfo.tex
@@ -0,0 +1,4003 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc.
+
+%This texinfo.tex 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 texinfo.tex 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 texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+\def\texinfoversion{2.108}
+\message{Loading texinfo package [Version \texinfoversion]:}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ } % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }}
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+% Why was this kern here? It messes up equalizing space above and below
+% environments. --karl, 6may93
+%{\advance \baselineskip by -\singlespaceskip
+%\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % We do @comment here in case we are called inside an environment,
+ % such as @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+%Use \input\thisfile to avoid blank after \input, which may be an active
+%char (in which case the blank would become the \input argument).
+%The grouping keeps the value of \thisfile correct even when @include
+%is nested.
+\def\includezzz #1{\begingroup
+\def\thisfile{#1}\input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ \long\def\doignoretext##1\end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+%
+\def\set{\parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+}
+\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+ \ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}
+ \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex). But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\font\textrm=cmr12
+\font\texttt=cmtt12
+\else
+\font\textrm=cmr10 scaled \mainmagstep
+\font\texttt=cmtt10 scaled \mainmagstep
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\textbf=cmb10 scaled \mainmagstep
+\font\textit=cmti10 scaled \mainmagstep
+\font\textsl=cmsl10 scaled \mainmagstep
+\font\textsf=cmss10 scaled \mainmagstep
+\font\textsc=cmcsc10 scaled \mainmagstep
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\font\ninett=cmtt9
+\font\indrm=cmr9
+\font\indit=cmsl9
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\let\indsc=\indrm
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+\font\chapsc=cmcsc10 scaled\magstep3
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+\font\secsc=cmcsc10 scaled\magstep2
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad.
+% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+\font\ssecsc=cmcsc10 scaled \magstep1
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current. Plain TeX does, for example,
+% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need
+% to redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+ \resetmathfonts}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+ \resetmathfonts}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+ \resetmathfonts}
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
+ \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\font\shortcontrm=cmr12
+\font\shortcontbf=cmbx12
+\font\shortcontsl=cmsl12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \nohyphenation \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overful hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate an a dash.
+% -- rms.
+{
+\catcode `\-=\active
+\catcode `\_=\active
+\global\def\code{\begingroup \catcode `\-=\active \let-\codedash \let_\codeunder \codex}
+}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ {\parskip = 0in
+ \par
+ }%
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}%
+ \fi
+ \endgroup
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\def\doind #1#2{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+ \tex
+ \dobreak \chapheadingskip {10000}
+ \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+ \catcode`\$=\other\catcode`\_=\other
+ \catcode`\~=\other
+ %
+ % The following don't help, since the chars were translated
+ % when the raw index was written, and their fonts were discarded
+ % due to \indexnofonts.
+ %\catcode`\"=\active
+ %\catcode`\^=\active
+ %\catcode`\_=\active
+ %\catcode`\|=\active
+ %\catcode`\<=\active
+ %\catcode`\>=\active
+ % %
+ \def\indexbackslash{\rawbackslashxx}
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+ \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent=2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXbook, page 416.
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage
+ =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \eject
+ %
+ % Now switch to the double-column output routine.
+ \output={\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it once.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +- <
+ % 1pt) as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+ \doublecolumnpagegoal
+}
+
+\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
+
+\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
+ \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
+ \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
+ \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+ \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+}
+\def\doublecolumnpagegoal{%
+ \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\doublecolumnout{%
+ \setbox5=\copy255
+ {\vbadness=10000 \doublecolumnsplit}
+ \ifvbox255
+ \setbox0=\vtop to\dimen@{\unvbox0}
+ \setbox2=\vtop to\dimen@{\unvbox2}
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
+ \else
+ \setbox0=\vbox{\unvbox5}
+ \ifvbox0
+ \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ {\vbadness=10000
+ \loop \global\setbox5=\copy0
+ \setbox1=\vsplit5 to\dimen@
+ \setbox3=\vsplit5 to\dimen@
+ \ifvbox5 \global\advance\dimen@ by1pt \repeat
+ \setbox0=\vbox to\dimen@{\unvbox1}
+ \setbox2=\vbox to\dimen@{\unvbox3}
+ \global\setbox\partialpage=\vbox{\pagesofar}
+ \doublecolumnpagegoal
+ }
+ \fi
+ \fi
+}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appenixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #2\enspace #1}%
+ }%
+ \bigskip
+ \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \ifnum \pageno>0
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{Table of Contents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{Short Contents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm Appendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in in \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+\def\tocentry#1#2{\begingroup
+ \hyphenpenalty = 10000
+ \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces %
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% To ending an @example-like environment, we first end the paragraph
+% (via \afterenvbreak's vertical glue), and then the group. That way we
+% keep the zero \parskip that the environments set -- \parskip glue
+% will be inserted at the beginning of the next paragraph in the
+% document, after the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}%
+
+% This macro is
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \rawbackslash % have \ input char produce \ char from current font
+ \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp. This is not used unless the @smallbook
+% command is given. Originally contributed by Pavel@xerox.
+%
+\def\smalllispx{\begingroup
+ \nonfillstart
+ \let\Esmalllisp = \nonfillfinish
+ \let\Esmallexample = \nonfillfinish
+ %
+ % Smaller interline space and fonts for small examples.
+ \baselineskip 10pt
+ \indexfonts \tt
+ \rawbackslash % output the \ character from the current font
+ \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushleft = \nonfillfinish
+ \gobble
+}
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble}
+
+% @quotation does normal linebreaking and narrows the margins.
+%
+\def\quotation{%
+\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\let\Equotation = \nonfillfinish
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\advance \rightskip by \lispnarrowing
+\exdentamount=\lispnarrowing
+\let\nonarrowing=\relax
+\fi}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+\def\defvrparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#4}}}
+
+% This seems to work right in all cases.
+\let\deftpparsebody=\defvrparsebody
+% This fails to work. When given `@deftp {Data Type} foo_t',
+% it thinks the type name is just `f'.
+%%% This is the same as all the others except for the last line. We need
+%%% to parse the arguments differently for @deftp, since the ``attributes''
+%%% there are optional.
+%%%
+%%\def\deftpparsebody #1#2#3#4 {\begingroup\inENV %
+%%\medbreak %
+%%% Define the end token that this defining construct specifies
+%%% so that it will exit this group.
+%%\def#1{\endgraf\endgroup\medbreak}%
+%%\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+%%\parindent=0in
+%%\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+%%\exdentamount=\defbodyindent
+%%\begingroup\obeylines\parsetpheaderline{#3{#4}}}
+
+%%{\obeylines %
+%% % Parse the type name and any attributes (field names, etc.).
+%% % #1 is the beginning of the macro call that will produce the output,
+%% % i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody.
+%% % #2 is the type name, e.g., `struct termios'.
+%% % #3 is the (possibly empty) attribute list.
+%% %
+%% \gdef\parsetpheaderline#1#2#3^^M{%
+%% \endgroup % Started in \deftpparsebody.
+%% %
+%% % If the attribute list is in fact empty, there will be no space after
+%% % #2; so we can't put a space in our TeX parameter list. But if it
+%% % isn't empty, then #3 will begin with an unwanted space.
+%% \def\theargs{\ignorespaces #3}%
+%% %
+%% % Call the macro to produce the output.
+%% #1{#2}\theargs %
+%% }%
+%%}
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names. Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss. Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed.
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\setleading{15pt}
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+\else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+
+% These values for secheadingskip and subsecheadingskip are
+% experiments. RJC 7 Aug 1992
+\global\secheadingskip = 17pt plus 6pt minus 3pt
+\global\subsecheadingskip = 14pt plus 6pt minus 3pt
+
+\global\lispnarrowing = 0.3in
+\setleading{12pt}
+\advance\topskip by -1cm
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+% \lvvmode is equivalent in function to \leavevmode.
+% Using \leavevmode runs into trouble when written out to
+% an index file due to the expansion of \leavevmode into ``\unhbox
+% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
+% magic tricks with @.
+\def\lvvmode{\vbox to 0pt{}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/gnu/usr.bin/dialog/Makefile b/gnu/usr.bin/dialog/Makefile
index 436519a7e32a..c5c1089ff2ab 100644
--- a/gnu/usr.bin/dialog/Makefile
+++ b/gnu/usr.bin/dialog/Makefile
@@ -1,5 +1,5 @@
# Makefile for dialog
-# $Id: Makefile,v 1.3 1994/10/11 23:51:06 ache Exp $
+# Makefile,v 1.4 1994/10/28 03:12:45 ache Exp
PROG= dialog
MAN1= dialog.1
diff --git a/gnu/usr.bin/gdb/doc/gdbint.texinfo b/gnu/usr.bin/gdb/doc/gdbint.texinfo
index a2f625771e94..e2f3d546d6ad 100644
--- a/gnu/usr.bin/gdb/doc/gdbint.texinfo
+++ b/gnu/usr.bin/gdb/doc/gdbint.texinfo
@@ -1,6 +1,6 @@
\input texinfo
@setfilename gdbint.info
-@c $Id: gdbint.texinfo,v 1.1.1.1 1993/10/30 21:59:41 jkh Exp $
+@c gdbint.texinfo,v 1.1 1994/06/10 13:34:28 paul Exp
@ifinfo
@format
@@ -42,7 +42,7 @@ regarded as a program in the language TeX).
@page
@tex
\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
-\xdef\manvers{\$Revision: 1.1.1.1 $} % For use in headers, footers too
+\xdef\manvers{\1.1} % For use in headers, footers too
{\parskip=0pt
\hfill Cygnus Support\par
\hfill \manvers\par
diff --git a/gnu/usr.bin/gdb/doc/refcard.tex b/gnu/usr.bin/gdb/doc/refcard.tex
index 589960805f24..a7f892e48784 100644
--- a/gnu/usr.bin/gdb/doc/refcard.tex
+++ b/gnu/usr.bin/gdb/doc/refcard.tex
@@ -1,7 +1,7 @@
%%%%%%%%%%%%%%%% gdb-refcard.tex %%%%%%%%%%%%%%%%
%This file is TeX source for a reference card describing GDB, the GNU debugger.
-%$Id: refcard.tex,v 1.1.1.1 1993/10/30 21:59:42 jkh Exp $
+%refcard.tex,v 1.1 1994/06/10 13:34:43 paul Exp
%Copyright (C) 1991, 1992 Free Software Foundation, Inc.
%Permission is granted to make and distribute verbatim copies of
%this reference provided the copyright notices and permission notices
diff --git a/gnu/usr.bin/gdb/doc/stabs.texinfo b/gnu/usr.bin/gdb/doc/stabs.texinfo
index 23d8e7baa996..ca5132c8ce61 100644
--- a/gnu/usr.bin/gdb/doc/stabs.texinfo
+++ b/gnu/usr.bin/gdb/doc/stabs.texinfo
@@ -43,7 +43,7 @@ regarded as a program in the language TeX).
@page
@tex
\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
-\xdef\manvers{\$Revision: 1.1.1.1 $} % For use in headers, footers too
+\xdef\manvers{\1.1} % For use in headers, footers too
{\parskip=0pt
\hfill Cygnus Support\par
\hfill \manvers\par
diff --git a/gnu/usr.bin/gdb/gdb/gdb.1 b/gnu/usr.bin/gdb/gdb/gdb.1
index ccb216ee88f7..45f81aec1344 100644
--- a/gnu/usr.bin/gdb/gdb/gdb.1
+++ b/gnu/usr.bin/gdb/gdb/gdb.1
@@ -1,6 +1,6 @@
.\" Copyright (c) 1991 Free Software Foundation
.\" See section COPYING for conditions for redistribution
-.\" $Id: gdb.1,v 1.1.1.1 1993/10/30 21:59:13 jkh Exp $
+.\" gdb.1,v 1.1 1994/06/10 13:37:34 paul Exp
.TH gdb 1 "4nov1991" "GNU Tools" "GNU Tools"
.SH NAME
gdb \- The GNU Debugger
diff --git a/gnu/usr.bin/gdb/mmalloc/mmalloc.texi b/gnu/usr.bin/gdb/mmalloc/mmalloc.texi
index 5e28398c334c..b0778271f00c 100644
--- a/gnu/usr.bin/gdb/mmalloc/mmalloc.texi
+++ b/gnu/usr.bin/gdb/mmalloc/mmalloc.texi
@@ -47,7 +47,7 @@ into another language, under the above conditions for modified versions.
@tex
\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
-\xdef\manvers{\$Revision: 1.1.1.1 $} % For use in headers, footers too
+\xdef\manvers{\1.1} % For use in headers, footers too
{\parskip=0pt
\hfill Cygnus Support\par
\hfill fnf\@cygnus.com\par
diff --git a/gnu/usr.bin/groff/BUG-REPORT b/gnu/usr.bin/groff/BUG-REPORT
new file mode 100644
index 000000000000..c87c66fe53ff
--- /dev/null
+++ b/gnu/usr.bin/groff/BUG-REPORT
@@ -0,0 +1,57 @@
+ Groff Bug Report
+
+Please read the PROBLEMS file before sending in a bug report.
+
+Please fill in all fields, even if you think they are not relevant.
+
+Please delete the text in brackets before sending it in.
+
+Please report separate bugs separately.
+
+Send the completed form either to bug-groff@prep.ai.mit.edu or
+directly to me (jjc@jclark.com). Messages sent to bug-groff can
+sometimes take several days to reach me.
+
+GROFF VERSION:
+[The version of groff you are using. For example, `1.05']
+
+MACHINE:
+[The machine you are using. For example, `Sun SPARCstation 2']
+
+OS:
+[The operating system you are using. For example, `SunOS 4.1.1']
+
+COMPILER:
+[The compiler you are used to compile groff. For example, `g++ 1.40.3']
+
+INPUT FILES:
+[Include all the files necessary to reproduce the problem that are not
+part of the standard groff distribution. This includes font
+description files, DESC files and macro files (with the exception of
+the -ms and -mm macros: I have them). Send them as as a shell archive
+or as a uuencoded, compressed tar file.
+
+It's easier for me if you can provide an example that doesn't depend
+on any macro package, but obviously if you're reporting a problem with
+a macro package that won't be possible. Also a short example is more
+convenient than a long one, but don't worry if you can't find a short
+example. Don't say something like ``any file that X'': always send a
+definite example.]
+
+COMMAND LINE:
+[The command line that I should run in order to observe the bug. For
+example, `gtroff -Tps bug.tr'. If the commmand line uses -ms or -mm,
+say whether these refer to the groff versions or the Unix versions of
+the macros.]
+
+DESCRIPTION OF INCORRECT BEHAVIOUR:
+[What goes wrong when that command line is run? For example, `gtroff
+gets a segmentation fault', or `The output looks bad because the bar
+over the x is too long and is too far over to the left.' If you get
+an error message, include it here without modification: don't edit it
+to make it more readable.]
+
+SUGGESTED FIX [optional]:
+[If you can suggest a fix for the problem, include a context diff
+here. But don't delay sending in a bug report in the hope of finding
+a fix. Guesses about the cause of the bug are not usually helpful.]
diff --git a/gnu/usr.bin/groff/COPYING b/gnu/usr.bin/groff/COPYING
new file mode 100644
index 000000000000..c712f50f0954
--- /dev/null
+++ b/gnu/usr.bin/groff/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1990, 1991, 1992 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/groff/ChangeLog b/gnu/usr.bin/groff/ChangeLog
new file mode 100644
index 000000000000..5c338d674133
--- /dev/null
+++ b/gnu/usr.bin/groff/ChangeLog
@@ -0,0 +1,4958 @@
+Mon Apr 19 09:55:57 1993 James Clark (jjc at jclark)
+
+ * Version 1.08 released.
+
+ * Makefile.in (dist): Insert || true after ln -s commands that
+ might fail.
+
+ * mm: Update to mm 1.16.
+
+ * acgroff.m4 (GROFF_CSH_HACK): New macro.
+ * configure.in: Call GROFF_CSH_HACK. Substitute for
+ SH_SCRIPT_SED_CMD.
+ * Makefile.in (SH_SCRIPT_SED_CMD): New variable. Include in
+ MDEFINES.
+ * nroff/Makefile.sub (nroff): New target.
+ (install_data): Install nroff.
+ * eqn/Makefile.sub (neqn): Sed with SH_SCRIPT_SED_CMD.
+ * grog/Makefile.sub (grog): Sed grog.sh with SH_SCRIPT_SED_CMD.
+
+Sat Apr 17 08:24:28 1993 James Clark (jjc at jclark)
+
+ * eqn/Makefile.sub (neqn): Add chmod +x.
+
+ * grog/Makefile.sub (grog): Remove spurious semi-colon.
+
+Fri Apr 16 22:41:57 1993 James Clark (jjc at jclark)
+
+ * troff/input.cc (string_iterator::string_iterator()): Initialize
+ lineno and count.
+
+Tue Apr 13 10:22:28 1993 James Clark (jjc at jclark)
+
+ * troff/div.cc (macro_diversion::space,
+ top_level_diversion::space): Don't set high_water_mark.
+ (macro_diversion::output, top_level_diversion::output): Don't
+ include post line space in high water mark.
+
+Wed Apr 7 12:48:18 1993 James Clark (jjc at jclark)
+
+ * eqn/eqn.y: Don't define YYDEBUG.
+ * pic/pic.y: Likewise.
+
+Mon Apr 5 10:15:15 1993 James Clark (jjc at jclark)
+
+ * tmac/tmac.e ([3): Add space after comma following editors.
+ Change double spaces to single spaces.
+ ([4): Change double spaces to single spaces.
+
+ * grops/ps.h (USE_PS_ADOBE_2_0): New flag for broken_flags.
+ * grops/ps.cc (ps_printer::~ps_printer): If the USE_PS_ADOBE_2_0
+ bit is set in broken_flags, use 2.0 rather than 3.0 as the version
+ after %!PS-Adobe- (for Newsprint).
+
+ * troff/div.cc (top_level_diversion::begin_page): When
+ before_first_page is 1, set page_number to 1.
+
+Sun Apr 4 14:28:53 1993 James Clark (jjc at jclark)
+
+ * eqn/box.cc (box::top_level): Protect equation with \&.
+
+Sat Apr 3 23:27:25 1993 James Clark (jjc at jclark)
+
+ * groff/groff.cc (possible_command::set_name): Delete old name.
+
+ * groff/groff.cc (possible_command::~possible_command): Use
+ a_delete.
+
+ * troff/node.cc (troff_output_file::begun_page): New member.
+ (troff_output_file::troff_output_file): Initialize it.
+ (troff_output_file::really_begin_page): Only output V command if a
+ page has been begun.
+
+ * pic/pic.y (placeless_element): Delete argument to PRINT after
+ use.
+
+Fri Apr 2 11:31:02 1993 James Clark (jjc at jclark)
+
+ * Make wrapman work.
+ * troff/div.h (class top_level_diversion): Replace
+ first_page_begun by before_first_page (with opposite sense).
+ * Change first_page_begun to before_first_page inverting sense.
+ * troff/div.cc (class nl_reg): New class.
+ (init_div_requests): Use class nl_reg for \n(nl.
+ (top_level_diversion::begin_page): Don't call
+ output_file::begin_page if before_first_page is 2;
+ reset before_first_page afterwards. If have_next_page_number is
+ false, then always increment page_number.
+ * tmac/tmac.an: Set traps within TH rather than at the top-level.
+ Restore compatibility mode after loading, and then disable
+ compatibility mode in TH.
+
+Thu Apr 1 11:09:34 1993 James Clark (jjc at jclark)
+
+ * grotty/tty.cc (tty_printer::end_page): Don't discard characters
+ past last line.
+ * troff/node.h (output_file::trailer): Declare.
+ * troff/div.cc (cleanup_and_exit): Call output_file::trailer().
+ * troff/node.cc (output_file::trailer): New function.
+ (troff_output_file::~troff_output_file): Move most code into...
+ (troff_output_file::trailer): New function.
+ (class troff_output_file): Delete page_length member. Declare
+ trailer().
+ (troff_output_file::really_begin_page): Use current page length
+ for final V command.
+
+ * tbl/main.cc (struct options): New decimal_point_char member.
+ (options::options): Initialize this.
+ (process_options): Implement decimalpoint option.
+ (process_data): Pass decimal_point_char option to table::table.
+ * tbl/table.h (class table): New decimal_point_char member.
+ (table::table): Add additional argument.
+ * tbl/table.cc (find_dot): Rename to find_decimal_point. Add
+ second argument specifying decimal point character. Use this
+ instead of '.'.
+ (table::table): Initialize decimal_point_char.
+ (table::add_entry): Change call to find_dot.
+
+ * troff/input.cc (get_copy, token::next): Implement \V.
+ (interpolate_environment_variable): New function.
+
+Tue Mar 30 14:41:39 1993 James Clark (jjc at jclark)
+
+ * pic/lex.cc (lookup_keyword): Rename MIN to K_MIN, MAX to K_MAX.
+ * pic/pic.y: Likewise.
+
+ * grotty/tty.cc (tty_printer::add_char, tty_printer::end_page):
+ Add casts to int.
+ * refer/ref.cc (reference::insert_field, reference::delete_field):
+ Likewise.
+ * troff/number.cc (parse_term): Likewise.
+
+ * acgroff.m4 (GROFF_PROG_YACC): New macro.
+ * configure.in: Use GROFF_PROG_YACC.
+
+ * acgroff.m4 (GROFF_PROG_CCC): Don't add -O automatically for gcc
+ and g++.
+ * Makefile.in (OPTIMIZE): New define.
+ (DEBUG): Empty by default.
+ (CCFLAGS, CFLAGS): Include $(OPTIMIZE).
+
+ * acgroff.m4 (GROFF_SYS_SIGLIST): Don't quote program.
+ (GROFF_ARRAY_DELETE): Likewise.
+ (GROFF_CC_COMPILE_CHECK): Quote use of $2 and $3.
+
+ * troff/env.cc (trie::~trie): Make virtual to shut up g++.
+
+ * devps/psstrip.sed: Use different delimiter on last line (so that
+ it works with BSD 4.4 sed.)
+
+Mon Mar 29 17:07:14 1993 James Clark (jjc at jclark)
+
+ * devps/psstrip.sed: Delete comments.
+
+ * acgroff.m4 (AC_GETOPT): Don't test whether <unistd.h> declares
+ optind, opterr, optarg.
+ * lib.h: When UNISTD_H_DECLARES_GETOPT is defined, declare optind,
+ opterr, optarg.
+
+Sun Mar 28 17:44:25 1993 James Clark (jjc at jclark)
+
+ * Makefile.in (check): Dummy target.
+
+Wed Mar 3 04:53:38 1993 James Clark (jjc at jclark)
+
+ * Version 1.07 released.
+
+ * Integrate mm 1.11.
+
+ * tbl/table.cc (alphabetic_block_entry::print): start_row was used
+ where start_col was meant.
+
+Thu Feb 25 07:55:36 1993 James Clark (jjc at jclark)
+
+ * grog/grog.sh, grog/grog.pl: Recognize PH and SA as -mm macros.
+
+Wed Feb 24 10:15:34 1993 James Clark (jjc at jclark)
+
+ * troff/input.cc (token::next): Make \z\o'...' and similar things
+ work.
+
+ * env.h (MARGIN_CHARACTER_ON, MARGIN_CHARACTER_NEXT): New
+ constants.
+ (environment): Add margin_character_flags member.
+ * env.cc (environment::environment(symbol),
+ environment::environment(const environment *): Initialize
+ margin_character_flags.
+ (margin_character): Rewrite.
+ (environment::output_line): Add a margin character if
+ margin_character_flags is non-zero. Turn off the
+ MARGIN_CHARACTER_NEXT bit. If that makes margin_character_flags
+ zero, use margin_character_node without copying and then set
+ margin_character_node to 0.
+
+ * devps/DESC.in: Change minimum size to 1000.
+
+Tue Feb 23 14:57:49 1993 James Clark (jjc at jclark)
+
+ * troff/symbol.h (symbol::hash): Change return type to unsigned
+ long.
+ * troff/dictionary.cc (dictionary::lookup, dictionary::remove):
+ Add casts to int.
+
+ * test-groff: Use -r rather than -x.
+
+ * grops/psfig.diff: Include in distribution again.
+
+Mon Feb 22 09:10:44 1993 James Clark (jjc at jclark)
+
+ * Makefile.in (dist): Use gzip.
+
+Sun Feb 21 11:12:53 1993 James Clark (jjc at jclark)
+
+ * acgroff.m4 (GROFF_GETOPT): Check for declaration of getopt() in
+ unistd.h as well as in stdlib.h.
+ * include/lib.h: Include <stdlib.h> is STDLIB_H_DECLARES_GETOPT is
+ defined; otherwise include <sys/types.h> and <unistd.h> if
+ UNISTD_H_DECLARES_GETOPT is defined.
+
+ * configure.in: use builtin(include, ... rather than include(...
+ * configure: Regenerate with autoconf 1.3.
+
+ * libdriver/print.cc (printer::adjust_arc_center): Use new
+ algorithm suggested by Andy Fyfe.
+
+ * libdriver/printer.cc (printer::adjust_arc_center): New function.
+ * include/printer.h: Declare this.
+ * grops/ps.cc (ps_printer::draw): Use it.
+ * grodvi/dvi.cc (dvi_printer::draw): Use it.
+
+Fri Feb 19 23:13:51 1993 James Clark (jjc at jclark)
+
+ * Makefile.comm (.man.n): Replace macrodir by tmacdir.
+
+Thu Feb 11 16:46:59 1993 James Clark (jjc at jclark)
+
+ * eqn/main.cc (main): Handle "eqn -".
+
+Mon Jan 4 20:29:56 1993 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (++): Install fix from comp.bugs.4sd.
+
+ * mm: Integrate version 1.08.
+
+ * pic/troff.cc (troff_output::finish_picture): Set
+ EQN_NO_EXTRA_SPACE reg to 0 rather than removing it.
+ * eqn/box.cc (box::extra_space): Set EQN_NO_EXTRA_SPACE_REG to 0
+ if it's not defined. Check whether the register is non-zero rather
+ than whether it's not defined.
+ * tmac.e ({, <): Make argument to \x zero if \n(0x is non-zero.
+
+ * indxbib/indxbib.cc: Move all signal handling into...
+ * indxbib/signal.c: New file.
+ * configure.in: Call AC_RETSIGTYPE.
+
+ * acgroff.m4 (GROFF_STRUCT_EXCEPTION): New macro.
+ * configure.in: Call GROFF_STRUCT_EXCEPTION.
+ * libgroff/matherr.c: Protect with ifdef HAVE_STRUCT_EXCEPTION.
+
+ * troff/input.cc (token::token, token::operator=): Work round SGI
+ C++ bug.
+ * pic/object.cc (position::position): Likewise.
+
+Mon Dec 28 21:50:21 1992 James Clark (jjc at jclark)
+
+ * pic/pic.h: Move declaration of hypot().
+
+Wed Dec 16 12:28:29 1992 James Clark (jjc at jclark)
+
+ * pic/pic.h: Declare hypot().
+
+ * pic/pic.h: Define M_PI if necessary.
+
+Thu Dec 10 12:03:29 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (re): Add alternative version that doesn't use groff
+ `.ta T' feature.
+
+ * devps/prologue.ps (RE): Handle the possibility that the old font
+ doesn't have a FontName entry.
+
+Wed Dec 2 10:25:29 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (fam): Redefine to set family in environment 2.
+ (@C): Use @fam not fam.
+
+Thu Nov 26 16:01:25 1992 James Clark (jjc at jclark)
+
+ * lookbib/lookbib.cc (main): Change type of start to const char *.
+ * lkbib/lkbib.cc (main): Likewise.
+
+ * eqn/lex.cc (definition::definition): Don't use member
+ initializer syntax for members of anonymous unions.
+
+ * troff/input.cc (input_stack::backtrace): Change type of to const
+ char *.
+
+Wed Nov 25 13:43:09 1992 James Clark (jjc at jclark)
+
+ * include/stringclass.h (class string): Declare inline friend
+ functions as inline in class declaration.
+ * troff/hvunits.h (class hunits, class vunits): Likewise.
+ * include/refid.h (class reference_id): Likewise
+ * troff/troff.h (points_to_units(units), scale(units, double)):
+ Delete declarations.
+ * libdriver/input.cc (get_char): Delete declaration.
+ * include/lib.h: Change 2nd argument of getopt from const char **
+ to char **.
+ * troff/symbol.cc (symbol::symbol): Cast `new char *[n]' to `const
+ char **' before assigning to a `const char **'.
+ * tbl/table.cc: Delete extra declarations of prints().
+
+Tue Nov 24 14:33:13 1992 James Clark (jjc at jclark)
+
+ * libgroff/font.cc (font::load_desc): Cast `new char *[n]' to `const
+ char **' before assigning to a `const char **'.
+
+ * libgroff/errarg.cc (errarg::errarg): Don't use member
+ initializer syntax for members of anonymous unions.
+
+Sat Nov 21 05:02:23 1992 James Clark (jjc at jclark)
+
+ * mm: Integrate version 1.07.
+
+Tue Nov 17 16:44:27 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (translate2): Rename to
+ (translate_no_transparent).
+ (init_input_requests): Rename tr2 to trnt.
+
+Mon Nov 16 09:49:32 1992 James Clark (jjc at jclark)
+
+ * troff/charinfo.h (class charinfo): Add transparent_translate field.
+ (charinfo::set_translation, charinfo::set_special_translation):
+ Add second argument that specifies value for
+ transparent_translate.
+ (charinfo::get_translation, charinfo::get_special_translation):
+ Add optional second argument that specifies whether translation is
+ being used for transparent throughput.
+ * troff/input.cc (charinfo::set_translation,
+ charinfo::set_special_translation): Handle second argument.
+ (charinfo::charinfo): Initialize transparent_translate.
+ (translate): Split main part off into
+ (do_translate): New function. Pass argument saying whether
+ translation applies to transparent throughput.
+ (translate2): New request.
+ (init_input_requests): Bind translate2 to `tr2'.
+
+Wed Nov 11 11:43:20 1992 James Clark (jjc at jclark)
+
+ * tbl/table.h (class table): Add `nokeep' flag.
+ * tbl/main.cc (process_options): Handle `nokeep' option.
+ * tbl/table.cc (table::init_output, table::do_row, table::do_top,
+ table::do_bottom): Don't output keep/release macro definitions or
+ calls when `nokeep' option has been specified.
+
+Sat Nov 7 01:28:33 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.Xps (Xps-char): Use " as delimiter for \Z.
+
+Wed Nov 4 16:29:04 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table_entry::divert, block_entry::do_divert,
+ block_entry::divert, alphabetic_block_entry::divert): Add extra
+ argument giving column separation.
+ (table::compute_widths): Pass column separation to
+ table_entry::divert().
+ (block_entry::do_divert): If an entry spans multiple columns and a
+ minimumum width has been specified for each column, then set the
+ line length to the sum of the widths (plus possibly the column
+ separations).
+
+ * troff/input.cc (set_escape_char): Don't set the escape_char
+ until after calling has_arg().
+
+Tue Nov 3 11:23:27 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table::do_top): Add missing \s0 for double box
+ case.
+
+ * tbl/table.cc (table::print_double_hline): Avoid extra new line
+ in case where r > nrows - 1.
+
+ * tbl/table.cc (BODY_HEIGHT): Deleted.
+ (LINE_SEP): New definition.
+ (table::print_single_hline, table::print_double_hline,
+ table::compute_vrule_top_adjust, table::compute_vrule_bot_adjust,
+ table::do_row, table::do_top): Use LINE_SEP space before a line
+ instead of \n[.v]-BODY_HEIGHT-BODY_DEPTH.
+
+ * tbl/table.cc (text_entry::print_contents): New function.
+ (text_string_name, right_text_string_name): Deleted.
+ (TEXT_STRING, RIGHT_TEXT_STRING): Deleted.
+ (simple_text_entry::do_width, numeric_text_entry::do_width,
+ alphabetic_text_entry::do_width): Don't store the contents of the
+ entry in a string.
+ (left_text_entry::simple_print, right_text_entry::simple_print,
+ center_text_entry::simple_print,
+ alphabetic_text_entry::simple_print,
+ numeric_text_entry::simple_print): Print the entry directly
+ instead of using the stored string.
+
+Fri Oct 30 10:39:32 1992 James Clark (jjc at jclark)
+
+ * devps/Makefile: Strip PostScript files.
+ * devps/prologue: Rename to...
+ * devps/prologue.ps.
+ * devps/psstrip.sed: New file.
+ * devps/download: Use .pfa rather than .ps for installed versions
+ of fonts.
+
+Thu Oct 29 09:14:43 1992 James Clark (jjc at jclark)
+
+ * troff/env.cc (input_trap): Give a warning if the argument is out
+ of range.
+
+ * troff/env.cc (adjust): Treat negative argument as missing. Round
+ argument > 5 down to 5.
+
+ * troff/env.cc (center, right_justify): Make negative argument zero.
+
+ * troff/div.cc (page_offset, vertical_position_traps): Treat
+ invalid argument as missing.
+ * troff/env.cc (line_spacing, line_length, title_length, indent,
+ underline, hyphen_line_max_request, control_char,
+ no_break_control_char, widow_control_request, adjust, input_trap,
+ point_size): Likewise.
+ * troff/node.cc (ligature, kern_request, bold_font, track_kern,
+ constant_space): Likewise.
+ * troff/input.cc (compatible, shift, warn_request,
+ set_escape_char): Likewise.
+
+ * tbl/main.cc (format::format): Avoid doing `new int[0]'.
+ * tbl/table.cc (table::table): Likewise.
+
+ * Makefile.dev (install_dev): depends on $(DEVFILES).
+
+Wed Oct 28 08:30:57 1992 James Clark (jjc at jclark)
+
+ * devX75, devX75-12, devX100, devX100-12: New directories.
+ * Makefile.in: Add these to DEVDIRS.
+
+ * troff/Makefile.sub, eqn/Makefile.sub, indxbib/Makefile.sub,
+ afmtodit/Makefile.sub, tmac/Makefile.sub, nroff/Makefile.sub,
+ grog/Makefile.sub, mm/Makefile.sub (uninstall_sub): New target.
+ * Makefile.in (uninstall, uninstall_sub, uninstall_dirs): New
+ targets.
+ * Makefile.ccpg, Makefile.cpg, Makefile.dev, Makefile.man
+ (uninstall): New target.
+ * Makefile.comm (uninstall, uninstall_sub, uninstall_man,
+ uninstall_prog, uninstall_dev): New targets.
+
+ * troff/div.cc (return_request): Treat an invalid argument as
+ missing.
+
+Mon Oct 26 11:33:47 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e ((f): Set up the environment even when there's a
+ current diversion. Transperently throughput a call to @N.
+ (@N): New macro.
+
+Thu Oct 22 05:05:59 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table::compute_vrule_top_adjust): Round adjustment
+ up to vertical resolution.
+
+ * tbl/table.cc (table::do_row): Change row number after printing
+ stuff list.
+
+ * pic/lex.cc (get_token_after_dot): Make .left and .right work.
+
+Wed Oct 21 14:46:45 1992 James Clark (jjc at jclark)
+
+ * Rename CHANGES to NEWS.
+
+Tue Oct 20 23:25:21 1992 James Clark (jjc at jclark)
+
+ * libgroff/new.cc (operator new): Avoid calling malloc(0).
+
+Mon Oct 19 09:10:13 1992 James Clark (jjc at jclark)
+
+ * man.ultrix: Removed.
+
+Sun Oct 18 06:35:15 1992 James Clark (jjc at jclark)
+
+ * Makefile.comm (extraclean): Delete files whose names begin with
+ `='.
+
+ * pic/troff.cc (troff_output::text): Fix typo in implementation of
+ aligned text.
+
+Sat Oct 10 09:32:29 1992 James Clark (jjc at jclark)
+
+ * troff/env.cc (hyphenate_request, vertical_spacing, no_number):
+ * troff/div.cc (page_length, need_space, space_request): Treat
+ invalid optional argument as missing.
+ * troff/env.cc (number_lines): If the first argument is present
+ but not a number, turn on line numbering, don't change the next
+ line number and parse the remaining arguments.
+
+ * tmac/tmac.e (@q): Do the `ne' before changing to environment 2.
+
+Thu Oct 8 10:24:40 1992 James Clark (jjc at jclark)
+
+ * eqn/box.h: Change declaration accordingly.
+ * eqn/box.cc (set_gsize): Change return type to int. Return 0 if
+ the specified size was bad but don't give an error. Check for
+ overflow.
+ * eqn/main.cc (main): Change caller. Leave validation to set_gsize.
+ * eqn/lex (do_size): Likewise.
+
+Wed Oct 7 09:48:59 1992 James Clark (jjc at jclark)
+
+ * acgroff.m4 (GROFF_PROG_CCC): Use fopen when checking for C++
+ compatible headers.
+
+Sun Oct 4 18:24:02 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table::init_output): Improve error message when
+ table won't fit on one page.
+
+Fri Oct 2 10:41:40 1992 James Clark (jjc at jclark)
+
+ * pic/troff.cc (troff_output::start_picture): Generate line
+ containing a horizontal motion equal to the width of the picture.
+
+ * groff/groff.cc (main): Allow PROG_PREFIX to be set at runtime
+ using GROFF_COMMAND_PREFIX environment variable.
+
+Fri Sep 25 11:40:40 1992 James Clark (jjc at jclark)
+
+ * mdate.sh: Use $NF rather than $(NF).
+
+Tue Sep 22 09:47:24 1992 James Clark (jjc at jclark)
+
+ * pic/main.cc (main): Use %1 not %c in argument to warning.
+
+ * eqn/main.cc (main): Output code to check that geqn was given the
+ correct -T option.
+
+Mon Sep 21 10:59:16 1992 James Clark (jjc at jclark)
+
+ * Makefile.in (dist): Instead of doing `make -f ../Makefile', do
+ `ln -s ../Makefile .; make; rm -f Makefile'.
+
+ * troff/hyphen: Rename to...
+ * troff/hyphen.us:
+ * troff/input.cc (main): Delete -H option. Don't call
+ read_hyphen_file().
+ * troff/env.cc: Include searchpath.h and macropath.h.
+ (exception_dictionary): Deleted.
+ (ht): Deleted.
+ (read_hyphen_file): Deleted.
+ (hyphenation_language): New struct.
+ (class trie, class hyphen_trie): Move declarations up.
+ (trie_node::~trie_node): Deleted.
+ (trie::delete_trie_node): New function.
+ (trie::do_delete): New pure virtual function.
+ (hyphen_trie::do_delete): New function.
+ (trie::~trie): New function.
+ (hyphen_trie::~hyphen_trie): New function.
+ (trie::clear): No need to chcek that tp is not 0.
+ (current_language, language_dictionary): New variables.
+ (hyphen_word): Give an error if no current language. Use
+ exceptions dictionary in current language.
+ (hyphen_trie::read_patterns_file): Find file using macro_path.
+ Allow comments (starting with %) in patterns file. Don't make it
+ a fatal error if the file can't be found.
+ (hyphenate): Return if no current language. Get the exceptions
+ dictionary and the hyphenation patterns from the current language.
+ (set_hyphenation_language): New variable.
+ (hyphenation_patterns_file): New function.
+ (hyphenation_language_reg): New class.
+ (hyphenation_language_reg::get_string): New function.
+ (init_hyphen_requests): Bind "hla" to set_hyphenation_language and
+ "hpf" to hyphenation_patterns_file. Initialize `.hla' number
+ register.
+ * groff/groff.cc (main, help, synopsis): Delete -H option.
+ * include/Makefile.sub: Don't define HYPHENFILE.
+ * Makefile.in: Delete hyphenfile variable and remove from MDEFINES.
+ * Makefile.comm (.man.n): Don't substitute for HYPHENFILE.
+ * tmac/troffrc: Set hyphenation language to `us'. Load `hyphen.us'
+ hyphenation patterns.
+
+Sun Sep 20 09:33:02 1992 James Clark (jjc at jclark)
+
+ * eqn/neqn.sh: New file.
+ * eqn/Makefile.sub: Handle neqn.sh.
+
+ * eqn/eqn.h: Declare `nroff' variable.
+ * eqn/box.cc (param_table): Add `nroff' param.
+ (nroff): Define it.
+ * eqn/lex.cc (yylex): Handle TDEFINE and NDEFINE using `nroff'
+ variable.
+ * tmac/eqnrc: Set `nroff' to 1 for -Tascii or -Tlatin1.
+
+ * troff/troff.h (WARN_FONT): New warning.
+ (WARN_TOTAL): Change accordingly.
+ * troff/input.cc (DEFAULT_WARNING_MASK): Include WARN_FONT.
+ (warning_table): Add WARN_FONT.
+ * troff/node.cc (mount_font_no_translate): Pass argument to
+ font::load_font. If this is non-zero, give a warning.
+ Don't give an error message when accessing a font that has already
+ been found to be invalid.
+ * include/font.h (font::load, font::load_font): Add additional
+ optional argument which suppresses error message if the font is
+ not found.
+ * libgroff/font.cc (font::load_font): Handle additional argument.
+ (font::load): Add additional argument. If this is non-null, set it
+ to 1 and don't give error message.
+
+ * include/printer.h (printer::end_page): Add argument giving
+ length of page.
+ * libdriver/input.cc (do_file): Pass this.
+ * grops/ps.cc (ps_printer::end_page): Add argument.
+ * grodvi/dvi.cc (dvi_printer::end_page,
+ draw_dvi_printer::end_page): Add argument.
+ * grotty/tty.cc (class tty_printer): Remove lines_per_page and
+ columns_per_page members. New member nlines.
+ (DEFAULT_LINES_PER_PAGE): Deleted.
+ (tty_printer::tty_printer): Don't compute lines_per_page from
+ font::paperlength. Don't compute columns_per_page from
+ font::paperwidth.
+ (tty_printer::add_char): Don't check horizontal position against
+ columns_per_page. Grow glyphs vector if neccessary.
+ (tty_printer::end_page): Add argument giving page_length in units.
+ Discard lines past end of page.
+
+Wed Sep 16 06:29:52 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.tty-char: Fix definition of \(/l.
+
+ * tmac/tmac.X: Define \(en.
+
+Tue Sep 15 10:37:13 1992 James Clark (jjc at jclark)
+
+ * acgroff.m4 (GROFF_PRINT): If a system has lpr and lp but not
+ lpq, then use lp rather than lpr.
+
+ * tmac/tmac.s (par@reset): Don't call `ad'.
+ (par*env-init): Call `ad'.
+
+Sun Sep 13 18:48:20 1992 James Clark (jjc at jclark)
+
+ * mdate.sh: Use $(NF) instead of $6 to extract year from output of
+ date.
+
+ * troff/symbol.cc: #undef BLOCK_SIZE if it's defined.
+ * indxbib/indxbib.cc: Likewise.
+
+Sun Sep 6 09:44:46 1992 James Clark (jjc at jclark)
+
+ * libgroff/putenv.c: New file.
+ * libgroff/Makefile.sub: Add putenv.c to CSRCS.
+ * Makefile.in: Say that putenv.o can be one of LIBOBJS.
+ * configure.in: Test for putenv with AC_REPLACE_FUNCS. Test for
+ stdlib.h with AC_HAVE_HEADERS.
+
+Sat Sep 5 18:11:52 1992 James Clark (jjc at jclark)
+
+ * indxbib/dirnamemax.c: Include <sys/dir.h> only if <dirent.h>
+ does not exist.
+
+Fri Sep 4 09:43:26 1992 James Clark (jjc at jclark)
+
+ * eqn/box.cc (gsize): Make it an int.
+ (set_gsize): Parse argument handling increment or decrement.
+ (box::top_level): Convert gsize to a string.
+
+ * troff/input.cc (exit_troff): Make buf unsigned char [].
+ Call to make_temp_iterator casts buf to char*.
+
+ * Makefile.in ($(TARGETS), dot): Pass $(MDEFINES) to recursive makes.
+
+ * Makefile.ccpg (depend.temp): Depends on $(YTABC).
+ * Makefile.cpg (depend.temp): Likewise.
+
+ * Makefile.dep: Remove Makefile.dep from $(REALCLEANFILES).
+
+ * Makefile.comm: Add y.output to MOSTLYCLEANFILES.
+
+Thu Sep 3 08:01:55 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.s (B, I, BI, CW): Rewrite avoiding aliases.
+
+Tue Sep 1 18:24:53 1992 James Clark (jjc at jclark)
+
+ * Version 1.06 released.
+
+ * Integrate mm 1.04.
+
+Fri Aug 28 11:28:19 1992 James Clark (jjc at jclark)
+
+ * Makefile.comm, Makefile.ccpg, Makefile.cpg: Fix TAGS target.
+
+Thu Aug 27 11:03:33 1992 James Clark (jjc at jclark)
+
+ * afmtodit/afmtodit.pl: Add -n option that disables generation of
+ ligatures command.
+ * devps/generate/Makefile (CR, CB, CI, CBI): Pass -n flag to
+ afmtodit. Regenerate.
+
+ * tmac/tmac.e ()z): Adjust _b if necessary so as to avoid moving
+ @f back past the current position.
+
+ * tmac/tmac.e: Change calls to @R so that comments are not part of
+ arguments.
+
+Tue Aug 25 10:42:07 1992 James Clark (jjc at jclark)
+
+ * configure.in: Check for mkstemp with AC_HAVE_FUNCS.
+
+ * acgroff.m4 (GROFF_PROG_CCC): Don't check for <osfcn.h>. Instead
+ check that we can link a call to a function declared in <stdio.h>.
+ (GROFF_UNISTD_H): New macro.
+ * configure.in: Call it.
+ * Makefile.in: Document it.
+ * include/posix.h: New file.
+ * troff/troff.h: Don't include <osfcn.h>
+ * troff/input.cc: Include posix.h.
+ * libgroff/new.cc, libgroff/tmpfile.cc: Include posix.h rather than
+ osfcn.h.
+ * indxbib/indxbib.cc, libbib/{search.cc,linear.cc,index.cc}:
+ Include posix.h rather <sys/types.h>, <sys/stat.h>, <osfcn.h>,
+ <fcntl.h>.
+ * indxbib/indxbib.cc (S_IRUSR, S_IRGRP, S_IROTH): Delete definitions.
+ * libbib/index.cc (S_ISREG, O_RDONLY): Delete definitions.
+ * libbib/search.cc (O_RDONLY): Delete definition.
+ * refer/refer.cc, include/driver.h, pic/pic.h, groff/groff.cc:
+ Don't include <osfcn.h>.
+
+ * acgroff.m4 (GROFF_TIME_T): New macro.
+ * configure.in: Call it.
+ * Makefile.in: Document it.
+
+ * acgroff.m4 (GROFF_TRADITIONAL_CPP): New macro.
+ * configure.in: Call it.
+ * Makefile.in: Document -DTRADITIONAL_CPP.
+ * include/ptable.h: Don't include generic.h.
+ (name2): Define it.
+
+ * tmac/tmac.s (][): Make [T1 and [T2 aliases for [T.
+ Afterwards remove [T1 and [T2.
+ (ref*spec!0, ref*spec!2): Use T1 rather than T.
+ (ref*spec!1, ref*spec!4, ref*spec!4): Use T2 rather than T.
+ (ref*add-T2): Renamed from ref*add-T.
+ (ref*add-T1): New macro.
+
+Mon Aug 24 11:11:11 1992 James Clark (jjc at jclark)
+
+ * acgroff.m4 (AC_PROG_CCC): Use GROFF_EXIT rather than exit 1.
+
+ * libbib/index.cc: Include <fcntl.h>.
+ (O_RDONLY): Define if necessary.
+ (make_index_search_item, index_search_item_iterator::get_tag,
+ index_search_item::check_files): Use O_RDONLY.
+ * libbib/seach.cc: Include <fcntl.h>, <sys/types.h>, <sys/stat.h>.
+ (O_RDONLY): Define if necessary.
+ (search_list::add_file): Use O_RDONLY.
+ * indxbib/indxbib.cc: Include <fcntl.h>, <sys/types.h>,
+ <sys/stat.h>.
+ (S_IRUSR, S_IRGRP, S_IROTH): Define if necessary.
+ (main): Use these.
+
+ * libbib/index.cc (S_ISREG): Define it if necessary.
+ (index_search_item::load): Use S_ISREG.
+
+ * include/driver.h: Include <errno.h>.
+
+Sun Aug 23 11:32:18 1992 James Clark (jjc at jclark)
+
+ * eqn/box.cc (body_height): Increase default value to 85.
+ (body_depth): Increase default value to 35.
+
+Fri Aug 21 05:34:42 1992 James Clark (jjc at jclark)
+
+ * eqn/pbox.h (SAVE_FONT_STRING): Define it.
+ * eqn/box.cc (box::top_level): Hide use of \R in a string that is
+ protected from expansion with \E.
+
+ * acgroff.m4 (GROFF_PAGE): Use `case' to test domain.
+
+ * Makefile (Makefile): New target.
+
+ * Makefile.sub (configure, distfiles): New targets.
+
+ * acgroff.m4 (GROFF_BROKEN_SPOOLER_FLAGS): Avoid using ${var:-val}
+ construct.
+
+Thu Aug 20 12:27:26 1992 James Clark (jjc at jclark)
+
+ * eqn/box.cc (param_table): Add body_height and body_depth.
+
+ * eqn/lex.cc (def_table): Make circumflex in hat_def roman.
+
+Tue Aug 18 16:24:25 1992 James Clark (jjc at jclark)
+
+ * psbb/Makefile.sub: Don't link with libgroff.a.
+
+ * acgroff.m4 (GROFF_PUTENV): New macro.
+ * configure.in: Call GROFF_PUTENV.
+ * Makefile.in: Document STDLIB_H_DECLARES_PUTENV.
+ * groff/groff.cc: Don't declare putenv if STDLIB_H_DECLARES_PUTENV
+ is defined.
+
+ * troff/env.cc (distribute_space): Rename force_forward argument
+ to force_reverse. Reverse the list if force_reverse is true.
+
+Mon Aug 17 17:49:05 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.an: Don't define a string `T'. Just define Tm.
+
+ * eqn/pile.cc (matrix_box::compute_metrics): Don't allow computed
+ height or depth to be negative. Guard against SUP_RAISE quantity
+ being negative.
+
+Sat Aug 15 08:18:54 1992 James Clark (jjc at jclark)
+
+ * devps/generate/textmap: Add `an' (arrowhorizex).
+ * tmac/tmac.ps: \(an overlaps horizontally.
+ * tmac/tmac.dvi, tmac/tmac.tty: Add `an'.
+
+ * devps/symbolchars: Add arrowverttp, arrowvertbt.
+ * devps/textmap: Add arrowvertex.
+ * eqn/delim.cc (delim_table): Add uparrow, downarrow and
+ updownarrow delimiters.
+ * tmac/tmac.ps, tmac/tmac.X: Add definition of \(va.
+
+ * tbl/table.cc (simple_entry::position_vertically,
+ block_entry::position_vertically): For a centered entry, perform
+ the motion in two stages.
+
+ * refer/refer.cc (split_punct): Don't call lookup_token if there
+ is no token.
+
+Fri Aug 14 11:14:58 1992 James Clark (jjc at jclark)
+
+ * troff/input.cc (token::next): Delete token_node after copying
+ token.
+
+ * grodvi/grodvi.cc (dvi_printer::dvi_printer): Initialize
+ cur_point_size.
+
+ * libdriver/printer.cc (printer::load_font): Delete old_font_table.
+
+ * grops/ps.cc (ps_printer::define_encoding): Delete elements of vec.
+
+Tue Aug 11 13:50:38 1992 James Clark (jjc at jclark)
+
+ * grops/ps.cc (usage): -b option takes an argument.
+
+ * devps/prologue (PLG): New procedure.
+ * grops/ps.cc (main, usage): New -g option.
+ (ps_printer::~ps_printer): If guess_flag is set, guess the paper
+ length using PLG.
+
+Mon Aug 10 11:17:53 1992 James Clark (jjc at jclark)
+
+ * include/cset.h: Include <limits.h> if we have it.
+
+ * libgroff/illegal.cc: New file.
+ * include/lib.h (illegal_input_char): Use table.
+ * troff/input.cc (ESCAPE_RIGHT_PARENTHESIS): Renumber to 0206.
+ * pic/lex.cc (ARG1): Renumber to 14.
+ * eqn/lex.cc (ARG1: Likewise.
+
+ * troff/Makefile.sub (majorminor.cc): Handle 3 part versions
+ (eg 1.05.90) correctly.
+
+Sun Aug 9 13:35:43 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (sr): Deleted. Set $r and $R directly.
+ Rename $r and $R registers to $v and $V.
+ ($r, $R): Initialize to 0.
+ (@v, @V): New macros.
+ (sz): Call @v.
+ (@M): Call @V.
+
+ * troff/input.cc (main, usage): Add -R option that says not to
+ load troffrc.
+ * eqn/main.cc (main, usage): Rename -n to -R.
+
+Sat Aug 8 00:16:00 1992 James Clark (jjc at jclark)
+
+ * devps/DESC.in: Leave font positions 5-9 blank.
+ * devdvi/DESC.in: Likewise.
+
+ * grog/grog.pl: Handle `.PS <file' correctly.
+
+ * troff/input.cc (input_stack::push): Improve error message when
+ input stack limit exceeded.
+
+Fri Aug 7 13:08:16 1992 James Clark (jjc at jclark)
+
+ * refer/refer.cc (main): Fix typo in handling of `a' option.
+
+ * refer/refer.cc (do_bib): In state START after a newline remain
+ in state START.
+
+ * groff/groff.sh: Deleted.
+ * groff/Makefile.sub: Delete handling of groff.sh.
+
+ * pic/troff.cc (troff_output::text): Test \n(0p rather than \*(.T
+ to determine whether to use \X'ps:...'.
+ * tmac/troffrc: Set 0p register to 0.
+ * tmac/tmac.ps: Set 0p register to 1.
+
+ * groff/groff.cc: Support -X option. Give warning for -TXps and
+ transform to -X -Tps. Pass troff a -r.X=1 option if -X is used.
+ * tmac/troffrc: Support -r.X=1.
+
+ * pic/troff.cc (troff_output::dot): Don't test
+ zero_length_line_flag.
+
+Thu Aug 6 13:32:08 1992 James Clark (jjc at jclark)
+
+ * include/lib.h: Declare getopt() and friends unless
+ STDLIB_H_DECLARES_GETOPT is defined.
+
+ * doc/chars.tr: Delete.
+ * man/groff_char.man: New file.
+
+Wed Aug 5 00:38:58 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (np, bu): Test \n($p with string expression in case
+ user has changed register format.
+
+Mon Aug 3 11:22:18 1992 James Clark (jjc at jclark)
+
+ * groff/groff.cc: Get rid of device_table. Get postprocessor from
+ `postpro' command in DESC file. Get spooler command from `print'
+ command in DESC file. Execute spooler command with /bin/sh.
+
+ * groff/groff.cc: Split Unix-specific parts into...
+ * groff/pipeline.c: New file.
+
+ * LICENSE: Delete.
+ * COPYING: New file.
+ * all files: Update copyright notices.
+
+ * Rearrange files. Redo Makefiles. Use autoconf.
+
+Sat Aug 1 09:36:50 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (charinfo_to_node_list): Interpret character
+ definition with escape_char of `\'.
+
+Tue Jul 28 12:20:12 1992 James Clark (jjc at jclark)
+
+ * lib/strerror.c, lib/iftoa.c, lib/itoa.c: Don't include lib.h.
+ Define INT_DIGITS as big enough for 64-bit integer.
+ * lib/strtol.c: Don't include lib.h.
+ * lib/lib.h: Delete ifdef __cplusplus stuff.
+
+Mon Jul 27 11:08:50 1992 James Clark (jjc at jclark)
+
+ * ps/devps/Makefile: Add DESC to DEVICEFILES. Separate out rule
+ for making DESC. Make $(FONTS) depend on DESC. afmtodit should
+ get DESC from current directory.
+
+Sun Jul 26 15:38:26 1992 James Clark (jjc at jclark)
+
+ * tbl/main.c (main): Always reset the line number when reading
+ from stdin.
+
+ * tbl/table.c (table::print_single_hline, table::print_double_hline,
+ table::define_bottom_macro, table::do_row, table::do_top): Round
+ vertical spacing up to vertical resolution.
+
+Fri Jul 24 14:32:07 1992 James Clark (jjc at jclark)
+
+ * ps/ps.h (enum resource_type): Avoid comma at end of
+ enumerator-list.
+ * dvi/dvi.c (class dvi_printer): Likewise.
+ * dvi/tfmtodit.c (gf::load): Likewise.
+ * refer/label.y (struct expression): Likewise.
+ * refer/refer.c (class label_processing_state): Likewise.
+ * refer/indxbib.c (do_file): Likewise.
+ * troff/troff.c (enum warning_type): Likewise.
+ * tbl/main.c (process_data): Likewise.
+ * troff/charinfo.h (class charinfo):
+
+Wed Jul 22 09:17:58 1992 James Clark (jjc at jclark)
+
+ * dvi/devdvi/textt.map: Add entry for `-'. Regenerate fonts.
+
+Tue Jul 21 11:39:26 1992 James Clark (jjc at jclark)
+
+ * groff.c: Move to new groff subdirectory.
+ * groff/Makefile: New file.
+ * Makefile: Remove handling of groff.c. Add groff to SUBDIRS.
+
+ * man/mdate.sh: Use ls -L if supported.
+
+ * Consolidate all header files produced by gendef into lib/defs.h.
+ * lib/macropath.c, lib/fontfile.c, lib/device.c: Include defs.h.
+ Don't include path.h.
+ * lib/Makefile (path.h): Don't generate.
+ * troff/input.c: Include defs.h. Don't include config.h.
+ * troff/Makefile (config.h): Don't generate.
+ * refer/index.h: Don't include suffix.h.
+ * refer/index.c: Include defs.h.
+ * refer/indxbib.c: Include defs.h.
+ * refer/refer.h, refer/lkbib.h: Don't include path.h. Include
+ defs.h.
+ * refer/Makefile (suffix.h, path.h): Don't generate.
+ * groff.c: Don't include config.h. Include defs.h.
+ * Makefile (config.h): Don't generate.
+ (lib/defs.h): Generate.
+ (topclean): Remove lib/defs.h.
+
+Mon Jul 20 10:12:57 1992 James Clark (jjc at jclark)
+
+ * lib/malloc.c, lib/getpagesize.h: Deleted.
+ * Makefile: Add COOKIE_BUG configuration option. Delete malloc
+ related stuff.
+ * lib/Makefile: Delete malloc-related stuff.
+ * lib/new.c: Workaround COOKIE_BUG if necessary.
+
+ * refer/lkbib.c, refer/indxbib.c: Don't include refer.h. Include
+ needed header files directly.
+ * refer/refer.h: Omit definition of DEFAULT_INDEX.
+ * Makefile: Include definition of DEFAULT_INDEX in path.h.
+
+Sun Jul 19 10:19:22 1992 James Clark (jjc at jclark)
+
+ * lib/font.c (FONT_COMMAND_HANDLER): Pass command name and single
+ argument.
+ * lib/font (font::load_desc, font::load): Don't split argument of
+ unknown command.
+ (font::handle_unknown_font_command): Change type.
+ * ps/ps.c (ps_font::handle_unknown_font_command,
+ handle_unknown_desc_command): Change type.
+ * dvi/dvi.c (dvi_font::handle_unknown_font_command): Change type.
+
+Fri Jul 17 11:12:49 1992 James Clark (jjc at jclark)
+
+ * lib/font.h (font::handle_unknown_font_command): Add file and
+ line arguments.
+ * lib/font.c (font::handle_unknown_font_command):
+ * ps/ps.c (ps_font::handle_unknown_font_command):
+ * dvi/dvi.c (dvi_font::handle_unknown_font_command): Add file and
+ lineno arguments. Use _with_file_and_line functions for error
+ reporting.
+
+ * lib/fontfile.c (font::unknown_desc_command_handler): New static
+ data member.
+ * lib/font.c (font::set_unknown_desc_command_handler): New
+ function.
+ (font::load_desc): For unknown commands, call
+ unknown_desc_command_handler if not null.
+ * lib/font.h (class font): Declare them.
+ (FONT_COMMAND_HANDLER): New typedef.
+ * ps/ps.c (handle_unknown_desc_command): New function.
+ (main): Set bflag if we had a -b option. Call
+ font::set_unknown_desc_command_handler.
+ (broken.h): Don't include.
+ * ps/Makefile: No need for broken.h. Pass BROKEN_SPOOLER_FLAGS to
+ submake
+ * ps/devps/Makefile: Add `broken' command to DESC file using
+ BROKEN_SPOOLER_FLAGS.
+
+ * macros/tmac.e ([, ]): Add as synonyms for { and }.
+
+ * macros/tmac.e ($p): Only exdent if \$3 > 0.
+
+ * macros/tmac.e (@R, @S): New macros.
+ Declare @, po, $0, $i, $p, df, so, fu, bt, *, ?a, ?b, ?C, ?e, ?H,
+ ?I, ?n, ?o, ?R, ?s, ?T, ?W, ?w registers with @R.
+ Declare $H, $[0-9], .. macros with @S.
+ Declare |0, |1, |2, |3 strings with @S.
+
+ * macros/tmac.e (@S): Rename to @U.
+
+ * macros/tmac.e (@z): Define @b and bp as empty instead of
+ deleting them,
+
+ * macros/tmac.e (@m): Deleted.
+ (@h): Don't call @m.
+ (@z): Don't set @m trap.
+
+ * macros/tmac.e ($h, $f): Define |z as empty string.
+
+ * macros/tmac.e (@D): Rework to avoid unbalanced .el requests.
+ (@q): Likewise.
+
+ * macros/tmac.e (@h): Set ?H, ?C , ?s registers to 0 rather than
+ removing them.
+ ()f): Likewise for * register.
+
+ * macros/tmac.e (sr): Don't ever scale the arguments. If the third
+ argument is missing, don't change $R. Call sr with three
+ arguments when initializing.
+
+Thu Jul 16 12:17:12 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.e (sr): New macro.
+ Initialize $r and $R using sr.
+
+ * macros/tmac.e (,): Delete \*(#[.
+
+ * troff/env.c (set_tabs): Read the tab type even if the position
+ is bad. Allow the position of the first tab stop to be negative.
+
+Wed Jul 15 13:14:37 1992 James Clark (jjc at jclark)
+
+ * refer/dirnamemax.c: Use pathconf() if <unistd.h> defines
+ _POSIX_VERSION.
+ * refer/Makefile: Compile dirnamemax.c using -DHAVE_UNISTD_H
+ rather than -DPATHCONF_MISSING.
+ * Makefile: Get rid of PATHCONF_MISSING.
+
+ * refer/map.c: New file.
+ * refer/index.c: Interface to mmap through map.c. Rename map_size
+ to map_len.
+ * refer/Makefile: Handle map.c.
+ * Makefile: Include -DHAVE_MMAP in OLDCFLAGS rather than CFLAGS.
+
+Tue Jul 14 14:15:20 1992 James Clark (jjc at jclark)
+
+ * Makefile: RANLIB should be `true' if there is no ranlib.
+ * lib/Makefile (libgroff.a): Simplify.
+ * driver/Makefile (libdriver.a): Simplify.
+
+ * Makefile: Change -DWAIT_COREDUMP_0200 to -DWCOREFLAG=0200.
+ * groff.c (WCOREDUMP): Use WCOREFLAG. Define only if not already
+ defined.
+
+Sat Jul 11 09:19:17 1992 James Clark (jjc at jclark)
+
+ * troff/env.c (compare_ranges): Declare as extern "C".
+
+ * troff/input.c (init_registers): Use `struct tm' instead of `tm'.
+
+ * macros/tmac.s, macros/tmac.e: Change .nx /dev/null to .nx.
+
+Wed Jul 8 11:52:27 1992 James Clark (jjc at jclark)
+
+ * pic/troff.c (troff_output::text): Merge in grops_output::text,
+ but conditionalize use of \X based on \*(.T.
+ (grops_output::*): Deleted.
+ * pic/output.h: Delete declaration of make_grops_output.
+ * pic/main.c (main): Ignore -p and -x. driver_extension_flag is 1
+ by default. -n sets it to 0.
+ (usage): Corresponding changes.
+ * groff.c (main): Don't pass -x or -p to pic.
+ * groff.sh: Likewise.
+
+ * ps/ps.c (ps_printer::do_exec, ps_printer::do_file): Force ndefs
+ to be non-zero.
+
+ * ps/devps/afmtodit: Change calculation of asc_boundary and
+ desc_boundary. Make these bounds inclusive.
+ * ps/devps: Regenerate font files.
+
+Tue Jul 7 13:14:15 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.latin1: New file.
+ * macros/tmac.tty-char: Use tmac.latin1.
+ (tmac.tty-tr): Deleted.
+ * macros/Makefile: Install tmac.latin1.
+ * macros/tmac.dvi: Use tmac.latin1.
+ * macros/troffrc: Translate \[char160] onto no-break space here.
+ * macros/{tmac.dvi,tmac.ps,tmac.tty,tmac.X75}: Don't do it here.
+
+Mon Jul 6 11:06:52 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.Xps: Use `do' request.
+
+ * macros/tmac.ps: Use `do' request.
+
+ * macros/tmac.e (@C): Use `do' request.
+
+ * macros/tmac.X, macros/tmac.Xps: Moved from xditview.
+ * macros/Makefile: Install tmac.X*.
+
+ * tty/tmac.tty, tty/tmac.tty-char: Move to macros.
+ * tty/Makefile: Don't install tmac.tty*.
+ * macros/Makefile: Install tmac.tty*.
+
+ * dvi/tmac.dvi: Move to macros.
+ * dvi/Makefile: Don't install tmac.dvi.
+ * macros/Makefile: Install tmac.dvi.
+
+ * ps/tmac.ps*: Move to macros.
+ * ps/Makefile: Don't install tmac.ps*.
+ * macros/Makefile: Install tmac.ps*.
+
+ * eqn/box.c: Provide draw_lines parameter corresponding to -D
+ option.
+ * macros/eqnrc: Set draw_lines parameter based on device.
+ * groff.c: Don't pass -D flag to eqn.
+ * groff.sh: Likewise.
+ * eqn/main.c: Warn about use of -D.
+
+ * troff/input.c (process_startup_file): New function.
+ (main): Call process_startup_file().
+ * macros/troffrc: New file.
+ * macros/Makefile: Install troffrc.
+ * groff.c (main): Don't pass extra -m option to troff. For a
+ pseudo device pass the name of the pseudo device to troff using
+ -d.
+ * groff.sh: Likewise.
+ * groff.c (possible_command::prepend_arg): Deleted.
+
+ * troff/input.c (do_request): New function.
+ (init_input_requests): Bind "do" to do_request.
+
+ * eqn/main.c (main): Instead of loading eqnchar from device directory,
+ load eqnrc from macro directory.
+ * macros/eqnrc: New file.
+ * macros/Makefile: Install eqnrc.
+ * ps/devps/eqnchar: Deleted.
+ * ps/devps/Makefile: Don't install eqnchar.
+ * dvi/devdvi/eqnchar: Deleted.
+ * dvi/devdvi/Makefile: Don't install eqnchar.
+ * groff.c (main): Pass -M to eqn. Don't pass -F to eqn. New
+ variable optM.
+
+ * lib/device.[ch]: New files.
+ * lib/font.h (font::set_device_name, font::get_device_name):
+ Deleted.
+ * lib/fontfile.c: Use device.h.
+ * lib/Makefile: Handle device.[ch]. Make paths.h define DEVICE.
+ * troff/input.c: Delete definition of `device'.
+ (main): Don't initialize device.
+ * troff/troff.h: Include device.h rather than declaring device.
+ * troff/Makefile: No need to handle DEVICE.
+ * driver/input.c: Include device.h. Don't use
+ font::{set,get}_device_name.
+ * groff.c, Makefile: Rename device.h to config.h.
+ * groff.c: Use library device variable.
+ * eqn/main.c: Use library device variable.
+ * eqn/Makefile: No need to handle DEVICE.
+
+ * lib/searchpath.[ch]: New files.
+ * lib/Makefile: Handle searchpath.[ch].
+ * troff/input.c (open_file, init_dirs): Deleted.
+ (macro_dirs): Deleted.
+ (open_mac_file, macro_source): Use class search_path.
+ (add_string, struct string_list): Move definition.
+ (main): Change -M option to use macro_path. Delete call to
+ init_dirs().
+ * lib/fontfile.c (font::command_line_font_dir, font::open_file):
+ Rewrite to use class search_path.
+ * lib/font.h, lib/fontfile.c (font::cl_font_dirs): Deleted.
+ * lib/Makefile: fontfile.c depends on searchpath.h.
+ * lib/Makefile: Rename fontpath.h to paths.h. Make paths.h define
+ MACROPATH.
+ * lib/macropath.[ch]: New files.
+ * troff/Makefile: No need to handle MACROPATH.
+
+ * troff/input.c: Delete DUMP code.
+ * lib/fontfile.c, lib/font.h: Delete
+ font::forget_command_line_font_dirs.
+
+ * troff/input.c (push_token): New function.
+ (handle_first_page_transition): Use push_token().
+ (process_input_stack): Change handling of a space at the beginning
+ of the line.
+
+Sun Jul 5 17:11:09 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (font_dirs): Delete unused variable.
+
+ * eqn/lex.c (do_set): Correct error messages.
+
+Sat Jul 4 10:20:55 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (do_define_string): Allow the string name to be
+ followed immediately by a tab.
+ (define_character): Likewise.
+
+Thu Jul 2 10:59:15 1992 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::draw): When drawing an arc, don't allow k to
+ be negative.
+
+ * troff/input.c (input_iterator::is_file): New virtual function.
+ (file_iterator::is_file): New function.
+ (input_stack::end_file): New function.
+ (input_stack::next_file): Handle the situation where there is no
+ file on the input stack correctly. Avoid making two passes over
+ the input stack.
+ (next_file): Make the filename optional; in this case call
+ input_stack::end_file().
+
+Wed Jul 1 10:17:25 1992 James Clark (jjc at jclark)
+
+ * dvi/tmac.dvi: Change the definitions of \(ul and _ so that they
+ produce a real _ charater when the current font is CW and _
+ otherwise.
+
+ * lib/errarg.c (errarg::errarg(const char *)): Invert conditional
+ expression to work around gcc 2.2 bug.
+
+Wed Jun 24 08:12:24 1992 James Clark (jjc at jclark)
+
+ * eqn/main.c (main): Don't give an error if we can't find eqnchar.
+
+ * troff/env.c (environment::add_padding): New function.
+ (environment::add_char): Use add_padding().
+ (environment::space): Likewise.
+ (environment::wrap_up_field): Add some padding if there is none
+ and there's no current tab.
+ * troff/env.h: Declare environment::add_padding.
+
+Mon Jun 22 08:37:45 1992 James Clark (jjc@jclark)
+
+ * pic/pic.y: undef fmod and rand before declaring them.
+
+Sun Jun 14 11:40:18 1992 James Clark (jjc@jclark)
+
+ * troff/input.c (main): If the DESC file specifies a font name of
+ 0, then leave the corresponding font position empty.
+
+ * nroff.sh: New file.
+ * Makefile (install.nobin): Install nroff.sh.
+
+ * tty/devlatin1/R.proto: Add ao as synonym for de.
+ * tty/tmac.tty-char: Define ao as o.
+
+ * tty/dev{ascii,latin1}/R.proto: Add aq.
+ * tty/tmac.tty-char: Delete definition of aq.
+
+Mon Jun 8 11:43:20 1992 James Clark (jjc@jclark)
+
+ * troff/input.c (init_charset_table): Don't translate 0240.
+ * ps/tmac.ps: Translate char160 to space.
+ * dvi/tmac.dvi: Likewise.
+ * tty/tmac.tty: Likewise.
+
+Sun Jun 7 10:52:35 1992 James Clark (jjc@jclark)
+
+ * dvi/tmac.dvi: Add support for all Latin-1 characters.
+
+ * macros/tmac.s: Delete definitions of \(rg, \(ah, \(ad, \(a-,
+ \(ao, \(ac, \(ho, \(-D, \(Sd, \(TP, \(Tp, \(ss, \(AE, \(ae, \(OE,
+ \(oe, \(r?, \(r!.
+
+ * tty/tmac.tty-char: Add \(ah.
+
+ * dvi/tmac.dvi: Add definitions of Tp, TP, Sd, -D, ho.
+ No need to define \(FM and \(!/. Conditionalize all character
+ definitions.
+
+ * ps/devps/lgreekmap: Add +h, +f, +p.
+
+ * ps/tmac.psnew: New file.
+ * ps/Makefile: Install tmac.psnew.
+
+ * troff/input.c (charinfo_to_node_list): Don't ever interpret
+ character definitions in compatible mode.
+
+ * troff/input.c (remove_character): New function.
+ (init_input_requests): Bind remove_character to "rchar".
+
+ * ps/tmac.psold: New file.
+ * ps/Makefile: Install tmac.psold.
+ * ps/tmac.ps: Load tmac.psold. Move definitions of ISO Latin-1
+ characters into tmac.psold. Make these definitions unconditional.
+
+ * tty/tmac.tty-char: Define \n(_C only if it is not already defined.
+
+ * ps/tmac.ps: Don't define \('c and \('C.
+
+ * ps/devps/textmap: Move Greek characters to...
+ * ps/devps/symbolchars:
+
+Sat Jun 6 16:41:17 1992 James Clark (jjc@jclark)
+
+ * ps/devps/text.enc: Add quotesingle.
+ * ps/devps/textmap: Add +h, +f, +p, Fn, Bq, bq, aq, lz.
+ * tty/tmac.tty-char: Likewise.
+ * dvi/devdvi/texmi.map: Add +h, +f, +p.
+ * dvi/devdvi/texi.map: Add Fn.
+ * dvi/devdvi/msam.map: Add lz.
+ * dvi/tmac.dvi: Handle Bq, bq, aq.
+
+ * pic/lex.c (get_token): Recognize 'th.
+ * pic/map.y: Allow `expr'th in contexts where ORDINAL was allowed.
+
+Fri Jun 5 11:20:46 1992 James Clark (jjc@jclark)
+
+ * ps/devps/textmap: Move di, mu, +- to...
+ * ps/devps/symbolchars:
+
+ * macros/tmac.s (@XS): Don't call par@reset or fi.
+ (XA): Call LP. Turn off adjustment. Reduce line length.
+
+ * macros/tmac.s: Initially alias XS to LP.
+ (XS): Rename to @XS.
+ (cov*ab-init): Alias XS to @XS.
+
+Thu Jun 4 09:12:05 1992 James Clark (jjc@jclark)
+
+ * troff/token.h: Delete TOKEN_CHAR_HEIGHT, TOKEN_CHAR_SLANT,
+ TOKEN_FONT_NAME, TOKEN_FONT_POSITION, TOKEN_SIZE tokens.
+ (token::is_size, token::changes_env): Deleted.
+ * troff/number.c (parse_term): No need to process \s explicitly.
+ Call tok.next() only after scale indicator has been processed.
+ * troff/input.c (do_overstrike, do_bracket): No need to process \s,
+ \f etc explicitly.
+ (token::next): Handle \s, \f, \S, \H immediately rather than
+ returning them as tokens.
+ (token::operator==, token::description, token::add_to_node_list,
+ token::process): Remove handling of deleted tokens.
+
+ * troff/env.c (environment::add_char): When adding padding
+ indicator character, call start_line() if necessary.
+
+Wed Jun 3 09:55:50 1992 James Clark (jjc@jclark)
+
+ * ps/devps/afmtodit: Don't output 0 kerns.
+
+ * ps/devps/afmtodit: Remove directory from name of encoding in
+ font description file.
+
+ * ps/devps/afmtodit: Improve error messages.
+
+ * ps/devps/afmtodit: Allow DESC file to be specified with -d.
+
+ * ps/devps/Makefile: Incorporate FontMakefile. Rework.
+ * ps/devps/FontMakefile: Deleted.
+ * ps/devps/afmname: New file.
+
+ * ps/devps/symbol.sed: New file.
+ * ps/devps/symbol.diff: Deleted.
+ * ps/devps/FontMakefile: Generate symbol.afm using symbol.sed.
+ Generate zapfdr.afm from zapfd.afm.
+
+ * tty/tmac.tty (tty-char): Prefix definition with ".
+
+ * macros/tmac.an (TP): Don't start a diversion if one has already
+ been started.
+
+ * tty/tmac.tty-char: Add Latin-1 characters.
+
+ * tty/tmac.tty-char: Incorporate suggestions from Paul Eggert.
+
+Tue Jun 2 00:54:34 1992 James Clark (jjc@jclark)
+
+ * tbl/table.c (table::allocate): Delete old_vline, old_entry.
+ Move declaration of struct horizontal_span.
+
+ * tbl/table.c (table::table): Initialize span_list.
+ (table::~table): Delete span_list.
+
+ * lib/ptable.h (PTABLE(T)::~PTABLE(T)): Delete v.
+
+ * ps/devps/Makefile: Avoid dependency on GNU make.
+
+ * ps/tmac.ps: Check that character does not already exist before
+ defining it.
+
+ * tty/tmac.tty: Add definitions of \(ff, \(!=, \(==, \(~=, \(sq,
+ \(OE, \(oe, \(AE, \(ae, \(lh, \(rh. Delete definitions of \(en,
+ \(ru, \(ul, \(br, \(bv, \(sl which are in the font description
+ files.
+
+ * tty/tmac.tty-char: New file.
+ * tty/Makefile: Install tmac.tty-char.
+ * tty/tmac.tty: Move definitions of \(ua, \(da, \(uA, \(dA into
+ tmac.tty-char.
+
+ * tty/tmac.tty: Fix definition of \(34.
+
+ * tty/dev{ascii,latin1}/R.proto: Add ha and ti. Map
+ bracket-drawing characters onto |. Add *o.
+
+ * troff/env.c (environment::wrap_up_tab): Increment field_spaces
+ only if current_field.
+
+ * troff/dictionary.c (dictionary::lookup): Free old_table after
+ rehashing.
+
+Mon Jun 1 10:15:22 1992 James Clark (jjc@jclark)
+
+ * tty/dev{ascii,latin1}/R.proto: Add uppercase Greek characters
+ whose glyphs are identical to glyphs of some Roman character.
+
+ * tty/devlatin1/R.proto (bu): Deleted.
+ * tty/devascii/R.proto (bu): Deleted.
+ * tty/tmac.tty: Add definition of \(bu.
+
+ * eqn/main.c (do_file): Pass FILE as argument.
+ (main): Automatically load eqnchar. New options -F and -n.
+ Pass do_file an opened FILE.
+ * groff.c: Don't pass eqnchar to eqn. Pass -F options onto eqn.
+ No need to include font.h.
+ * groff.sh: Likewise. Don't need to use - for standard input.
+ Prefix files with -- if first file starts with -.
+
+ * macros/tmac.e: Conditionalize use of \$* on \n(.g.
+
+ * troff/env.c (environment::possibly_break_line): Don't set line
+ to 0 across call to output_line(). Don't call output_line() until
+ after discarding nodes after break.
+
+Sun May 31 10:45:29 1992 James Clark (jjc@jclark)
+
+ * request.h (macro::empty): Declare it.
+ * input.c (macro::empty): New method.
+ (interpolate_macro): Don't give a WARN_SPACE if the two-character
+ macro is empty.
+
+Sat May 30 10:27:15 1992 James Clark (jjc@jclark)
+
+ * troff/env.c (environment::start_field): Decrement space_total
+ when a space is frozen.
+
+Fri May 22 14:34:38 1992 James Clark (jjc@jclark)
+
+ * macros/tmac.an (R): Delete macro.
+
+ * troff/input.c (get_copy, token::next): Support \# (like \" but
+ newline is ignored).
+
+ * troff/input.c (token::next): Fix error message in 'Y' case.
+
+Thu May 21 09:26:24 1992 James Clark (jjc@jclark)
+
+ * eqn/delim.c (define_extensible_string): Recognize any prefix of
+ a delimiter name.
+
+Fri May 15 10:20:41 1992 James Clark (jjc at jclark)
+
+ * c++test.c: Include <osfcn.h>.
+
+ * lib/strtol.c, lib/getcwd.c, ps/psbb.c: Declare errno in case
+ <errno.h> doesn't.
+
+Fri May 8 09:37:19 1992 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::divide_span): Don't count column separation
+ if expand was specified.
+
+ * tbl/main.c (process_format): Don't ignore width specs in
+ continued format. Give warning for changing equal widths or
+ column separation in continued format.
+ (process_data): Set column separation, minimum width, equal
+ columns at end of table.
+
+Thu May 7 08:50:40 1992 James Clark (jjc at jclark)
+
+ * troff/node.c (kern_pair_node::add_discretionary_hyphen,
+ node::add_discretionary_hyphen): Use soft_hyphen_char.
+ (set_soft_hyphen_char): New function.
+ (init_node_requests): Bind to shc. Initialize soft_hyphen_char.
+
+ * Makefile (c++tested): Give more helpful message if test fails.
+
+Tue May 5 10:58:39 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (init_charset_table): Translate 0240 to
+ an unbreakable space.
+
+ * troff/token.h (token::hyphen_indicator): New function.
+ * troff/charinfo.h (TRANSLATE_HYPHEN_INDICATOR): New special
+ translation.
+ * troff/input.c (translate): Allow translation to \%.
+ * troff/node.c (node::add_char): Handle
+ TRANSLATE_HYPHEN_INDICATOR.
+ (make_node): Don't allow TRANSLATE_HYPHEN_INDICATOR here.
+
+ * troff/input.c (init_charset_table): Don't set BREAK_AFTER flag
+ for \(hy.
+
+ * tty/devlatin1/R.proto: \(hy and - should print as 055.
+
+Tue Apr 21 09:24:42 1992 James Clark (jjc at jclark)
+
+ * groff.c (run_commands): If the last command gets a SIGPIPE send
+ a SIGPIPE to all children than haven't yet terminated. When
+ command terminates, set pid field to -1.
+
+Fri Apr 17 11:20:48 1992 James Clark (jjc at jclark)
+
+ * groff.c (main): Pass an appropriate -filename option to gxditview.
+
+Thu Apr 16 15:11:40 1992 James Clark (jjc at jclark)
+
+ * Makefile.bd (install): Remove existing program before copying.
+
+ * Makefile, */Makefile, Makefile.bd, groff.sh, groff.c: Allow
+ programs which have Unix counterparts to be installed with
+ user-specified prefix.
+
+ * troff/input.c (exit_troff): Don't check if exit_started.
+ (exit_request): Don't call exit_troff if exit_started.
+
+ * Makefile.bd (install.mm): Rename to install.dwbmm.
+
+Tue Apr 14 10:05:10 1992 James Clark (jjc at jclark)
+
+ * driver/input.c (do_file): Add missing break for '#' case.
+
+Mon Apr 13 10:11:02 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (input_stack::clear): Clear past any boundaries and
+ then add the boundaries back.
+
+ * troff/input.c (exit_troff): Return immediately if already
+ exiting.
+
+ * macros/tmac.s (pg@end-text): New macro. Use pg@end-text for the
+ end macro.
+ (pg*end-page): If the text has ended and there are no more
+ footnotes or keeps, exit.
+
+ * macros/doc-ditroff (Lq, Rq): Define as \(lq and \(rq.
+
+ * troff/input.c (init_charset_table): Make \(rq transparent by
+ default.
+
+ * macros/tmac.an: Define lq and rq strings.
+
+ * macros/tmac.s (Q, U): Define as \(lq and \(rq.
+
+Sun Apr 12 12:54:37 1992 James Clark (jjc at jclark)
+
+ * troff/env.c (environment::final_break): New function.
+ (environment::newline): Set prev_line_interrupted to 2 if
+ exit_started.
+ * troff/env.h: Declare environment::final_break.
+ * troff/input.c (exit_troff): Call environment::final_break()
+ instead of environment::do_break().
+
+ * macros/Makefile: Install man.local if $(MACRODIR)/man.local
+ doesn't already exist.
+ * macros/man.local: New file.
+ * macros/tmac.an: Load man.local.
+ * macros/man.ultrix: New file.
+
+Sat Apr 11 17:32:04 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (exit_groff): Rename to...
+ (exit_troff): New function.
+
+ * troff/div.c (exit_started, done_end_macro,
+ seen_last_page_ejector): New global variables.
+ (began_page_in_end_macro): New static variable.
+ (exit_flag): Deleted.
+ (top_level_diversion::top_level_diversion): Initialize
+ last_page_count.
+ (top_level_diversion): More elaborate test for whether
+ cleanup_and_exit() should be called.
+ Set began_page_in_end_macro if the end macro isn't yet finished.
+ * troff/div.h (top_level_diversion::last_page_count): New data
+ member.
+ (top_level_diversion::set_last_page): New function.
+ (exit_started, done_end_macro, seen_last_page_ejector): Declare.
+ * troff/env.c (do_break): Zero prev_line_interrupted.
+ * troff/input.c (exit_flag): Delete declaration.
+ (LAST_PAGE_EJECTOR): New magic cookie.
+ (token::next): Handle LAST_PAGE_EJECTOR.
+ (exit_groff): Set exit_started and done_end_macro instead of
+ exit_flag. Call top_level_diversion::set_last_page. Push a
+ LAST_PAGE_EJECTOR instead of calling push_page_ejector(). Do
+ another ejection after setting seen_last_page_ejector.
+
+Thu Apr 9 04:37:11 1992 James Clark (jjc at jclark)
+
+ * etc/grog.sh, etc/grog.sh: Recognize -me sh macro.
+
+ * macros/tmac.e (TH): Make sure there's room for the initial
+ header.
+
+ * macros/tmac.s (par@init): Make PD and DD at least \n(.V.
+ Set FVS in points rather than units.
+
+Mon Apr 6 11:21:32 1992 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::add_trap): Don't consider the
+ position of empty slots.
+
+Fri Apr 3 10:46:45 1992 James Clark (jjc at jclark)
+
+ * ps/devps/S: Fix height and depth of parenrightex.
+ * ps/devps/symbol.diff: Regenerate.
+
+Sat Mar 28 21:17:52 1992 James Clark (jjc at jclark)
+
+ * tmac.e (u): Do underlining as in -mgs.
+
+Fri Mar 27 09:23:44 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c (tty_printer::end_page): If overstriking is
+ suppressed, still turn overstruck horizontal and vertical lines
+ into +.
+
+ * lib/new.c: Back out Feb 24 change; no longer needed with gcc
+ 2.1.
+
+ * refer/label.y (format_expr::evaluate): Avoid use of %0*d.
+
+Wed Mar 18 09:29:10 1992 James Clark (jjc at jclark)
+
+ * Version 1.05 released.
+
+Tue Mar 17 16:50:45 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c: Instead of keeping an array of glyphs and then
+ sorting it, keep a ordered linked list of glyphs for each line.
+
+ * driver/driver.h: Include stddef.h.
+
+ * tty/tty.c (compare_glyph):
+ * refer/refer.c (rcompare):
+ * troff/env.c (compare_ranges): Arguments of qsort comparison
+ function should be const void *.
+
+ * troff/number.c (parse_term):
+ * dvi/dvi.c (draw_dvi_printer::draw): Avoid initialization in
+ switch statement.
+
+ * refer/label.y (consider_authors): Don't access variables
+ constructed under a condition outside that condition: put braces
+ round for statement containing declaration; redeclare use of same
+ variable later.
+
+ * pic/pic.y (text_expr): Delete production that allows
+ parenthesised text_expr.
+ (expr): Allow a conditional_expr to appear in parentheses.
+ (conditional_expr): Rename to any_expr.
+
+ * mm: Install new version 1.01 from jh.
+
+ * lib/font.c (font::get_width): Cache scaled widths.
+ (font::font): Initialize widths_cache.
+ (font::~font): Destroy widths_cache.
+ * lib/font.h: Add font::widths_cache. Declare font_widths_cache.
+
+Mon Mar 16 10:16:10 1992 James Clark (jjc at jclark)
+
+ * c++test.c, c++test.ref: New files.
+ * Makefile: Check that the C++ compiler works.
+
+ * ps/tmac.pspic (PSPIC): Do a break.
+
+ * ps/tmac.ps: Move definition of PSPIC into...
+ * ps/tmac.pspic: New file.
+ (PSPIC): Draw box around picture, but make it invisible to grops.
+ * ps/tmac.ps: Load tmac.pspic.
+ * ps/Makefile: Install tmac.pspic.
+
+Sun Mar 15 14:18:08 1992 James Clark (jjc at jclark)
+
+ * lib/font.c (scale_round): If n is negative,
+ subtract .5 before truncating floating point result.
+
+ * lib/fontfile.c: Include <errno.h>.
+
+Tue Mar 10 14:17:03 1992 James Clark (jjc at jclark)
+
+ * driver/input.c (get_char): Inline. Don't update current_lineno.
+ Change callers to up date current_lineno if necessary.
+ Use get_char() instead of getc(current_file).
+
+Sun Mar 8 18:05:28 1992 James Clark (jjc at jclark)
+
+ * ps/tmac.ps: Fix up spacing of \(mo and \(nm.
+
+Fri Mar 6 19:38:58 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c (tmac.tty): Define \(rg as (R).
+
+Tue Mar 3 10:11:25 1992 James Clark (jjc at jclark)
+
+ * lib/lib.h: New define a_delete.
+ * Use a_delete instead of delete when deleting an array of objects
+ without destructors.
+
+ * lib/lib.h: Rename adelete to ad_delete.
+ * Change uses of adelete.
+
+Mon Mar 2 12:41:05 1992 James Clark (jjc at jclark)
+
+ * eqn/eqn.y: Include lib.h.
+
+ * troff/node.c (grow_font_table): Delete old_font_table.
+
+ * mm: Install new version from jh.
+
+Fri Feb 28 10:42:23 1992 James Clark (jjc at jclark)
+
+ * tbl/table.h (format_type): Make global instead of local to class
+ entry_format. Prefix enumerators with FORMAT_.
+ * tbl/table.c, tbl/main.c: Corresponding changes.
+ * refer/token.h (token_type): Make global. Prefix enumerators
+ with TOKEN_.
+ * refer/token.[ch]: Corresponding changes.
+ * Makefile: Get rid of -DNO_NESTED_TYPES configuration option.
+
+ * troff/div.c (node::set_vertical_size): Don't name argument.
+
+Thu Feb 27 10:29:19 1992 James Clark (jjc at jclark)
+
+ * Makefile: New configuration option ARRAY_DELETE_NEEDS_SIZE.
+ * lib/lib.h: Define adelete accordingly.
+ * pic/object.c (graphic_object::graphic_object):
+ * tbl/main.c (format::~format):
+ * tbl/table.c (table::~table):
+ * refer/ref.c (reference::~reference, reference::merge,
+ reference::insert_field, reference::delete_field): Use adelete.
+
+ * Makefile: Change NESTED_TYPES to NO_NESTED_TYPES.
+ * refer/token.h:
+ * tbl/table.h: Corresponding changes.
+
+ * common.c (common_output::dashed_arc, common_output::dotted_arc):
+ Ensure total_angle is positive.
+
+Wed Feb 26 08:49:26 1992 James Clark (jjc at jclark)
+
+ * refer/ref.c (reference::merge, reference::insert_field,
+ reference::delete_field): Avoid delete[0].
+
+ * refer/token.c (init_special_chars): Move calls to cmupper
+ outside calls to init_two_char_letter to work around bug in gcc
+ 2.0.
+
+Mon Feb 24 14:20:00 1992 James Clark (jjc at jclark)
+
+ * lib/new.c (operator new): Use __builtin_new for g++.
+
+ * pic/object.c (graphic_object::~graphic_object): Don't use
+ delete [] on 0.
+
+ * pic/object.c (output::compute_scale): Initialize max_width and
+ max_height.
+
+Sat Feb 15 09:55:20 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (write_request): Call fflush.
+
+ * troff/node.h (class composite_node): Move declaration to node.c
+ * troff/input.c (charinfo_to_node): Rename to ...
+ (charinfo_to_node_list): Return node list rather than composite
+ node.
+ * troff/node.c (make_composite_node): New function.
+ (make_node, add_char): Call make_composite_node instead of
+ charinfo_to_node.
+ (class composite_node): Add a tfont * member. Delete font_size
+ member.
+ (composite_node::composite_node, composite_node::copy,
+ composite_node::size): Corresponding changes.
+ (composite_node::tprint): Provide constant spacing, emboldening
+ and track kerning as specified in tfont.
+ (composite_node::width): Change width calculation accordingly.
+ * troff/env.h (environment::composite): New member.
+ (environment::is_composite, environment::set_composite): New
+ functions.
+ * troff/env.c (environment::environment): Initialize composite.
+ * troff/input.c (charinfo_to_node): Call
+ environment::set_composite.
+ * troff/node.c (make_composite_node, make_glyph_node): Use the
+ plain version of the tfont if the environment is composite.
+
+ * troff/node.c (font_info::get_space_width): Additional argument
+ giving space_size. Handle constant space correctly. Scale by
+ space_size unless constant spaced.
+ (env_sentence_space_width): New function.
+ * troff/node.h: Declare it.
+ * troff/env.h (environment::get_space_size,
+ environment::get_sentence_space_size,
+ environment::get_narrow_space_width,
+ environment::get_half_narrow_space_width): Make inline.
+ (environment::get_space_width): Make inline. Just call
+ env_space_width.
+ * troff/env.c: Delete definitions for funtions made inline.
+ (environment::space_newline, environment::space): Use
+ env_sentence_space_width(). Don't scale by space_size.
+ * troff/node.h: Move declarations of env*space_width() functions
+ into env.h.
+
+Sat Feb 8 09:30:22 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.s (PS): Don't try to set negative indent.
+
+Thu Feb 6 09:00:35 1992 James Clark (jjc at jclark)
+
+ * pic/pic.y: Fix min function.
+
+Tue Jan 28 07:52:29 1992 James Clark (jjc at jclark)
+
+ * man/mdate.sh: Clear LANGUAGE.
+
+Sun Jan 19 13:02:41 1992 James Clark (jjc at jclark)
+
+ * pic/pic.y, pic/lex.c: Rename COMMAND token to COMMAND_LINE.
+ * pic/lex.c: New COMMAND keyword.
+ * pic/pic.y (print_args, print_arg): New rules.
+ (placeless_element): Use print_args for PRINT.
+ New COMMAND element.
+
+Tue Jan 7 13:14:31 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (terminal): Handle missing argument correctly.
+
+ * pic/pic.y (text_expr): New rule.
+
+ * pic/pic.y: Implement := operator.
+
+Sun Jan 5 10:23:02 1992 James Clark (jjc at jclark)
+
+ * etc/grog.pl, etc/grog.sh: Distinguish old and new versions of
+ mdoc.
+
+Sat Jan 4 14:42:26 1992 James Clark (jjc at jclark)
+
+ * ps/devps/dingbatsrmap: Include this in the distribution.
+
+ * macros/tmac.doc: Replace with new version from 2nd Networking
+ Release. Fix loading of doc-* files.
+ * macros/{doc-common,doc-ditroff,doc-nroff,doc-syms}: New files.
+ * macros/tmac.doc.old: New file. Apply fixes that had been
+ applied to old tmac.doc.
+ * macros/tmac.andoc: Check that we're running under groff.
+ * macros/Makefile: Rework.
+
+Fri Jan 3 13:27:51 1992 James Clark (jjc at jclark)
+
+ * tbl/table.h (format_type):
+ * refer/token.h (token_type): If NESTED_TYPES is defined, use
+ typedef to make these types visible at file scope.
+ * Makefile: Add NESTED_TYPES configuration option.
+
+ * troff/div.c (mark): At the top level use the value of
+ nl_reg_contents rather than the current vertical position.
+
+Thu Jan 2 10:34:51 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c: Implement \D for horizontal or vertical lines.
+ (tty_printer::set_char): Use vec_used+2 as serial number.
+ Don't allow size of vector to exceed USHRT_MAX-2.
+ Split off part into...
+ (tty_printer::add_char): New function.
+ (tty_printer::draw): New function.
+ (compare_glyph): Handle equal serial numbers.
+ (tty_printer::end_page): Handle overstruck characters from \D.
+ (main, usage): Implement -d option.
+
+Mon Dec 23 10:37:51 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_format):
+ * eqn/text.c (split_text):
+ * troff/input.c (token::next): Use inner block for declarations
+ with initializers in switch statement.
+
+Mon Dec 16 20:52:03 1991 James Clark (jjc at jclark)
+
+ * pic/common.c (common_output::dash_line): Cope with zero-length
+ lines.
+
+Sun Nov 17 12:04:08 1991 James Clark (jjc at jclark)
+
+ * Version 1.04 released.
+
+Wed Nov 13 05:27:21 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.an (TH): Define a macro an-init to define variables
+ based on command line arguments.
+ (an-header): Call it.
+
+Sun Nov 3 12:07:34 1991 James Clark (jjc at jclark)
+
+ * Makefile (install.mm): Rename to install.dwbmm.
+
+ * Makefile: Integrate mm.
+ * mm: New directory.
+
+Wed Oct 30 10:11:34 1991 James Clark (jjc at jclark)
+
+ * refer/dirnamemax.c: If PATHCONF_MISSING is defined, include
+ <sys/types.h>.
+
+ * pic/troff.c (troff_output::simple_spline,
+ troff_output::simple_polygon): Rename variable `v' to `d' to avoid
+ shadowing parameter.
+
+ * lib/tmpfile.c (xtmpfile): Declare dir as const char *.
+
+ * lib/ptable.h: Add explicit casts when converting from unsigned
+ long to unsigned.
+
+ * dvi/devdvi/{SA,SB,msam.map,msbm.map}: New files.
+ * dvi/devdvi/Makefile: Install SA, SB.
+
+ * refer/indxbib.c: Add declaration of mktemp.
+
+ * refer/lookbib.c: Add declaration of isatty.
+
+Fri Oct 25 09:00:17 1991 James Clark (jjc at jclark)
+
+ * pic/lex.c (interpolate_macro_with_args): While collecting
+ arguments, keep track of whether we're in a string.
+
+Wed Oct 23 08:42:48 1991 James Clark (jjc at jclark)
+
+ * ps/tmac.ps (PSPIC): Do the .sp after the \X, and move the \X
+ down with \v, so as to avoid problems with top of page trap
+ setting no space mode.
+
+Tue Oct 22 17:38:49 1991 James Clark (jjc at jclark)
+
+ * eqn/lex.c (get_delimited_text): Allow tab before macro body.
+
+Tue Oct 15 17:24:53 1991 James Clark (jjc at jclark)
+
+ * ps/psrm.c (ps_get_line): Fix bug when lines longer than 255.
+ Improve error message.
+
+Fri Oct 11 11:09:38 1991 James Clark (jjc at jclark)
+
+ * ps/psrm.c (print_ps_string): Don't pass negative numbers to
+ printf("%03o");
+
+Wed Oct 9 17:50:14 1991 James Clark (jjc at jclark)
+
+ * groff.c (possible_command::execp): Always use _exit() after a
+ failed exec.
+
+ * Makefile: Add HAVE_UNION_WAIT, HAVE_PID_T, WAIT_COREDUMP_0200,
+ NO_SYS_WAIT_H configuration options.
+ * groff.c: Use these options. Use POSIX-style macros to extract
+ fields from the status returned by wait().
+
+Fri Oct 4 12:12:27 1991 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::compute_separation_factor): Allow the
+ separation factor to drop to 0.
+
+Tue Oct 1 18:12:38 1991 James Clark (jjc at jclark)
+
+ * refer/search.c: Include <errno.h>.
+
+Sun Sep 29 08:40:57 1991 James Clark (jjc at jclark)
+
+ * pic/pic.y (YYDEBUG): Don't define for Borland C++.
+
+ * lib/lib.h: #ifdef out declarations of itoa and iftoa for Borland
+ C++.
+
+ * pic/lex.c (input_stack::bol): Move definition out of class body.
+
+ * pic/main.c: On MSDOS munge argv[0].
+
+ * lib/ptable.h: Define name2 as _Paste2 for Borland C++.
+
+ * lib/ptable.c (hash_string): Use unsigned long rather than
+ unsigned.
+ (next_ptable_size): Use unsigned rather than int. Give an error
+ message if we've hit the largest table size.
+ * lib/ptable.c: Corresponding changes. Also use unsigneds for the
+ table size.
+
+ * pic/object.h (object_spec): Make flags unsigned long. Declare
+ flags as const unisgned long rather than as enums.
+
+ * pic/output.c: Deleted.
+
+ * pic/troff.c (troff_output::simple_ellipse): Remove spurious %.
+
+ * tbl/table.c (simple_entry::note_double_vrule_on_{left,right}):
+ Add additional argument.
+ (line_entry::note_double_vrule_on_{left,right}): Set value of
+ douvle_vrule_on_{right,left} flag according to argument.
+ (simple_line_entry::simple_print,
+ simple_line_entry::double_line_print): If adjacent to double vrule
+ on a corner extend rather than shorten the rule by half the double
+ vrule sep.
+
+ * troff/number.c (parse_term): In checking for overflow, handle the
+ case where the current horizontal position is negative.
+
+Thu Sep 12 08:26:09 1991 James Clark (jjc at jclark)
+
+ * pic/object.c (draw_arrow): Check for object having zero length.
+
+Wed Sep 11 10:32:38 1991 James Clark (jjc at jclark)
+
+ * eqn/main.c (do_file): Split off inline equation handling into...
+ (inline_equation): New function. Search for starting delimiter
+ using...
+ (delim_search): New function. Don't recognize a delimiter that
+ occurs in the name of an escape sequence, number register, string
+ etc.
+
+Tue Sep 10 04:01:11 1991 James Clark (jjc at jclark)
+
+ * eqn/delim.c (delim_box::compute_metrics): Don't call
+ define_extensible_string if left is 0.
+ (delim_box::output): Don't print the left delimiter if left is 0.
+ (delim_box::debug_print): Check for left == 0 before calling printf.
+
+Fri Aug 23 13:02:30 1991 James Clark (jjc at jclark)
+
+ * troff/Makefile (majorminor.c): Include only digits in
+ minor_version.
+
+Thu Aug 22 09:35:37 1991 James Clark (jjc at jclark)
+
+ * refer/dirnamemax.c: new file.
+ * refer/genlimits.c: Deleted.
+ * refer/indxbib.c (main): Use dir_name_max() instead of NAME_MAX.
+ Don't check path length.
+ * refer/Makefile: Add dir_name_max.o; delete genlimits.
+ * Makefile: Add PATHCONF_MISSING option.
+
+ * refer/indxbib.c (get_cwd): New function.
+ (main): Use get_cwd().
+ * lib/getcwd.c: New file.
+ * Makefile: Delete -DHAVE_GETWD. Include GETCWD variable. Pass
+ GETCWD in SUBFLAGS.
+ * lib/Makefile: Compile getcwd.o.
+
+ * ps/tmac.psatk (psatk-defs): Define showpage after pushing
+ userdict.
+
+ * refer/indxbib.c (main): Check success of mktemp.
+
+ * lib/tmpfile.c: New file.
+ * lib/Makefile: Add tmpfile.c.
+ * lib/lib.h: Declare xtmpfile(); include <stdio.h>.
+ * ps/ps.h: Delete declaration of mktemp().
+ * ps/ps.c (ps_printer::ps_printer): Use xtmpfile().
+ * refer/refer.c (divert_to_temporary_file): Use xtmpfile().
+ * driver/driver.h: No need now to include errno.h.
+
+ * everywhere: Set errno to 0 before calling fopen().
+
+ * eqn/eqn.h, etc/soelim.c, driver/driver.h, etc/addftinfo.c,
+ dvi/tfmtodit.c, groff.c, refer/index.c, refer/linear.c,
+ refer/lookbib.c, refer/refer.h, ps/psbb.c: Include <errno.h>.
+
+Mon Aug 19 10:52:18 1991 James Clark (jjc at jclark)
+
+ * troff/env.h (translate_space_to_dummy): Declare it.
+ * troff/env.c (environment::space_newline, environment::space):
+ If translate_space_to_dummy is set then make the width of spaces 0.
+ * troff/input.c (translate): If the second character of a
+ translation is a space, translate to unbreakable space. If the
+ first character is a space, set or clear translate_space_to_dummy
+ according to whether the second character is \&. Weird!
+
+Tue Jul 30 10:03:56 1991 James Clark (jjc at jclark)
+
+ * groff.c (run_commands): Don't use non-zero exit code because a
+ command gets SIGPIPE.
+
+ * groff.c, groff.sh: Use -mXps with -TXps.
+
+ * ps/ps.c (ps_printer::special): Move call to flush_sbuf() into...
+ (ps_printer::do_exec, ps_printer::do_file, ps_printer::do_def,
+ ps_printer::do_mdef, ps_printer::do_import): Call flush_sbuf().
+ (ps_printer::special): New specials invis and endinvis.
+ (ps_printer::do_invis, ps_printer::do_endinvis): New functions.
+ (ps_printer::set_char, ps_printer::draw): Return if invis_count>0.
+ (ps_printer::end_page): Check that invis_count == 0.
+ (ps_printer::invis_count): New member.
+ (ps_printer::ps_printer): Initialize invis_count to 0.
+
+ * troff/env.c (environment::hyphenate_line): Hyphenation
+ indicator at beginning of word inhibits splitting after -, \(em
+ etc.
+
+ * pic/pic.y (element): Allow another element to follow } without
+ any intervening separator.
+
+Mon Jul 22 12:27:37 1991 James Clark (jjc at jclark)
+
+ * pic/lex.c (get_delimited): Allow tabs before delimiter.
+
+Wed Jul 17 10:59:08 1991 James Clark (jjc at jclark)
+
+ * groff.c: Get rid of HAVE_UNION_WAIT stuff. Instead suppress
+ declaration of wait() in header files.
+ * Makefile: Get rid of -DHAVE_UNION_WAIT.
+
+ * tbl/table.c (alphabetic_text_entry::add_tab): New function.
+
+ * lib/lib.h: Declare return type of strerror as char *.
+
+ * man/Makefile: Add g flag to sed substitutions.
+ * Makefile (shgroff, bindist): Likewise.
+
+Sun Jul 14 11:57:02 1991 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::do_import): Move push of userdict into...
+ * ps/devps/prologue (PBEGIN): Define showpage after pushing
+ userdict.
+
+Sat Jul 13 20:53:04 1991 James Clark (jjc at jclark)
+
+ * ps/devps/prologue (PBEGIN): Zap any definition of showpage in
+ userdict.
+
+Fri Jul 12 07:10:09 1991 James Clark (jjc at jclark)
+
+ * man/mdate.sh: Handle the fact that BSD ls -l does not print the
+ group.
+
+Sun Jul 7 08:00:23 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (define_number_reg): If currently undefined,
+ don't define it if the argument is an invalid expression.
+
+ * Makefile: Ignore return value of `if' commands without `else'
+ parts.
+
+ * Makefile: Split up CPPDEFINES into a series of separate
+ configuration options.
+
+ * troff/input.c (init_registers): Use time_t instead of long
+ unless LONG_FOR_TIME_T is defined. Use returned result rather
+ than passing pointer.
+ * Makefile: Document LONG_FOR_TIME_T as a CPPDEFINE.
+
+ * lib/Makefile (fontpath.h): Use gendef.
+
+Thu Jul 4 09:48:05 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (input_iterator::shift): Delete argument name.
+ * troff/node.c (suppress_output_file::really_begin_page,
+ suppress_output_file::really_transparent_char, node::ascii_print,
+ node::tprint): Delete names of unused arguments.
+
+Wed Jul 3 17:34:57 1991 James Clark (jjc at jclark)
+
+ * refer/label.y (string): Pass $4 to command_error.
+
+Tue Jul 2 15:06:01 1991 James Clark (jjc at jclark)
+
+ * Version 1.03 released.
+
+Sat Jun 29 08:14:01 1991 James Clark (jjc at jclark)
+
+ * Makefile: Pass definition of SHELL in SUBFLAGS.
+
+ * gendef: New file.
+ * Makefile, eqn/Makefile, refer/Makefile, troff/Makefile,
+ ps/Makefile: Use gendef to construct header files that are
+ constructed from the Makefile.
+
+ * macros/Makefile: make all should build stripped version of tmac.e.
+
+ * refer/Makefile (clean): Remove y.output.
+
+Fri Jun 28 09:44:36 1991 James Clark (jjc at jclark)
+
+ * ps/pfbtops.c (main): Add -v option which prints out a version
+ number.
+ * ps/Makefile (pfbtops): Link with libgroff.a.
+
+Fri Jun 21 07:43:23 1991 James Clark (jjc at jclark)
+
+ * refer/search.h (linear_searcher::get_nkeys): Delete declaration.
+ * refer/linear.c (linear_searcher::get_nkeys): Delete definition.
+
+ * refer/lkbib.c (main): Always terminate reference with blank
+ line.
+ * refer/lookbib.c (main): Likewise.
+
+ * refer/linear.c (file_buffer::load): Check that the file is not a
+ binary file.
+
+ * refer/Makefile (genlimits): Possibly add -DHAVE_SYS_DIR_H.
+ (genlimits.c): Include <sys/dir.h> if HAVE_SYS_DIR_H is defined.
+ Delete second inclusion of <sys/param.h>.
+
+Tue Jun 18 01:32:26 1991 James Clark (jjc at jclark)
+
+ * troff/token.h (token::special): Deleted.
+
+ * tbl/main.c (process_format): Rework so that opt->tab_char is
+ recognized only when appropriate.
+
+ * ps/Makefile (clean): Remove pfbtops.
+
+Sun Jun 16 09:37:19 1991 James Clark (jjc at jclark)
+
+ * lib/font.c (text_file::next): Don't return if we have got a
+ blank line.
+
+Fri Jun 14 09:52:26 1991 James Clark (jjc at jclark)
+
+ * refer/refer.c (store_reference): Get hash code from old_table[i]
+ when rehashing the table.
+
+Thu Jun 13 01:26:43 1991 James Clark (jjc at jclark)
+
+ * eqn/box.c (box::top_level): Save size and prev size using \R and
+ restore it afterwards. Set the size to the size at the beginning
+ of the line.
+ * eqn/pbox.h: Declare SAVED_INLINE_PREV_SIZE_REG,
+ SAVED_INLINE_SIZE_REG, and SAVED_SIZE_REG.
+
+ * refer/Makefile (limits.h): Use ./genlimits.
+
+Wed Jun 12 16:05:34 1991 James Clark (jjc at jclark)
+
+ * refer/index.c: Delete declarations of stat() and fstat().
+
+Tue Jun 11 14:52:49 1991 James Clark (jjc at jclark)
+
+ * tty/tmac.tty: Add character definitions for \(>= and \(<=.
+
+Mon Jun 10 22:49:48 1991 James Clark (jjc at jclark)
+
+ * etc/grog.sh, etc/grog.pl: Change regex for .PS.
+
+Fri Jun 7 09:13:06 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (token::get_char): Handle \e.
+
+ * refer/linear.c: Delete declarations of fstat() and stat().
+
+Wed Jun 5 09:11:59 1991 James Clark (jjc at jclark)
+
+ * troff/node.c, troff/env.c, troff/input.c, Makefile: Remove
+ OP_DELETE_BROKEN stuff, since we now have a fix for g++.
+
+Mon Jun 3 13:41:32 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (do_define_macro): Improve error handling for end
+ of file while defining macro.
+
+Sun Jun 2 10:20:24 1991 James Clark (jjc at jclark)
+
+ * eqn/box.h: Fix declaration of set_gsize.
+ * eqn/box.c (set_gsize): Make argument const char *.
+ (gsize): Declare as char *.
+ * eqn/main.c (main): Don't convert gsize to int.
+ * eqn/lex.c (do_gsize): Pass char * to set_gsize.
+
+ * Version 1.02 released.
+
+Sat Jun 1 12:19:46 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.andoc: New file.
+ * macros/Makefile: Install tmac.andoc.
+
+ * troff/node.c, troff/env.c, troff/input.c: Conditionalize use of
+ operator new and delete on OP_DELETE_BROKEN not being defined.
+ * Makefile: Mention OP_DELETE_BROKEN.
+
+Mon May 27 13:49:07 1991 James Clark (jjc at jclark)
+
+ * Makefile (bindist): Pass SUBFLAGS.
+
+Sun May 26 14:13:22 1991 James Clark (jjc at jclark)
+
+ * Makefile, groff.c: Pass definitions to groff.c via device.h.
+
+ * tty/tty.c (tty_font::load_tty_font): Avoid shadowing
+ parameter.
+
+ * ps/Makefile, ps.c: Pass BROKEN_SPOOLER_FLAGS via broken.h.
+
+ * ps/ps.h, ps/psrm.c: Make comment_table and
+ header_comment_table local to resource_manager::process_file.
+
+ * groff.sh: With -TXps pass -printCommand option to gxditview.
+
+ * groff.c (possible_command::print): Implement using
+ append_arg_to_string.
+
+ * xditview: Merge in new implementation with own ChangeLog.
+
+Sat May 25 18:33:20 1991 James Clark (jjc at jclark)
+
+ * groff.c (main): Implement PRINT_OPTION.
+ (append_arg_to_string): New command.
+ (device_table): Set PRINT_OPTION flag for Xps.
+
+Fri May 24 09:48:58 1991 James Clark (jjc at jclark)
+
+ * troff/groff.h: Rename to troff.h.
+
+ * pic/lex.c (lookup_keyword, docmp): New functions.
+ (get_token): Use new lookup_keyword.
+ Don't include key.h.
+ * pic/key.[ch], pic/pic.gperf: Deleted.
+ * pic/Makefile: Remove gperf stuff.
+
+ * pic/Makefile, pic/output.h: Move definition of TEX_SUPPORT
+ into output.h.
+ * pic/tex.c: Move include of pic.h before test of TEX_SUPPORT.
+
+ * troff/Makefile, troff/node.c: Move definition of
+ STORE_WIDTH into node.c.
+
+ * etc/grog.pl, etc/grog.sh: Support -mdoc.
+
+Thu May 23 12:30:49 1991 James Clark (jjc at jclark)
+
+ * dvi/devdvi/texr.map, dvi.devdvi/texi.map,
+ dvi/devdvi/texb.map: Add lq and rq.
+ dvi/devdvi: Regenerate fonts.
+ * ps/devps/textmap: Add lq and rq.
+ * ps/devps: Regenerate fonts.
+ * tty/devascii/R.proto, tty/devlatin1/R.proto: Add lq and rq.
+ * macros/tmac.e: Define \*(lq and \*(rq to be \(lq and \(rq.
+
+ * pic/object.c (position_rectangle): When checking radius
+ cope with possiblity that width or height is negative.
+ (box_object::box_object): Have separate xrad and yrad with
+ signs matching signs of dim components.
+ (box_object::{north,south}_{east,west}): Use xrad and yrad.
+ (box_object::print): With rounded boxes use absolute values
+ for dim and rad arguments.
+
+ * lib/Makefile, lib/fontfile.o: Pass definition of FONTPATH
+ in fontpath.h.
+
+ * eqn/Makefile, eqn/main.c: Pass definition of DEVICE in device.h.
+
+ * various files: Add explicit destructors to keep Saber CC +d
+ happy.
+
+Wed May 22 11:37:11 1991 James Clark (jjc at jclark)
+
+ * eqn/box.c (box::top_level): Restore fonts correctly after
+ font changes in line containing inline equation. Also
+ restore previous font as well as current font.
+ * eqn/pbox.h: Define necessary string and register names.
+
+ * troff/input.c (token::next): Case 'R' calls do_register.
+ (do_register): New function.
+
+Tue May 21 11:28:23 1991 James Clark (jjc at jclark)
+
+ * groff.c, groff.sh: Support Xps device. Allow each device
+ to have a pseudo_name and a real_name.
+
+ * groff.c (run_commands): Don't print `Broken pipe' messages.
+
+ * ps/pfbtops.c: New file.
+ * ps/Makefile: Add pfbtops.
+
+ * troff/number.c (parse_term): Improved error message.
+
+Mon May 20 11:22:14 1991 James Clark (jjc at jclark)
+
+ * groff.c, groff.sh, etc/grog.sh, etc/grog.pl: Support grefer.
+
+ * Makefile: Integrate refer.
+ * refer: New directory.
+ * man/grefer.man, man/glookbib.man, man/gindxbib.man,
+ man/lkbib.man: New files.
+ * man/Makefile: Support refer man pages.
+
+ * lib/lib.h: Declare is_prime.
+ * lib/prime.c: New file.
+
+ * troff/input.c (macro_source): New function.
+ (init_input_requests): Bind "mso" to macro_source.
+
+ * troff/env.c (environment::possibly_break_line): Maintain
+ pointer to pointer to node to be split in ndp so as to avoid
+ using address of freed node.
+
+ * troff/env.c (environment::hyphenate_line): Maintain pointer to
+ pointer to first node to be hyphenated in startp so as to
+ avoid using address of freed node.
+
+ * troff/env.c (class trie, class hyphen_trie): Make the
+ elements of the trie be of type char not unsigned char.
+ Declare arguments to be const char* instead of unsigned char *.
+
+ * troff/env.c (hyphenate): Initialize hbuf[0].
+
+ * troff/input.c (set_string): Declare p to be char * and cast
+ *p to unsigned char when necessary.
+
+ * troff/input.c (do_define_macro): Declare s to be const
+ char*. Cast element to unisgned char when necessary, Declare
+ d to be an int. Handle EOF better.
+
+ * troff/Makefile, troff/input.c: Different scheme for passing
+ definitions of MACROPATH, HYPHENFILE and DEVICE.
+
+Tue May 14 13:41:36 1991 James Clark (jjc at jclark)
+
+ * tty/devascii/R.proto: Delete entry for em.
+ * tty/devlatin1/R.proto: Likewise.
+
+Sat May 11 11:13:28 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (translate): Stop when we get a space. Treat eof
+ like newline.
+
+ * macros/tmac.an (IP): Only pass quoted argument to TP when \n(.$>1.
+
+Wed Apr 24 19:24:33 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_format): A font name following a `f'
+ modifier that starts with a digit can be only one character long.
+ Also deal with EOF on the second character of the font name.
+
+Wed Apr 17 11:23:43 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Turn \~ into an
+ unbreakable_space_node.
+ * troff/node.c (unbreakable_space_node): New class.
+ * troff/node.h: Declare it.
+
+Tue Apr 16 10:47:12 1991 James Clark (jjc at jclark)
+
+ * dvi/dvi.c (dvi_printer::set_char): Make code an int. Check that
+ it's >= 0, before outputting it as a single byte.
+
+Mon Apr 15 11:20:23 1991 James Clark (jjc at jclark)
+
+ * lib/font.c: Make font_char_metric::code an int.
+ (font::get_code): Change return type to int.
+ (font::load): Allow code to be arbitrary integer.
+ * lib/font.h (font::get_code): Change return type to int.
+ (font::number_to_index): Change argument type to int.
+ * troff/input.c (token::next): In case 'N', allow any value.
+ Store value in token::val.
+ (token::operator==): For TOKEN_NUMBERED_CHAR test equality of val.
+ (token::get_char, token::add_to_node_list, token::process): Get
+ number from val.
+ (charinfo::set_number): Change argument to int.
+ (charinfo::get_number): Require that NUMBERED flag be set.
+ (get_charinfo_by_number): Store numbered characters not between 0
+ and 255 in a dictionary.
+ * troff/charinfo.h (get_charinfo_by_number): Change argument type
+ to int.
+ (charinfo::number): Change type to int.
+ (charinfo::set_number): Change type of set_number to int.
+ * troff/node.c (troff_output_file::put_char_width,
+ troff_output_file::put_char): Test whether character is numbered
+ using charinfo::numbered().
+ * driver/printer.c (printer::set_numbered_char): Allow arbitrary
+ values of num.
+ * lib/nametoindex.c: New implementation to cope with arbitrary
+ number characters.
+
+ * troff/input.c (token::operator==): Test val for
+ TOKEN_CHAR_HEIGHT, TOKEN_CHAR_SLANT, TOKEN_FONT_POSITION, and
+ TOKEN_SIZE.
+
+ * man/Makefile: Add definiton of BROKEN_SPOOLER_FLAGS.
+ (.man.n): sed out @BROKEN_SPOOLER_FLAGS@.
+
+Sun Apr 14 12:57:00 1991 James Clark (jjc at jclark)
+
+ * ps/devps/zapfdr.ps: Don't copy UniqueID. Avoid use of newdict
+ variable.
+
+ * all Makefiles: rm targets of cp and >.
+
+ * xditview/xtotroff.c (MapFont): Unlink troff_name before opening
+ it.
+
+ * eqn/lex.c (def_table): Add dollar.
+
+Sat Apr 13 13:02:44 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (do_width): Push back newline before closing delim
+ like do_bracket.
+
+Fri Apr 12 15:16:03 1991 James Clark (jjc at jclark)
+
+ * groff.c (possible_command::prepend_arg): New function.
+ (main): Prepend device -m option.
+ * groff.sh: Put device -m options before command-line options.
+
+Tue Apr 9 10:24:43 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.an (IP): Quote argument to TP.
+
+ * ps/ps.c (main): New option -b, which sets...
+ (broken_flags): New variable.
+ (ps_printer::~ps_printer): Incorporate the setup section in the
+ prolog if (broken_flags & NO_SETUP_SECTION).
+ (ps_printer::begin_page): Generate {Begin,End}PageSetup comments.
+ (ps_printer::merge_download_fonts, ps_printer::merge_import_fonts,
+ ps_printer::merge_ps_fonts, ps_printer::print_font_comment,
+ ps_printer::print_needed_font_comment,
+ ps_printer::print_supplied_font_comment,
+ ps_printer::print_include_font_comments,
+ ps_printer::lookup_doc_font, ps_printer::download_fonts,
+ ps_printer::read_download_file, read_document_fonts, add_font,
+ skip_line, parse_fonts_arg, document_font::document_font,
+ document_font::~document_font, document_font::download,
+ ps_output::include_file): Deleted.
+ (ps_printer::~ps_printer): Generate %%EOF. Generate %!PS-Adobe-3.0
+ rather than %!PS-Adobe-2.0. Make calls to
+ resource_manager::need_font for each font that we used. Replace
+ calls to merge_ps_fonts, merge_download_fonts, print_font_comment,
+ print_supplied_font_comment, print_needed_font_comment by call to
+ resource_manager::print_header_comments. Output %%Orientation
+ comment. Output %%Requirements: numcopies comment if ncopies > 1.
+ Don't output the prolog directly. Instead call
+ resource_manager::output_prolog. Only define #copies when ncopies
+ > 1. Delete calls to print_include_font_comments and
+ download_fonts. Add call to resource_manager::document_setup.
+ (ps_printer::do_file): Call resource_manager::import_file instead
+ of including it ourselves.
+ (ps_printer::do_import): Likewise. Also don't call
+ merge_import_fonts. Push userdict on the dictionary stack before
+ and pop it afterwards.
+ Move declaration of ps_output into ps.h.
+ * ps/psrm.c: New file implementing resource_manager class.
+ * ps/ps.h: New file declaring ps_output and resource_manager
+ classes.
+ * ps/devps/zapfdr.ps:
+ * ps/devps/symbolsl.ps:
+ * ps/devps/prologue: Use 3.0 conventions.
+ * ps/Makefile: Pass definition of BROKEN_SPOOLER_FLAGS in DEFINES.
+ Add default definition of BROKEN_SPOOLER_FLAGS.
+ * Makefile: New variable BROKEN_SPOOLER_FLAGS. Add
+ BROKEN_SPOOLER_FLAGS to SUBFLAGS.
+
+Mon Apr 8 09:26:54 1991 James Clark (jjc at jclark)
+
+ * etc/grog.pl: New file.
+ * Makefile (GROG): New variable.
+ Add GROG to SUBFLAGS.
+ * etc/Makefile (GROG): New variable.
+ (install.nobin): Install $(GROG) rather than grog.sh.
+
+Thu Apr 4 11:36:45 1991 James Clark (jjc at jclark)
+
+ * eqn/special.c (special_box::compute_metrics): Make the input and
+ output strings the same. Get the new height and depth from the
+ predefined height and depth registers. Also make subscript kern
+ and skew available.
+ (special_box::compute_subscript_kern, special_box::compute_skew):
+ New functions.
+
+ * eqn/box.c (pointer_box::compute_skew,
+ simple_box::compute_metrics, box::top_level)
+ * eqn/text.c (prime_box::compute_metrics,
+ prime_box::comput_subscript_kern)
+ * eqn/limit.c (limit_box::compute_metrics):
+ * eqn/delim.c (build_extensible, delim_box::compute_metrics):
+ * eqn/sqrt.c (sqrt_box::compute_metrics): Protect possibly
+ negative numbers in `nr' requests with a leading 0.
+
+Wed Apr 3 15:58:23 1991 James Clark (jjc at jclark)
+
+ * eqn/special.c: New file.
+ * eqn/eqn.y: Declare token SPECIAL. Make it right associative.
+ Add new rule for simple.
+ * eqn/lex.c (token_table): Add SPECIAL.
+ * eqn/box.h: Declare make_special_box.
+ * eqn/Makefile: Add special.[co].
+
+Sat Mar 30 10:57:53 1991 James Clark (jjc at jclark)
+
+ * ps/devps/prologue: Possibly set packing to true while defining.
+ Create grops dictionary here. Initialize local variables before
+ defining procedures.
+ (PICTURE): Rename to PBEGIN. Also do save, noop showpage, count
+ the dictionary stack. Set strokeadjust and overprint to false if
+ the relevant operators are defined.
+ (PEND): New procedure.
+ * ps/ps.c (ps_printer::~ps_printer): In the prolog just include
+ prologue. Do everything else in the setup section.
+ (ps_printer::do_import): Just call PBEGIN and PEND around the
+ picture. Also push userdict before, and pop it afterwards.
+
+Wed Mar 27 07:59:50 1991 James Clark (jjc at jclark)
+
+ * troff/node.c (bracket_node::tprint): Brackets were being printed
+ 1m too low.
+
+ * macros/tmac.an (SH, SS): Set fill mode.
+
+Tue Mar 26 07:46:31 1991 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::begin_page): Set
+ high_water_mark to 0.
+
+Fri Mar 22 09:19:46 1991 James Clark (jjc at jclark)
+
+ * man/mdate.sh: New file.
+ * man/mdate.c: Deleted.
+ * man/Makefile: Use mdate.sh instead of mdate.
+ (mdate): Deleted.
+
+ * eqn/lex.c (do_gsize): Supply missing argument to error message.
+
+Tue Mar 19 11:06:50 1991 James Clark (jjc at jclark)
+
+ * man/mdate.c: New file.
+ * man/*.man: Replace modification date by @MDATE@.
+ * man/Makefile (.man.n): Replace @MDATE@ by `mdate $<`.
+ (mdate): New target.
+
+ * lib/font.c (text_file::next): Deal with arbitrarily long lines.
+ Remove illegal input characters.
+
+Mon Mar 18 08:32:25 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (pg*start-col): Do .ns *after* running the hooks.
+
+Sat Mar 16 03:52:25 1991 James Clark (jjc at jclark)
+
+ * troff/div.c (begin_page): Change behaviour when
+ !first_page_begun and !break_flag.
+
+ * troff/input.c (do_name_test): Return 0 if argument is empty.
+
+ * troff/input.c (read_long_escape_name): Require closing ] to be
+ at same input level as opening [.
+
+ * troff/input.c (read_increment_and_escape_name): New function.
+ (get_copy, process_input_stack): Use this for \n.
+
+Fri Mar 15 00:31:48 1991 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::begin_page): Ignore the
+ current value of page_number if !first_page_begun.
+
+ * groff.c (main): Fix declaration of buf.
+
+ * troff/input.c (do_name_test): New function.
+ (token::next): Implement \A.
+ (token::next): Implement \e by turning it into a TOKEN_ESCAPE.
+ (token::description, token::add_to_node_list, token::process):
+ Handle TOKEN_ESCAPE.
+ * troff/token.h: New token TOKEN_ESCAPE.
+
+Thu Mar 14 10:22:26 1991 James Clark (jjc at jclark)
+
+ * pic/main.c (do_picture): Allow space before and after filename
+ following `<'. Check that the filename is not empty.
+
+Wed Mar 13 12:49:40 1991 James Clark (jjc at jclark)
+
+ * Version 1.01 released.
+
+ * dvi/devdvi/CompileFonts: Add cm*ss10 fonts.
+
+ * dvi/tmac.dvi: ftr HR to H.
+
+ * macros/tmac.e: Round up computation of $r.
+
+ * xditview/tmac.X: Don't give up completely in compatibility mode.
+ Use \n(.s instead of \n[.s].
+
+ * dvi/tmac.dvi: Don't give up completely in compatibility mode.
+ Use \(ci instead of \[ci]. Use \n(.s instead of \n[.s].
+ Add u to factors inside \s[...]. Rename frac to dvi-frac.
+ Translate \(FM onto \[prime] and \(!/ onto \[slashnot]; use these
+ short names in the char definitions.
+
+ * ps/tmac.ps: Don't give up completely in compatibility mode.
+ Fix the fraction definitions to use \n(.s and \(f/. Add an extra
+ quote in front of \n(.s. Add u to factors inside \s[...].
+
+Mon Mar 11 12:01:20 1991 James Clark (jjc at jclark)
+
+ * tty/tmac.tty: Call the nroff request.
+
+ * macros/tmac.e ((x, )x): Better definitions that work properly
+ in a diversion.
+ (@0, @1): Helper macros for (x.
+
+ * macros/tmac.e ($s, hl): Use \l rather than \D.
+
+ * tty/tmac.tty: Make it work better in compatibility mode.
+ (pchar): Rename to tty-char.
+
+ * macros/tmac.e (@E): New macro.
+ (r, i, b, rb, bi): Use @E.
+
+ * macros/tmac.e (@F): Don't use (;...) syntax.
+
+ * macros/tmac.e: Remove mention of \*(||/revisions. Mention that
+ it was modified for groff.
+
+ * macros/tmac.e: Make sure \n(ps and \n(es are >= \n(.V.
+
+ * macros/tmac.e (<., .>): Removed.
+ ([., .]): If \n(.V>=1v, use [] instead of superscripting.
+
+ * macros/tmac.e: Remove check that groff is being used.
+
+ * macros/tmac.e (@C): Change families only if using groff; turn
+ compatibility mode off while changing familes. Save compatibility
+ mode before changing families and restore it afterwards.
+
+ * macros/tmac.e (@h): Remove test for offset + line length.
+
+ * macros/tmac.e (sorry): Rename to @S. Use \$1 instead of \$0
+ (lo, th, ac): Define to call @S instead of using als.
+
+ * macros/tmac.e: Make $r and $R now contain \n(.v*100/\n(.sp, ie
+ the ratio of the vertical spacing to the point size in units
+ expressed as a percentage. Use these instead of $10r and $10R,
+ Delete $10r and $10R.
+
+ * lib/font.c (font::load): In default computation of space_width,
+ divide by sizescale. Use scale_round.
+
+ * macros/tmac.an (TP): Don't call `nf'.
+ (an-do-tag): Don't call `fi'.
+
+Sun Mar 10 09:52:35 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (process_input_stack): Handle the case where
+ spaces at the beginning of an input line are followed by a
+ newline.
+
+Thu Mar 7 20:18:07 1991 James Clark (jjc at jclark)
+
+ * groff.c (device_table): Add PIC_X_OPTION for dvi device.
+ * groff.sh: Use pic -x with the dvi device.
+
+ * dvi/devdvi/FontMakefile (H): Don't use -s.
+
+ * dvi/devdvi/HI, dvi/devdvi/HB: New files.
+ * dvi/devdvi/Makefile: Add HI and HB to FONTS.
+ * dvi/devdvi/FontMakefile: Add rules for HI and HB. Include these
+ in FONTS.
+
+Mon Mar 4 13:20:14 1991 James Clark (jjc at jclark)
+
+ * ps/psfig.diff: New file.
+ * ps/tmac.psfig: New file.
+
+Sat Mar 2 00:15:09 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (]=, ref*do-tl, ref*bib-print): Deleted.
+ (]-): Don't call ref*do-tl.
+
+ * macros/tmac.s (ref*end-print): Use XP if [F not defined.
+
+ * macros/tmac.s (ref*normal-print): Call FS rather than fn@do-FS.
+ (fn@do-FS): Rename to fn*do-FS.
+
+ * troff/input.c (transparent_translate): New function.
+ (process_input_stack): Apply transparent_translate before calling
+ diversion::transparent_output(unsigned char).
+
+Wed Feb 27 00:13:25 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (do_define_macro): Define the macro before calling
+ skip_line.
+
+ * xditview/Makefile: Add DEVICES variable. Change install target
+ to use this.
+
+Tue Feb 26 10:46:22 1991 James Clark (jjc at jclark)
+
+ * groff.c (run_commands): Handle the possibility that there are
+ child processes other than those forked by us.
+
+Sun Feb 24 21:32:30 1991 James Clark (jjc at jclark)
+
+ * lib/string.c (string::append): New function.
+ * lib/stringclass.h: Declare it.
+
+Thu Feb 21 11:49:26 1991 James Clark (jjc at jclark)
+
+ * eqn/main.c (main): New option -N which sets
+ no_newline_in_delim_flag.
+ (do_file): If no_newline_in_delim_flag is set don't allow newlines
+ in delimiters.
+ * groff.c (main): Pass -N on to eqn.
+ (help, synopsis): Mention -N.
+ * groff.sh: Implement -N.
+
+Wed Feb 20 15:16:10 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (]=, ref*bib-print, ref*do-tl): New macros.
+ (]-): Call ref*do-tl if ref*need-tl is non-zero.
+ (XP): Allow as initializer.
+
+Tue Feb 19 14:09:06 1991 James Clark (jjc at jclark)
+
+ * troff/env.c (environment::wrap_up_field): If field_spaces are
+ non-zero and we have a current_tab, subtract padding from
+ tab_distance. If this makes tab_distance <= 0, use the next tab
+ stop instead. If there isn't any next tab or it's a left tab,
+ wrap up the current tab.
+ (environment::start_field): Initialize tab_precedes_field.
+ (environment::wrap_up_tab): If there's a current field, update
+ pre_field_width, field_distance and tab_precedes_field.
+ * troff/env.h (environment::tab_precedes_field): New member.
+
+Fri Feb 15 01:24:00 1991 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::do_file): New function.
+ (ps_printer::special): Bind to `file' special.
+ (ps_printer::do_exec): Set ndefined_styles to 0.
+
+Sat Feb 9 03:03:04 1991 James Clark (jjc at jclark)
+
+ * eqn/text.c (split_text): Grok \* and similar escapes sequences.
+ Avoid stripping first character from the start of unrecognized
+ escapes. Use lex_error instead of error to report errors.
+ * eqn/lex.c (get_token): Rework handling of escapes.
+ (lex_error): Move declaration into...
+ * eqn/eqn.h.
+
+ * xditview/xditview.c (main): Make -page option work.
+
+ * Makefile: Correct comment about -DBROKEN_SPOOLER and pageview.
+
+Wed Feb 6 12:28:43 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (B2): Correct size of box.
+
+Tue Feb 5 00:37:35 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (B2): Postpone drawing the box until in the
+ top-level diversion.
+
+ * tty/tmac.tty: Add font translations for C, CR, CW.
+
+ * groff.c (synopsis, help): Document -i.
+ * groff.sh: Implement -i.
+
+ * macros/tmac.s (@NH): Put a `.' after multi-part numbers.
+ Simplify the construction of SN.
+
+ * troff/number.c (parse_term): Give `|' a higher precedence.
+ * tbl/table.c (numeric_text_entry::simple_print): Parenthesise
+ accordingly.
+
+ * macros/tmac.s (B2): Use par@finish instead of par@reset.
+
+Mon Feb 4 12:36:09 1991 James Clark (jjc at jclark)
+
+ * lib/string.c (string::move): New function.
+ * lib/stringclass.h: Declare it.
+
+Sat Feb 2 16:02:16 1991 James Clark (jjc at jclark)
+
+ * troff/env.c (distribute_space): Add optional argument
+ `force_forward'.
+ (environment::wrap_up_field): Call distribute_space with
+ `force_forward' argument of 1.
+
+Fri Feb 1 19:36:33 1991 James Clark (jjc at jclark)
+
+ * lib/string.c, lib/stringclass.h (string::operator+=(char)):
+ Inline it. Move reallocation into...
+ (string::grow1): New function.
+ * pic/Makefile, tbl/Makefile, eqn/Makefile, ps/Makefile: Redo
+ dependencies to include library header files.
+ * lib/Makefile: Make string.c and lf.c depend on stringclass.h.
+
+Thu Jan 31 15:02:27 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (@NH): Use the same number registers than -ms does
+ for the heading level counters. Use the same string that -ms does
+ for the number for this heading.
+
+Wed Jan 30 14:25:40 1991 James Clark (jjc at jclark)
+
+ * lib/new.c (operator new): Cast result of malloc to char *.
+
+ * troff/input.c (spring_trap, lookup_request): Add assert that nm
+ is not null.
+
+Tue Jan 29 18:08:05 1991 James Clark (jjc at jclark)
+
+ * groff.c (main): Support -i.
+
+Sun Jan 27 13:23:17 1991 James Clark (jjc at jclark)
+
+ * pic/pic.h: Include <osfcn.h>.
+
+ * ps/ps.c: Add declaration of mktemp.
+
+ * Makefile: Add -DHAVE_UNION_WAIT option for CPPDEFINES.
+ * groff.c: If HAVE_UNION_WAIT is defined, declare wait()'s
+ argument as union wait *.
+ (run_commands): If HAVE_UNION_WAIT is defined cast wait()'s
+ argument to union wait *.
+
+Sat Jan 26 12:04:52 1991 James Clark (jjc at jclark)
+
+ * tty/tmac.tty: Add definition of \(co.
+
+ * pic/object.c (make_arc): Only increase radius when radius
+ strictly less than d.
+ (arc_object::update_bounding_box): May need to add 4.0 to end_quad
+ more than once.
+
+ * troff/env.c (environment::environment(symbol),
+ environment::environment(const environment *)): Initialize
+ input_trap_count.
+
+Sat Jan 19 08:18:35 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (main): Add exit(0).
+
+ * ps/ps.c (ps_printer::~ps_printer): Use fseek instead of rewind.
+
+ * pic/main.c (main):
+ * eqn/main.c (main):
+ * tbl/main.c (main):
+ * etc/soelim.c (main):
+ * driver/printer.c (printer::~printer):
+ * troff/node.c (real_output_file::~real_output_file,
+ real_output_file::flush): Check for errors on stdout.
+
+ * most files: Add 1991 to copyright notice.
+
+ * macros/tmac.s: Don't test \n(.x and \n(.y.
+
+ * troff/input.c (token::next): Rename `escape_char' label to
+ `handle_escape_char' and `normal_char' label to
+ `handle_normal_char'.
+
+Thu Jan 17 15:46:35 1991 James Clark (jjc at jclark)
+
+ * groff.c (main, synopsis, help): Support -a option.
+ * groff.sh: Likewise. Also eliminate Zflag variable by adding -z
+ to trflags while parsing options.
+
+Tue Jan 15 13:07:27 1991 James Clark (jjc at jclark)
+
+ * troff/number.c (parse_term): With `m', `M' and `n' scale
+ indicators, convert scale factor to hunits before scaling.
+
+Mon Jan 14 12:39:12 1991 James Clark (jjc at jclark)
+
+ * lib/font.c (scale_round): Better test for overflow when n is
+ negative.
+
+Thu Jan 10 11:10:56 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_format): Add second argument of type
+ options*. Change callers. Allow opt->tab_char as well as '\t'
+ between format items.
+
+Mon Jan 7 12:30:18 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.an (PD): With no arguments, make sure register PD is
+ at least \n[.V].
+ (TH): Call PD with no argument, instead of setting register PD
+ directly.
+
+Sun Jan 6 11:18:39 1991 James Clark (jjc at jclark)
+
+ * Version 1.00 released.
+
+Sat Jan 5 08:44:30 1991 James Clark (jjc at jclark)
+
+ * ps/tmac.ps, xditview/tmac.X: Add font translation of C to CR.
+
+ * dvi/devdvi/DESC: Mount CW instead of CR.
+
+ * dvi/tmac.dvi: Add definition of \(tm.
+
+ * dvi/devdvi/texsy.map: Add lh, and rh.
+ * dvi/devdvi/texex.map: Add lt, rt, lb, rb, lk, rk.
+ * dvi/devdvi/texmi.map: Add *o. Regenerate fonts.
+
+ * dvi/devdvi/FontMakefile: Generate H from cmss10.
+ * dvi/devdvi/Makefile: Install H.
+ * dvi/devdvi/H: New file.
+
+Fri Jan 4 15:04:57 1991 James Clark (jjc at jclark)
+
+ * troff/env.c (vertical_spacing): Don't allow vertical spacing to
+ be 0.
+
+Thu Jan 3 13:41:19 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (@EN): Add \n(.V to the argument to ds@need.
+
+ * macros/tmac.pic (PS): Avoid attempting to set negative indent.
+
+ * macros/tmac.s (@EN): Handle the case where the equation is empty
+ but the label is not.
+
+Wed Jan 2 10:31:44 1991 James Clark (jjc at jclark)
+
+ * troff/groff.h: New warning category WARN_SPACE.
+ * troff/input.c: Add WARN_SPACE to DEFAULT_WARNING_MASK. Add
+ WARN_SPACE to warning_table.
+ (interpolate_macro): Give a warning of type WARN_SPACE if the name
+ is longer than two characters and is not defined, but the first
+ two characters do make a defined name.
+
+ * PROBLEMS: New file.
+
+ * CHANGES: New file.
+ * README-0.6, README-1.00: Deleted.
+
+ * groff.c, groff.sh: Add X75-12 and X100-12 devices.
+ * xditview/devX75/Makefile: Make devX75-12.
+ * xditview/devX100/Makefile: Make devX100-12.
+
+ * xditview/devX100/eqnchar, xditview/devX75/eqnchar,
+ dvi/devdvi/eqnchar, ps/devps/eqnchar: Remove use of \R.
+
+Tue Jan 1 19:24:01 1991 James Clark (jjc at jclark)
+
+ * README-0.7: Rename to README-1.00.
+
+ * macros/tmac.pic: New file.
+ * macros/Makefile (install.nobin): Install tmac.pic.
+
+Mon Dec 31 10:40:53 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (hyphen_word): Correct the test for whether the
+ token is a hyphen. Reset npos to 0.
+
+ * macros/tmac.s (par@sup-start, par@sup-end): New implementations.
+
+Sun Dec 30 15:53:13 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s (ds*common-end): Call par*reset.
+ (PE): Likewise.
+ (par@reset-indent): Deleted.
+
+ * macros/tmac.s (@IP): Divert the label.
+
+Sat Dec 29 14:33:32 1990 James Clark (jjc at jclark)
+
+ * xditview/draw.c (setGC): Use a line width of .1m rather than
+ .04m by default; round rather than truncate value.
+
+ * tbl/table.c (class empty_entry): New class.
+ (empty_entry::empty_entry, empty_entry::line_type): New functions.
+ (table::add_entry): Represent empty entries by objects of type
+ empty_entry.
+ (table_entry::line_type): Return -1.
+ (table::determine_row_type): Ignore entries with line_type 0.
+ Treat type -1 as non-lines.
+
+Fri Dec 28 15:04:41 1990 James Clark (jjc at jclark)
+
+ * ps/devps/textmap, xditview/libXdvi/DviChar.c, tty/devlatin1/R.proto,
+ macros/tmac.s: Rename \(-d to \(Sd.
+
+Thu Dec 27 12:35:47 1990 James Clark (jjc at jclark)
+
+ * ps/devps/textmap: Add `sd', `/_' and `3d' characters.
+ * xditview/libXdvi/DviChar.c: Likewise.
+ * dvi/devdvi/texsy.map: Add `<<', `>>'.
+
+Wed Dec 26 13:33:23 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::begin_page): Call
+ init_output() if the_output is 0.
+
+Sat Dec 22 12:35:29 1990 James Clark (jjc at jclark)
+
+ * troff/input.c: Replace ESCAPE_E by ESCAPE_e and ESCAPE_C by
+ ESCAPE_c.
+ (get_copy): Turn \E into ESCAPE_E.
+ (token::process, asciify): Handle ESCAPE_E.
+
+ * macros/tmac.s (ds*common-end, par@reset): Add `.rj 0'.
+ (RD): New macro.
+ (DS): Implement `.DS R'.
+
+Fri Dec 21 11:41:53 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s (FS): New macro.
+
+ * macros/tmac.s (fn@do-FS): Use @LP instead of LP.
+
+ * macros/tmac.s (cov*tl-init): Remove after first execution
+ instead of aliasing to @nop. Call top of page macro explicitly
+ instead of setting trap; call @init first. Set pg@top as top of
+ page macro.
+ (cov*auto-init): Deleted. Set cov*tl-init instead of
+ cov*auto-init as top of page trap.
+ (TL, LP): Do a break instead of calling cov*tl-init.
+ (cov*print): With RP format but no TL, alias FS and FE to @FS and
+ @FE; in this case also give a warning and always start another
+ page. No need to set pg@top here.
+ (cov*tl-init): Rename to cov*first-page-init.
+
+ * macros/tmac.s (RP): Do `.pn 0'.
+ (cov*tl-init): With RP format don't do `.pn 0'.
+
+ * macros/tmac.s (pg@cs-top): Set no space mode.
+
+ * macros/tmac.s (par@TL, par@AU, par@AI): New macros.
+ (cov*ab-init): Alias TL, AU and AI to these.
+
+Thu Dec 20 10:10:50 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s (@EQ): Move the space before the equation into @EN
+ (@EN): Do nothing unless \n[dl] is > 0.
+
+Tue Dec 18 12:20:47 1990 James Clark (jjc at jclark)
+
+ * pic/object.c (ellipse_object::radius): New function.
+
+ * VERSION: Change version to 0.7.
+
+ * tbl/table.c (block_entry::do_divert): Declare return type as
+ void.
+ (block_entry::divert, alphabetic_block_entry::divert): Return 1.
+
+Mon Dec 17 12:30:34 1990 James Clark (jjc at jclark)
+
+ * troff/column.c: New file.
+ * troff/Makefile: Corresponding changes.
+
+ * troff/hvunits.c (scale(vunits, vunits, vunits)): New function.
+ Friend of vunits.
+
+ * troff/div.c (top_level_diversion::space): If the space causes
+ the first-page transition and springs a trap, truncate the space
+ to 0.
+
+Fri Dec 14 12:30:02 1990 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::do_import): Add a `clear' after including
+ the document.
+
+ * pic/troff.c (troff_output::line_thickness,
+ troff_output::set_fill): Do a horizontal motion to compensate for
+ the width of the \D escape sequence.
+
+Thu Dec 13 10:17:14 1990 James Clark (jjc at jclark)
+
+ * xditview/tmac.X: Reinstate definition of \(rn, but only for X100
+ (not X75).
+
+ * eqn/sqrt.c (sqrt_box::compute_metrics): Supply missing argument
+ to printf.
+
+ * tbl/table.c (simple_entry::simply_print): Don't declare as pure.
+ Supply empty definition.
+ (text_entry::simple_print, simple_text_entry::simple_print):
+ Delete declarations.
+ (table::add_entry): Represent empty entries by objects of type
+ `simple_entry'.
+
+Wed Dec 12 08:50:48 1990 James Clark (jjc at jclark)
+
+ * troff/Makefile: Remove -DHYPHEN_CONTROL from DEFINES.
+
+ * tbl/table.c (left_text_entry::add_tab): New function.
+
+ * macros/tmac.s: Make @RT an alias for par@reset. Make RT
+ initialize like LP.
+
+Mon Dec 10 11:19:55 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (environment::start_field): Give an error message if
+ there is no next tab.
+
+Sun Dec 9 11:46:40 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (hyphenate): Skip initial elements with zero
+ hyphenation code.
+
+ * macros/tmac.s (par@init): Keep VS in points rather than units.
+
+Sat Dec 8 23:00:27 1990 James Clark (jjc at jclark)
+
+ * pic/main.c (main): Implement `-c' option.
+ * pic/output.h: Declare make_tpic_output().
+ * pic/tex.c (tex_output::set_pen_size): Make it virtual and
+ protected.
+ (tpic_output): New class.
+ (tpic_output::tpic_output, tpic_output::set_pen_size,
+ tpic_output::command, make_tpic_output): New functions.
+
+Fri Dec 7 11:57:41 1990 James Clark (jjc at jclark)
+
+ * tbl/main.c (main): Call `.ab' if \n(.g is false. Define TS/TE
+ if they're not already defined.
+ * tbl/table.c (init_output): Don't test \n(.g.
+
+ * troff/input.c (do_if_request): Delete `g' condition. Recognize
+ `d', `r' and `c' conditions even in compatibility mode.
+
+Tue Dec 4 09:13:47 1990 James Clark (jjc at jclark)
+
+ * ps/tmac.ps (ps-bb): Protect against negative numbers in bounding
+ box.
+
+Mon Dec 3 07:18:26 1990 James Clark (jjc at jclark)
+
+ * troff/env.h (environment::prev_line_interrupted): New member.
+ (environment::get_prev_line_interrupted): New function.
+ * troff/env.c (environment::newline): Set prev_line_interrupted.
+ (environment::environment(const environment *),
+ environment::environment(symbol)): Initialize
+ prev_line_interrupted.
+ * troff/input.c (process_input_stack): Don't give special
+ treatment to space and newline at the beginning of the line if the
+ previous line was interrupted.
+
+Sat Dec 1 15:48:37 1990 James Clark (jjc at jclark)
+
+ * eqn/eqn.y: Disallow PRIME by itself.
+ * eqn/lex.c (token_table): Bind `opprime' instead of `prime' to
+ PRIME.
+ (def_table): Remove definition of '. Define prime to be `.
+
+ * eqn/eqn.y: Split off part of rule `script' into a new rule
+ `nonsup'.
+
+Fri Nov 30 10:23:44 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s ({, }): New string aliases.
+
+Thu Nov 29 11:34:40 1990 James Clark (jjc at jclark)
+
+ * README-0.7: New file.
+
+Wed Nov 28 10:09:57 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s: New file.
+ * man/groff_ms.man: New file.
+ * Makefile: Add definition of TMAC_S. Pass TMAC_S in SUBFLAGS.
+ * Makefile.bd: Similarily.
+ * man/Makefile: Add groff_ms.n to MAN7PAGES. Replace @TMAC_S@. Add
+ definition of TMAC_S.
+ * macros/Makefile: Add definition of TMAC_S. Install tmac.s.
+ * macros/TODO: New file.
+
+Sat Nov 24 20:04:54 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (right_justify): New function.
+ (init_env_requests): Bind this to request "rj".
+ (center_lines): Set right_justify_lines to 0. If we get a bad
+ integer, center 1 line.
+ (environment::environment(symbol), environment::environment(const
+ environment *)): Initialize right_justify_lines.
+ (environment::get_right_justify_lines): New function.
+ (init_env_requests): Bind this to number_register ".rj".
+
+ * troff/env.c (environment::choose_breakpoint): Implement
+ hyphenation_margin and hyphenation_space.
+ (environment::get_hyphenation_space,
+ environment::get_hyphenation_margin): New functions.
+ (init_env_requests): Bind these to .hys and .hym.
+ (hyphenation_space_request, hyphenation_margin_request): New
+ functions
+ (init_env_requests): Bind these to hys and hym.
+ (environment::environment(symbol), environment::environment(const
+ environment *)): Initialize hyphenation_margin and
+ hyphenation_space.
+ * troff/env.h: Corresponding changes to class environment.
+
+Fri Nov 23 09:08:16 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (blank_line): Always do a break.
+
+ * eqn/box.c (do_text): Turn off escapes while appending text to
+ string.
+
+Thu Nov 22 10:58:59 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (while_break_request, while_continue_request): New
+ functions.
+ (init_input_requests): Bind these to "break" and "continue".
+ (while_depth, while_break_flag): New variables.
+ (while_request): Update while_depth. Break out of loop if
+ while_break_flag is set.
+
+Wed Nov 21 10:54:40 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (init_span_reg): Initialize span_width_reg to \n(.H
+ rather than 0.
+
+Mon Nov 19 00:45:03 1990 James Clark (jjc at jclark)
+
+ * Makefile: Include -DBROKEN_SPOOLER by default. Expand comment.
+
+ * stringify: New file.
+ * Makefile (groff.o): Use stringify.
+
+ * xditview/tmac.X: Remove definition of \(rn.
+ * xditview/libXdvi/DviChar.c: Remove radicalex from
+ Adobe_symbol_map.
+
+Sat Nov 17 10:44:58 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::add_entry): Allow alphabetic text blocks.
+ (alphabetic_block_entry::alphabetic_block_entry,
+ alphabetic_block_entry::divert, alphabetic_block_entry::print):
+ New functions.
+ (block_entry::divert): Split off body into ...
+ (block_entry::do_divert): If the block is alphabetic, subtract 2n
+ from the line length; also update the span width to dl+2n, and the
+ alphabetic span width to dl.
+
+ * driver/input.c (do_file): While reading argument to D command,
+ when expanding buffer, multiply szp by sizeof(int) rather than 2
+ in the argument to memcpy.
+
+ * tbl/table.c (compute_span_width): Add 2n rather than 1n to the
+ width of alphabetic columns.
+
+Fri Nov 16 06:34:27 1990 James Clark (jjc at jclark)
+
+ * troff/node.c (lookup_family): Supply second argument to lookup.
+
+ * troff/dictionary.c (dictionary::lookup): After an unsuccesful
+ search, return immediately if v is 0.
+
+ * pic/troff.c: Define EQN_NO_EXTRA_SPACE_REG.
+ (troff_output::start_picture): Set this reg.
+ (troff_output::end_picture): Remove this reg
+ * eqn/box.c (box::extra_space): Don't produce `\x's if
+ EQN_NO_EXTRA_SPACE_REG is defined.
+
+ * eqn/eqn.y: Allow just a PRIME to be a `simple'.
+ * eqn/text.c (split_text): Map ' to \(fm when it's the first
+ character.
+
+Thu Nov 15 10:35:06 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.e: Use font 3 instead of B in $c. Remove `bd'
+ requests.
+
+ * troff/div.c (top_level_diversion::top_level_diversion):
+ Initialize page_number to 0.
+
+Wed Nov 14 21:41:58 1990 James Clark (jjc at jclark)
+
+ * groff/troff (environment::environment(const environment *)):
+ Initialize name to e->name, rather than "anonymous".
+
+Sat Nov 10 01:59:37 1990 James Clark (jjc at jclark)
+
+ * xditview/libXdvi/Dvi.c (ShowDvi): If eof is encountered, reset
+ requested_page. Split middle part into ...
+ (FindPage): New function.
+ (SetValues): If we don't yet know the last page, and the requested
+ page is greater than the current page, call FindPage.
+ Update the font_map_string before doing this.
+
+ * xditview/tmac.X: Add definitions of \(sq, \(ga, \(dg and \(dd.
+ Translate \(lh and \(rh into left and right double arrows.
+
+ * troff/node.c (class hyphen_inhibitor_node): New class.
+ (hyphen_inhibitor_node::hyphen_inhibitor_node,
+ hyphen_inhibitor_node::copy, hyphen_inhibitor_node::same,
+ hyphen_inhibitor_node::type,
+ hyphen_inhibitor_node::get_hyphenation_type): New functions.
+ (node::add_discretionary_hyphen): Use hyphen_inhibitor_node rather
+ than dbreak_node(0, 0) to represent a `\%' at the beginning of a
+ word.
+
+Fri Nov 9 16:05:38 1990 James Clark (jjc at jclark)
+
+ * troff/node.h (dummy_node::get_hyphenation_type,
+ transparent_dummy_node::get_hyphenation_type): Declare them.
+ * troff/node.c: (dummy_node::get_hyphenation_type,
+ transparent_dummy_node::get_hyphenation_type): New functions.
+
+Wed Nov 7 10:09:06 1990 James Clark (jjc at jclark)
+
+ * xditview/libXdvi/draw.c: If M_PI not defined after including
+ math.h, then define it.
+
+ * xditview/Makefile: Add definition of AR. Pass it to the submake
+ in libXdvi.
+ * xditview/libXdvi/Makefile: Add definitions of AR and RANLIB.
+
+Tue Nov 6 10:14:27 1990 James Clark (jjc at jclark)
+
+ * troff/dictionary.h (object_dictionary::alias): Declare return
+ value as int.
+ * troff/dictionary.c (object_dictionary::alias): Return non-zero
+ if the old name was defined.
+ * troff/input.c (alias_macro): Give a warning if the old name was
+ not defined.
+ * troff/reg.c (alias_reg): Likewise.
+
+Mon Nov 5 00:31:39 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Delete implementation of \R.
+
+ * macros/Makefile: Strip comments from tmac.e while installing it.
+
+ * troff/input.c: New variable `nroff_mode'.
+ (troff_request, nroff_request): New functions.
+ (init_input_requests): Bind `troff' and `nroff' to troff_request
+ and nroff_request.
+ (do_if_request): Compute results of t and n conditions from
+ nroff_mode.
+
+ * text/text.c (split_text): Fix typo in >=.
+
+ * eqn/lex.c: Add definition of `==' to def_table.
+
+Fri Nov 2 02:49:09 1990 James Clark (jjc at jclark)
+
+ * pic/tex.c (tex_output::start_picture): Change the definitions of
+ \graph and \graphtemp so that they work properly with Plain TeX.
+
+ * pic/tex.c (tex_output::solid_arc): Ensure that the second angle
+ argument to `ar' is not less than the first.
+
+ * pic/pic.y: Allow a comma between elements of the variable list
+ in the argument to `reset'.
+
+ * pic/object.c (arc_object::arc_object): Fix computation of
+ radius.
+
+ * eqn/main.c (main): Add exit(0).
+
+Thu Nov 1 02:03:50 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (begin_page): Test no_space_mode after doing the
+ break, but still push the page ejector cookie before doing the
+ break. Also set the next page number after doing the break.
+
+ * xditview/xditview.c (NewFile): Don't set the title and icon name
+ if this is the first file and its name is `-'.
+ * groff/groff.c: Define a new device flag XT_OPTION. Set it for
+ the X75 and X100 devices.
+ (main): If a device has the XT_OPTION flag set and there's exactly
+ one file argument, pass the driver -xrm and -title options to set
+ the icon name and window title to the name of the file.
+
+ * troff/env.c (environment_switch): If there was an argument but
+ it wasn't a valid number or name, then pop an environment but
+ don't give an error message on underflow.
+
+ * troff/number.c (start_number): Correct spelling in error message.
+
+ * troff/input.c (token::delimiter): Don't print an error message
+ if err is false.
+
+ * xditview/libXdvi/parse.c (ParseInput): In case 'D', only call
+ ParseDrawFunction if dw->display_enable is true.
+
+Wed Oct 31 05:49:50 1990 James Clark (jjc at jclark)
+
+ * pic/pic.y: Parse text positioning like normal attributes, so as
+ to allow `"text" at 0,0 ljust'. Don't allow `center' as a
+ positioning attribute.
+
+Mon Oct 29 22:50:38 1990 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_data): When in state START while reading a
+ text block, don't change to state MIDDLE if c is a newline.
+
+Sun Oct 28 21:59:56 1990 James Clark (jjc at jclark)
+
+ * dvi/dvi.c (dvi_printer::begin_page): Rename `i' variable to `j'
+ so as to avoid shadowing parameter.
+
+Wed Oct 24 18:35:39 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (trim_space): Deleted.
+ (table::add_entry): Don't call trim_space.
+
+Mon Oct 22 03:48:39 1990 James Clark (jjc at jclark)
+
+ * VERSION: Change version to 0.6.
+
+ * troff/number.c (parse_expr): Make == work.
+
+Sat Oct 20 11:28:17 1990 James Clark (jjc at jclark)
+
+ * man/grog.man: New file.
+ * man/Makefile: Add grog.n to MAN1PAGES.
+ * etc/grog.sh: New file.
+ * etc/Makefile: Install grog.sh as grog.
+
+Fri Oct 19 11:17:15 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Implement \E.
+
+Thu Oct 18 11:56:24 1990 James Clark (jjc at jclark)
+
+ * xditview/tmac.X: Change font translations to match tmac.ps.
+
+ * troff/input.c (non_empty_name_warning): Don't give a warning if
+ `\{' terminates the name.
+
+Tue Oct 16 10:04:23 1990 James Clark (jjc at jclark)
+
+ * ps/devps/symbol.diff: New file.
+ * ps/devps/FontMakefile: Mention symbol.diff.
+
+Sun Oct 14 11:46:46 1990 James Clark (jjc at jclark)
+
+ * troff/node.c (font_position): Use get_long_name to read the
+ external_name.
+
+ * troff/env.c (environment_switch): If we get a number that's < 0
+ or >= NENVIRONMENTS, treat it like a name.
+ Change NENVIRONMENTS to 10.
+
+ * troff/groff.h: Remove definition of FONTS_MAX.
+ * troff/node.h (class font_family): Make map a pointer instead of
+ an array. Add a map_size member. Make it a class. Make nm const
+ and public. Make invalidate_fontno a friend.
+ * troff/node.c: Define font_table_size. Make font_info a pointer
+ rather than an array.
+ (class troff_output_file): Allocate font_position dynamically. Add
+ nfont_positions member.
+ (troff_output_file::set_font): Grow font_position if necessary.
+ (troff_output_file::~troff_output_file): Delete font_position.
+ (troff_output_file::troff_output_file): Allocate font_position.
+ (grow_font_table): New function.
+ (troff_output_file::really_begin_page,
+ troff_output_file:really_copy_page): Use nfont_positions rather
+ than FONTS_MAX.
+ (mount_font_no_translate, mount_style): Call grow_font_table if
+ necessary.
+ (font_family::font_family): Allocate map.
+ (font_family::make_definite): Grow map if necessary. Use
+ font_table_size instead of FONTS_MAX.
+ (font_family::~font_family): New function.
+ (invalidate_fontno): Use font_family::map_size.
+ (get_fontno, env_space_width, env_half_narrow_space_width,
+ env_narrow_space_width, symbol_fotno, is_good_fontno,
+ get_bold_fontno, make_glyph_node): Use font_table_size rather than
+ FONTS_MAX.
+ (next_available_font_position): Never return 0.
+
+Fri Oct 12 10:17:52 1990 James Clark (jjc at jclark)
+
+ * ps/tmac.ps: Add font translations for compatibility with dpost.
+
+Thu Oct 11 12:09:03 1990 James Clark (jjc at jclark)
+
+ * eqn/pile.c: Rename default_baseline_sep to baseline_sep.
+ Move BASELINE_SEP_FORMAT and COLUMN_WIDTH_FORMAT into pbox.h.
+ Move definitions baseline_sep, shift_down, column_sep,
+ matrix_side_sep into...
+ * eqn/box.c: Add them to param_table.
+ * eqn/pbox.h: Add declarations to pbox.h.
+
+ * troff/input.c (set_string): Cast value to unsigned char *.
+
+ * troff/token.h (process_input_stack): Declare it static before
+ declaring it a friend.
+
+Wed Oct 10 09:59:13 1990 James Clark (jjc at jclark)
+
+ * dvi/devdvi/texex.map: Fix positions of extensible brace middle
+ and bottom.
+ * dvi/devdvi/EX: Regenerate.
+
+ * troff/input.c (init_charset_table): Make ", ', ), ], *, \(dg
+ transparent.
+
+Tue Oct 9 08:34:02 1990 James Clark (jjc at jclark)
+
+ * eqn/lex.c: In defaults_table, make definition of `dot' call
+ `dot_def'. Don't explicitly make it roman. Similarily for other
+ accents.
+
+ * pic/lex.c (for_input::for_input): Add by_is_multiplicative
+ argument.
+ (for_input::get, for_input::peek): Use this.
+ (do_for): Add by_is_multiplicative argument.
+ * pic/pic.y: Change optional_by clause to allow '*' after `by'.
+ Change semantic value of optional_by to be a double plus a flag
+ saying whethet the by clause is multiplicative.
+
+ * eqn/lex.c (get_delimited_text): Remember location of start of
+ definition. Improve error handling when EOF is encountered.
+
+ * lib/font.h: Rename handle_x_command to
+ handle_unknown_font_command.
+ * lib/font.c (font::load): Call handle_unknown_font_command for
+ any unknown command in the font description file. Don't call
+ handle_x_command. Include the name of the command in the argv.
+ Improve message for unknown command after kernpairs or charset
+ command.
+ * ps/ps.c (ps_font::handle_x_command): Rename to
+ handle_unknown_font_command. Remove message about `x download'
+ command. Give error message for wrong number of arguments.
+ * ps/devps/afmtodit: Generate `encoding' instead of `x encoding'.
+ * dvi/dvi.c (dvi_font::handle_x_command): Rename to
+ handle_unknown_font_command. Give an error message for wrong
+ number of arguments. Rename design_size to designsize.
+ * dvi/tfmtodit.c (main): Generate `checksum' instead of `x
+ checksum', `designsize' instead of `design_size'.
+
+Mon Oct 8 00:38:55 1990 James Clark (jjc at jclark)
+
+ * eqn/*.[chy]: Change underaccent to uaccent.
+
+ * eqn/eqn.y: Add rule for underaccent. Declare UNDERACCENT token;
+ give it the same precedence as ACCENT.
+ * eqn/other.c (make_underaccent_box): New function.
+ * eqn/box.h: Declare it.
+ * eqn/lex.c: Add UNDERACCENT to token_table. Add utilde to
+ def_table.
+
+Sun Oct 7 11:25:16 1990 James Clark (jjc at jclark)
+
+ * pic/pic.y (reset_all): New function. Called in rule for RESET.
+ (parse_init): Call reset_all.
+ (define_variable): When defining scale reset only those
+ pre-defined variables that are scaled.
+ (defaults_table): Add `scale' as non-scaled value.
+
+ * pic/pic.y: Redo parsing of text adjustments: parse adjustments
+ together with the text; allow any number of positioning words;
+ allow center as a positioning word.
+
+ * pic/object.c (output::compute_scale): Get picture maximum height
+ and width from variables called maxpswid and maxpsht.
+ * pic/pic.y: Add maxpswid and maxpsht to defaults_table.
+
+Sat Oct 6 10:16:56 1990 James Clark (jjc at jclark)
+
+ * pic/object.c (object_spec::make_text): Multiply textht by number
+ of text items.
+
+ * pic/pic.y: Allow `sprintf("string", expr,...)' wherever text can
+ occur.
+ (do_sprintf): New function.
+ (pic.gperf): Add sprintf token.
+ (text, sprintf): New rules.
+
+ * pic/pic.y: `rand()' with no arguments returns a random number
+ in the range [0,1).
+
+ * pic/pic.y: Allow a bare expression to be an attribute: change
+ precedences to support this. Change optional_ordinal rule to
+ optional_ordinal_last to avoid reduce/reduce conflict.
+ * pic/object.c (object_spec::object_spec): Initialize direction.
+
+ * pic/pic.y: Implement ^ operator meaning exponentiation.
+
+ * troff/node.h: Add default argument to mount_font.
+ * troff/node.c (font_position): Read an optional third argument
+ giving the external_name.
+ (mount_font): Add optional argument giving the external_name.
+ (mount_font_not_translate): Have additional argument giving
+ external name. Use this name to load the font. Pass both names
+ to font_info::font_info.
+ (font_info::font_info): Have additional argument giving
+ external_name.
+ (class tfont): New member external_name.
+ (font_info::get_tfont): Use external name to construct tfont_spec.
+
+Fri Oct 5 04:03:13 1990 James Clark (jjc at jclark)
+
+ * eqn/lex.c (init_table): Add argument giving device. Define
+ name of device to be "1".
+ (do_ifdef): Counts as true if the argument has been defined with
+ `define'.
+ * eqn/main.c (main): Call init_table with device argument. Make
+ device local to main.
+ * eqn/eqn.h: Change declaration of init_table. Remove declaration
+ of device.
+
+ * pic/lex.c (get_delimited): Allow text to be delimited by
+ matching {}s. Don't recognize ending delimiter within a string.
+
+ * troff/input.c (get_delim_name): New function.
+ (token::next): Implement \C.
+
+ * lib/font.c (font::load): Grok ---. Add an alias for each
+ character based on its code.
+ (font::get_code_width): Deleted.
+ * lib/font.h (class font): Declare font::number_to_index().
+ Remove declaration of font::get_code_width.
+ * lib/nametoindex.c (font::name_to_index): Add 512 rather than 256
+ to indices of named characters.
+ (font::number_to_index): New function.
+ * troff/input.c (font::number_to_index): New function.
+ (get_charinfo_by_number, charinfo::get_number,
+ charinfo::set_number): New functions.
+ (token::next): Turn \N into a TOKEN_NUMBERED_CHAR.
+ (token::process, token::description, token::get_char,
+ token::add_to_node_list, token::operator==): Handle
+ TOKEN_NUMBERED_CHAR.
+ * troff/charinfo.h: Declare get_charinfo_by_number,
+ charinfo::get_number, charinfo::set_number. Add NUMBERED flag to
+ charinfo class.
+ (charinfo::numbered): New function.
+ * troff/token.h: Add TOKEN_NUMBERED_CHAR.
+ * troff/env.h (class environment): Remove declaration of ...
+ * troff/env.c (environment::make_numbered_char_node): Deleted.
+ * troff/node.c (make_numbered_node): Deleted.
+ (class numbered_glyph_node): Remove.
+ (troff_output_file::put_char_width, troff_output_file::put_char):
+ Handle numbered chars.
+ (troff_output_file::numbered_char): Removed.
+ (tfont::get_code_width): Removed.
+ (make_glyph_node): Don't search special fonts for numbered
+ characters.
+ * troff/node.h: Remove declaration of make_numbered_node.
+ * driver/input.c (do_file): Handle N command.
+ * driver/printer.h: Add declaration of ...
+ * driver/printer.c (printer::set_numbered_char): New function.
+ * dvi/tfmtodit.c (main): Generate unnamed entries.
+ * ps/devps/afmtodit: Likewise.
+ * xditview/xtotroff.c (MapFont): Likewise.
+ * xditview/libXdvi/parse.c (ParseInput): Grok N command.
+
+ * tbl/main.c (process_format): If multiple widths are specified
+ for a column but all the widths are the same, don't give an error
+ message.
+
+ * tbl/table.c (table::do_row): If the current row is all lines and
+ the stuff doesn't contains a line, mark the top of the row after
+ printing stuff before the row. If the current row is not all
+ lines and the stuff doesn't contain a line, don't unnecessarily
+ mark the top of the row before printing the stuff.
+
+Mon Oct 1 11:42:00 1990 James Clark (jjc at jclark)
+
+ * troff/groff.h: Remove MAX_PATH.
+ * troff/input.c (open_file): Dynamically allocate space for the
+ path.
+ (open_mac_file, process_macro_file): Corresponding changes.
+
+Sun Sep 23 18:56:26 1990 James Clark (jjc at jclark)
+
+ * troff/node.h (class output_file): Make copy_file pure. Add
+ vspace method ifdef COLUMN. Add is_printing method.
+ * troff/node.c: Add class printing_reg. Add class
+ real_output_file. Derive other output_file classes from
+ real_output_file; in these classes rename begin_page to
+ really_begin_page, print_line to really_print_line, copy_file to
+ really_copy_file, transparent_char to really_transparent_char.
+ Move output_file::flush to real_output_file. Add printing member
+ to class output_file.
+ * troff/div.h: Remove printing member from top_level_diversion.
+ Add vspace member function to class diversion ifdef COLUMN. Add
+ some declarations ifdef COLUMN.
+ * troff/div.c (top_level_diversion::copy_file,
+ top_level_diversion::transparent_output,
+ top_level_diversion::output): Don't test printing member before
+ output.
+ * troff/input.c: Handle initial variable_space_request ifdef
+ COLUMN.
+ * troff/Makefile: Add column.c but comment it out. Add -DCOLUMN
+ but comment it out.
+
+Sat Sep 22 11:32:22 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (diversion::need): Make any space forced. If we
+ sprung a trap, set truncated_space to minus the distance to the
+ trap and set needed_space to the amount that was needed.
+ (top_level_diversion::space): A forced space turns no_space_mode
+ off.
+ (class constant_vunits_reg): New class.
+ (init_div_requests): Implement number registers .trunc and .ne
+ using constant_vunits_reg.
+ (class truncated_space_reg): Deleted.
+
+ * troff/div.h: Don't have a no_space_mode member in diversion.
+ Instead have it in top_level_diversion.
+ * troff/div.c (diversion::diversion): Don't initialize
+ no_space_mode.
+ (top_level_diversion::top_level_diversion): Initialize
+ no_space_mode.
+ (no_space, restore_spacing): Do nothing if curdiv != topdiv.
+ (macro_diversion::output): Don't clear no_space_mode.
+
+ * troff/input.c (diverted_space_node::reread): Don't call
+ environment::do_break. In fill mode, act like a blank line.
+ (diverted_copy_file_node::reread): Don't call
+ environment::do_break.
+
+ * troff/div.c (blank_line): New function.
+ * troff/div.h: Declare it.
+ * troff/input.c (process_input_stack): Call it.
+
+ * troff/div.c (truncated_space_reg::get_string): New function.
+ (init_div_requests): Bind to .trunc.
+ (space_request, top_level_diversion::space,
+ top_level_diversion::output, macro_diversion::space,
+ macro_diversion::output): Update truncated_space.
+ (macro_diversion::output): Redo calculations when trap sprung.
+ (macro_diversion::output, macro_diversion::space): No need for
+ trap_flag.
+
+ * troff/div.c (top_level_diversion::output): Set nl_reg_contents
+ after truncating post line spacing.
+
+Fri Sep 21 11:27:25 1990 James Clark (jjc at jclark)
+
+ * ps/devps/prologue (MF, SF): Make them work even if setfont is
+ defined as a procedure rather than as an operator.
+
+Thu Sep 20 12:55:05 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (macro_diversion::space): Ignore no_space_mode.
+
+Wed Sep 19 10:54:37 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::output): Merge
+ output_file::print_line and output_file::end_of_line member
+ functions.
+ * troff/div.h (class output_file):
+ * troff/node.c (troff_output_file::print_line,
+ troff_output_file::end_of_line, output_file::end_of_line,
+ ascii_output_file::print_line, suppress_output_file::print_line):
+ Corresponding changes.
+
+Tue Sep 18 11:31:47 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Don't give a warning for `\.'.
+
+ * troff/env.c (environment::get_center_lines): New function.
+ (init_env_requests): Bind number register .ce to it.
+ * troff/env.h: Declare it.
+ * tbl/table.c (table::init_output): Define reset macro to restore
+ .ce. If center option not given, store .ce in SAVED_CENTER_REG.
+ Then do .ce 0.
+ (table::print): If center option not given, then imply center
+ option if SAVED_CENTER_REG > 0.
+
+Mon Sep 17 09:19:19 1990 James Clark (jjc at jclark)
+
+ * ps/devps/Makefile: Remove T from FONTS. Remove TSymbol.ps and
+ Troff.ps from DOWNLOAD.
+
+ * troff/Makefile: Change comment in DEFINES to avoid confusing
+ System V make.
+
+ * ps/ps.c (ps_printer::do_exec): Allow newlines within PostScript
+ code. Don't try to catch errors with stopped.
+ (check_line_lengths): New function.
+ * ps/devps/prologue (EXEC): Deleted.
+ (EBEGIN, EEND): New procedures.
+
+Sun Sep 16 14:51:15 1990 James Clark (jjc at jclark)
+
+ * troff/input.c: Include request.h before node.h.
+ * troff/node.c: Likewise.
+ * troff/env.c: Likewise.
+ * troff/div.c: Likewise.
+ * troff/node.h (class special_node): Store argument as a macro
+ rather than a char *.
+ * troff/node.c (special_node::special_node, special_node::copy):
+ Grok this.
+ (special_node::~special_node): Deleted.
+ (special_node::tprint): Deleted.
+ (special_node::tprint_start, special_node::tprint_end,
+ special_node::tprint_char): New functions.
+ (troff_output_file::special): Deleted.
+ (troff_output_file::start_special, troff_output_file::end_special,
+ troff_output_file::special_char): New functions.
+ * troff/input.c (special_node::tprint): New function.
+ (do_special): Use macro not char *.
+ (do_transparent_macro): Deleted.
+ (token::next): Don't call do_transparent_macro.
+
+ * troff/input.c (token::next): Add 'Y' case.
+ (do_transparent_macro): New function.
+ * troff/node.c (troff_output_file::special): Handle newlines with
+ argument using new continuation convention.
+ * driver/input.c (get_string): Cope with continuation convention.
+ (do_file): Don't call skip_line after calling get_string(1).
+ * ps/ps.c (ps_printer::special, ps_printer::do_import,
+ ps_printer::do_def, ps_printer::do_exec): Cope with newlines in
+ arg.
+ * xditview/libXdvi/parse.c (ParseInput): Ignore lines starting
+ with +.
+
+Sat Sep 15 19:00:10 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (asciify): By default, illegal input characters
+ should return empty string.
+
+ * troff/input.c (copy_file): Handle first page transition like title.
+ (token::next, process_input_stack): Grok COPY_FILE_REQUEST.
+
+ * troff/input.c (token::next): Improve error message for EOF after
+ escape character.
+ (input_char_description): New function.
+ (get_char_for_escape_name): Use input_char_description.
+ (token::next): Warn about unrecognized escape sequences.
+ (warning_table): Add WARN_ESCAPE.
+ * troff/groff.h: Declare WARN_ESCAPE. Change WARN_TOTAL
+ accordingly.
+
+ * troff/token.h: Remove declaration of process_input_stack.
+
+ * troff/input.c: Remove declaration of init_hyphen_requests.
+ * troff/request.h: Correct spelling in declaration of same.
+
+ * troff/input.c (token::next): Check whether escape_char is 0.
+
+Fri Sep 14 12:09:25 1990 James Clark (jjc at jclark)
+
+ * groff.c (main, usage, help): Implement -P and -L options.
+ * groff.sh: Likewise.
+
+ * troff/input.c (token::next): Use some gotos to avoid code
+ duplication.
+
+ * troff/input.c (get_long_name, get_name, read_long_ecsape_name):
+ Avoid calling symbol::symbol if name empty.
+
+Thu Sep 13 06:21:45 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (init_input_requests): Make \n(.x return the major
+ version number and \n(.y return the minor version number.
+ * troff/Makefile: Construct file majorminor.c defining
+ major_version and minor_version automatically from ../VERSION.
+
+ * troff/node.c (class glyph_node): Make operator new and operator
+ delete public.
+ (class ligature_node): Similarily.
+
+ * troff/input.c (operator==(const macro &, const macro &)): New
+ function.
+ (non_interpreted_node::same): Use this.
+ (string_iterator::string_iterator): Make macro& argument const.
+
+ * troff/input.c (input_iterator::get): New function. Don't make
+ asciify_macro or class non_interpreted_node friends of class
+ input_iterator.
+ (non_interpreted_node::interpret): Use input_iterator::get.
+ (asciify_macro): Likewise.
+
+ * troff/input.c (~token_node, ~string_iterator, ~arg_list,
+ ~non_interpreted_node): Deleted.
+ * troff/node.c: (~suppress_output_file, ~ascii_output_file):
+ Deleted.
+
+ * troff/symbol.h: Make all symbol member functions const.
+
+ * lib/strtol.c: New file.
+ * lib/Makefile: Add strtol.c.
+ * Makefile: Define STRTOL as strtol.o to include strtol in
+ libgroff.a.
+
+Wed Sep 12 10:00:49 1990 James Clark (jjc at jclark)
+
+ * pic/troff.c (troff_output::simple_circle): Divide by scale.
+
+Tue Sep 11 14:17:16 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (do_special): Use input_level.
+
+ * troff/token.h (TOKEN_BACKSPACE): New token.
+ (token::backspace): New function.
+ * troff/input.c (token::description, token::next, token::process):
+ Grok TOKEN_BACKSPACE.
+ (do_special): Turn TOKEN_BACKSPACE back into \b.
+
+ * troff/token.h (token::leader): New function.
+ * troff/input.c (do_special): Turn TOKEN_LEADER back into \001.
+
+ * troff/input.c (do_special): Turn TOKEN_TAB back into \t.
+
+ * troff/input.c (do_special): Use token::description in error
+ message.
+
+Mon Sep 10 11:06:27 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (decode_args): Combine quoted and
+ quote_input_level variables. Make it a for (;;) loop.
+
+ * troff/input.c (get_char_for_escape_name): Check for \001 and \b.
+
+ * troff/input.c (read_long_escape_name): The test for whether to
+ expand buffer was off by 1.
+ (read_string): Similarily.
+
+Fri Sep 7 11:45:50 1990 James Clark (jjc at jclark)
+
+ * troff/input.c: Use `const int' rather than `static const int'.
+
+ * troff/div.h (diversion::copy_file): Declare as pure virtual.
+ (macro_diversion::copy_file): New function.
+ * troff/node.h: New class diverted_copy_file_node.
+ * troff/node.c: Implement it.
+ * troff/input.c (copy_file): Use diversion::copy_file. Handle
+ first page transition by pushing a diverted_copy_file_node.
+ * troff/input.c (token::next, process_input_stack): Don't handle
+ COPY_FILE_REQUEST.
+
+Thu Sep 6 13:29:10 1990 James Clark (jjc at jclark)
+
+ * ps/ps.c (flush_sbuf): Remember to add sbuf_kern when checking
+ whether space widths need adjusting.
+
+ * troff/charinfo.h: Generalize translated_to_space to
+ special_translation so as to allow translation to \&.
+ * troff/input.c (translate): Allow translation to \&.
+ (charinfo::*): Corresponding changes.
+ * troff/node.c (make_node, node::add_char): Corresponding changes.
+ * troff/node.h (dummy_node::dummy_node): Allow optional first
+ argument.
+
+ * lib/lib.h: Make codes 0200 to 0237 illegal input characters.
+ * troff/token.h: Remove TOKEN_TITLE. Remove token::title. Add
+ TOKEN_REQUEST.
+ * troff/input.c (token::next): Turn a TITLE_REQUEST into a
+ TOKEN_REQUEST with an argument of TITLE_REQUEST.
+ (token::process): Grok that.
+ * troff/input.c (copy_file): Handle first page transition like
+ title by pushing a COPY_FILE_REQUEST cookie.
+ (token::next, process_input_stack): Grok that.
+ * troff/node.h (output_file::copy_file): Add x and y arguments.
+ Make it non-pure.
+ * troff/div.c (top_level_diversion::copy_file): Supply them.
+ * troff/node.c (troff_output_file::copy_file): Add x and y
+ arguments; moveto specified position. Invalidate font_position
+ array after copying file.
+ (output_file::copy_file): New function.
+ (suppressed_output_file::copy_file, ascii_output::copy_file):
+ Removed.
+ * troff/input.c (transparent_file): New function.
+ (init_input_requests): Bind to "trf".
+ (token::next): Handle TRANSPARENT_FILE_REQUEST cookie.
+ (process_input_stack): Likewise.
+
+ * troff/Makefile: Add ../lib/lib.h to GROFF_H.
+
+ * troff/node.c (init_node_requests): New number registers .kern
+ pointing to global_kern_mode, and .lg pointing to
+ global_ligature_mode.
+
+ * troff/node.c (ligature): Don't change it if we get a bad
+ integer.
+
+ * troff/input.c (do_define_string): Don't strip tabs.
+
+ * troff/input.c (asciify_macro): Make the string_iterator auto.
+
+ * troff/node.c (init_font_requests): Rename to...
+ (init_node_requests):
+ * troff/node.h: Change declaration.
+ * troff/input.c (main): Change call.
+
+ * troff/input.c (node::reread, diverted_space_node::reread): New
+ methods.
+ (process_input_stack): Call reread rather than
+ get_diverted_space_node.
+ * troff/node.c (node::get_diverted_space_node,
+ diverted_space_node::get_diverted_space_node): Removed.
+ * troff/node.h: Declare reread methods instead of
+ get_diverted_space_node methods. Make `n' member private.
+ * troff/input.c: (token::diverted_space): Removed.
+ * troff/token.h: Removed declaration.
+
+
+Tue Sep 4 00:48:04 1990 James Clark (jjc at jclark)
+
+ * eqn/script.c (script_box::compute_metrics): Don't let
+ SUP_RAISE_FORMAT become negative.
+
+ * tbl/table.c (table::do_row): Entries that don't end in the
+ this row shouldn't make the row non-blank.
+
+ * tbl/table.c (table::make_columns_equal): Only set the width of
+ columns which are marked as equal.
+
+ * tbl/main.c (process_data): Before issuing excess data error,
+ if last character was a newline unget it; then get it again after
+ the error. Also include the contents of the entry in the message.
+
+ * groff.c: New file.
+ * Makefile: Build groff from groff.c. Make it possible to use
+ either groff.sh or groff.c as groff.
+ * Makefile.bd: Similarily.
+
+Mon Sep 3 09:39:49 1990 James Clark (jjc at jclark)
+
+ * groff.sh: Don't delay expansion of $@ in assignment to files.
+ Remove occurrences of \".
+
+Sun Sep 2 09:56:59 1990 James Clark (jjc at jclark)
+
+ * all Makefiles: Simplify and rearrange.
+
+ * Makefile: Handle fmod like malloc.
+ * lib/Makefile: Similarily.
+ * lib/fmod.c: Remove #ifdef NEED_FMOD.
+
+ * Makefile: Rename OPTIMISE to OPTIMIZE.
+
+ * groff.sh: Remove assignment to PATH.
+ * Makefile: Remove SHPATH variable.
+ * Makefile.bd: Similarily.
+
+ * groff.sh: Add -V option to print the pipeline instead of
+ executing it.
+
+Fri Aug 31 00:56:46 1990 James Clark (jjc at jclark)
+
+ * lib/font.c: Split off file searching into ...
+ * lib/fontfile.c: New file.
+
+ * lib/strerror.c (strerror): Use `Error %d' for unknown errors.
+
+Thu Aug 30 13:13:55 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::do_hspan): Delete assertion that e != 0.
+ Also change misleading comment.
+ (table::do_vspan): Change similarily misleading comment.
+ * tbl/main.c (process_data): A format row with an explicit `s'
+ uses up a data line, even if all the other columns are `_' or `='.
+
+ * troff/input.c (token::description): Fix description of
+ TOKEN_DUMMY and TOKEN_EMPTY.
+
+Wed Aug 29 04:12:08 1990 James Clark (jjc at jclark)
+
+ * groff.sh: Fix description of -Z in help message.
+
+Tue Aug 28 07:28:33 1990 James Clark (jjc at jclark)
+
+ * pic/object.c (object_spec::make_object): Allow negative and zero
+ line thicknesses.
+ * pic/pic.y: Give linethick default value of -1.0.
+ * pic/troff.c (troff_output::troff_output): Initialize
+ last_line_thickness to BAD_THICKNESS.
+ (troff_output::finish_picture): Set thickness to BAD_THICKNESS.
+ (troff_output::line_thickness): Canonicalize negative thicknesses
+ to RELATIVE_THICKNESS.
+ * pic/tex.c (tex_output::set_pen_size): Silently map negative line
+ thicknesses to DEFAULT_PEN_SIZE. Canonicalize negative pen sizes
+ to -1.0.
+ (tex_output::start_picture): Set pen_size to -2.0.
+
+ * ps/ps.c (ps_printer::set_line_thickness): If line_thickness is
+ 0, then use 0 linewidth.
+ (ps_printer::ps_printer): Initialize line_thickness to -1.
+
+ * pic/troff.c (troff_output::simple_ellipse): Divide by scale.
+
+ * ps/devps/symbolchars: Remove `or'.
+ * ps/tmac.ps: Implement \(or with .char.
+
+ * ps/devps/symbolchars: Move most characters into textmap.
+ * ps/devps/textmap: Add names for troff bracket characters. Remove
+ ul, ru, br, bv.
+
+ * ps/devps/TSymbol.ps: Removed.
+ * ps/devps/FontMakefile: Make S from Symbol not TSymbol.
+ * ps/tmac.ps: Do with .char what TSymbol did.
+ * ps/devps/download: Remove TSymbol.
+
+ * ps/devps/T: Removed.
+ * ps/devps/Troff.ps: Removed.
+ * ps/devps/Troff.afm: Removed.
+ * ps/tmac.ps: Implement \(ru, \(ul, and \(br with .char.
+ * ps/devps/download: Remove Troff.
+ * ps/devps/FontMakefile: Remove T target.
+ * ps/devps/DESC-A4: Remove T from font list.
+ * ps/devps/DESC-letter: Likewise.
+
+ * troff/input.c (macro_to_node): Rename to ...
+ (charinfo_to_node): Don't pass mac argument. Temporarily remove the
+ character's definition while processing it.
+ * troff/node.c (node::add_char, make_node): Change calls to
+ macro_to_node accordingly.
+
+ * troff/input.c (token::next): Translate \_ to \(ul.
+
+ * tty/devascii/R.proto: Add `|'.
+ * tty/devlatin1/R.proto: Likewise.
+
+Mon Aug 27 11:25:41 1990 James Clark (jjc at jclark)
+
+ * man: Put the version number in all the man pages.
+
+Sun Aug 26 11:40:05 1990 James Clark (jjc at jclark)
+
+ * Makefile.bd: New file.
+ * README.bd: New file.
+
+ * VERSION: New file.
+ * lib/version.c: Removed.
+ * lib/Makefile: Create version.c from ../VERSION. Remove version.c
+ in clean target.
+
+ * troff/input.c (main): Get hyphen_file from GROFF_HYPHEN
+ environment variable.
+
+ * all Makefiles: Split install target into install.bin for
+ binaries, and install.nobin for everything else.
+ * Makefile: Add bindist target.
+
+ * man/afmtodit.man: New file.
+ * man/Makefile: Add afmtodit.n to MAN1PAGES.
+ * ps/devps/Makefile: Add textmap to DEVICEFILES. Install afmtodit
+ in BINDIR.
+ * ps/Makefile: Pass BINDIR to make install in devps.
+
+ * ps/ps.c (ps_printer::set_char): Do nothing if the character is
+ the space character.
+
+ * ps/devps/FontMakefile: Rename symbol.afm to tsymbol.afm.
+
+Sat Aug 25 15:39:03 1990 James Clark (jjc at jclark)
+
+ * ps/ps.c: Redo font downloading.
+ * ps/devps/download: New file.
+ * ps/devps/Makefile: Add download to DEVICEFILES.
+ * ps/devps/afmtodit: Remove -d option.
+ * ps/devps/FontMakefile: Don't use -d option with afmtodit.
+ * ps/devps/symbosl.ps: Add %%DocumentFonts comment.
+ * ps/devps/zapfdr.ps: Likewise.
+ * ps/devps/TSymbol.ps: Likewise.
+
+Fri Aug 24 20:10:30 1990 James Clark (jjc at jclark)
+
+ * groff.sh: Initialize dev to ${GROFF_TYPESETTER:-@DEVICE@}.
+
+Thu Aug 23 10:03:47 1990 James Clark (jjc at yquem)
+
+ * ps/ps.c (ps_output::include_file): If BROKEN_SPOOLER is defined,
+ then strip the first line if it starts with %.
+ * Makefile: Add a comment about this.
+
+ * man/tfmtodit.man: New file.
+ * man/Makefile: Add tfmtodit.n to MAN1PAGES.
+ * dvi/Makefile: Install tfmtodit in BINDIR.
+
+ * dvi/tfmtodit.c (usage): Mention -v option.
+
+Wed Aug 22 09:56:36 1990 James Clark (jjc at yquem)
+
+ * troff/node.c (troff_output_file::end_of_line): Call do_motion.
+ * troff/node.c (troff_output_file::transparent_char): Don't call
+ flush_tbuf.
+
+ * eqn: Add check_tabs method to most box classes.
+ * eqn/box.c (box::top_level): Call check_tabs.
+
+ * eqn/script.c (script_box::output): Use \Z.
+ * eqn/limit.c (limit_box::output): Use \Z.
+
+ * eqn/box.c (box::top_level): Use itoa.
+
+Tue Aug 21 09:29:28 1990 James Clark (jjc at yquem)
+
+ * dvi/tmac.dvi: Add font translations for CR, C, TT.
+ * dvi/devdvi/Makefile: Don't make links to CW.
+
+ * ps/tmac.ps: Add font translations for C, CW, CO, CX, CD, H, HO,
+ HX, HD.
+ * xditview/tmac.X: Likewise.
+
+ * troff/node.c: Add font translation feature.
+ (get_font_translation): New function.
+ (symbol_fontno): Translate the font name.
+ (mount_font_no_translate): Rename to mount_font to this.
+ (mount_font): New function.
+ (font_family::make_definite): Call mount_font_no_translate instead
+ of mount_font.
+ (mount_style): Translate the font name.
+ (font_translate): New function.
+ (init_font_requests): Bind "ftr" to font_translate.
+
+ * ps/devps/prologue (SN): New procedure that rounds a position to
+ the nearest (pixel + (.25,.25)).
+ (DL): Use SN to round endpoints.
+
+ * lib/version.c: Changed version to 0.5.
+
+Sat Aug 18 04:43:21 1990 James Clark (jjc at yquem)
+
+ * Makefile: Move definition of PAGE to the very beginning, so that
+ people are less likely to miss it.
+
+Fri Aug 17 02:15:11 1990 James Clark (jjc at yquem)
+
+ * man/Makefile: Don't need to sed out @UPCASE_PROG_PREFIX@.
+
+ * troff/env.c (environment::choose_breakpoint): Make `can't find
+ breakpoint' error a warning of type WARN_BREAK. Change message to
+ `can't break line'.
+ * troff/groff.h: Declare WARN_BREAK with code 4; change WARN_INPUT to
+ code 040000.
+ * troff/input.c: Add WARN_BREAK to warning_table. Include
+ WARN_BREAK in DEFAULT_WARNING_MASK.
+
+ * tty/tmac.tty: Add definition of \(+-.
+
+ * groff.sh: Remove `--' option to set command.
+
+ * dvi/devdvi/texsy.map: Remove duplicate md entry.
+
+ * ps/devps/eqnchar: Better definition of cdot using md.
+ * dvi/devdvi/eqnchar: Likewise.
+ * xditview/devX100/eqnchar: Likewise.
+ * xditview/devX75/eqnchar: Likewise.
+ * eqn/lex.c: Add definition of cdot.
+
+Thu Aug 16 09:33:57 1990 James Clark (jjc at yquem)
+
+ * troff/input.c (get_optional_char): New function.
+ * troff/input.c (set_page_character): Use get_optional_char(),
+ rather than has_arg() and tok.get_char(1).
+ * troff/env.c (tab_character, leader_character, hyphen_char,
+ field_characters): Likewise.
+ (margin_character): Likewise. Also always delete the
+ margin_character_node.
+
+ * troff/input.c (token::get_char): Use token::description.
+
+ * troff/input.c (has_arg): Don't skip over tab and \}.
+ * troff/number.c (start_number): Give a warning if the number
+ starts with \} (WARN_RIGHT_BRACE) or tab (WARN_TAB).
+
+Wed Aug 15 10:04:37 1990 James Clark (jjc at yquem)
+
+ * troff/input.c (empty_name_warning, non_empty_name_warning): New
+ functions.
+ (get_name, get_long_name): Use these. Rename `warn' argument to
+ `required'.
+
+ * troff/node.c (get_fontno): Test that the symbol is not null.
+
+ * troff/input.c (token::description): New function.
+ * troff/number.c (parse_term): Use token::description in `numeric
+ expression expected' message.
+ * troff/groff.h: Add WARN_MISSING.
+ * troff/number.c (start_number): New function.
+ * troff/number.c (get_vunits, get_hunits, get_number, get_integer,
+ get_incr_number): Use start_number().
+ * troff/input.c (DEFAULT_WARNING_MASK): Enable WARN_NUMBER by
+ default.
+ * troff/input.c (get_name, get_long_name): Use WARN_MISSING.
+ * troff/reg.c (alter_format): Use WARN_MISSING. Also use
+ token::descripion.
+ * troff/input.c (token::get_char): Use WARN_MISSING.
+ * troff/input.c (token::delimiter): Use token::description.
+ * troff/env.c (environment_switch): Back out Aug 3 change.
+ * troff/input.c (has_arg): Skip over \}s and tabs but give a
+ warning.
+ * troff/token.h (token::tab): New function.
+ * troff/node.c (get_fontno): Use tok.skip() rather than has_arg().
+ * troff/reg.c (alter_format): Likewise.
+ * troff/node.c (bold_font): Use has_arg() rather than tok.skip().
+
+Tue Aug 14 10:11:21 1990 James Clark (jjc at yquem)
+
+ * troff (most files): Redo warnings. Divide warnings into various
+ categories; warning() has an additional first argument indicating
+ the category it falls into.
+ * troff/input.c (main): -w now takes an argument. New option -W.
+ (enable_warning, disable_warning): New functions.
+
+ * ps/devps/afmtodit: Add -a option to lie about the italic angle.
+ * ps/devps/FontMakefile: Pretend TI has an angle of 7.
+
+Mon Aug 13 10:11:16 1990 James Clark (jjc at yquem)
+
+ * ps/devps/eqnchar: Better definitions of dotdot, vec, dyad, inf.
+ * xditview/devX100/eqnchar: Likewise. Remove definition of dot.
+ * xditview/devX75/eqnchar: Likewise.
+ * dvi/devdvi/eqnchar: Better definitions of vec, dyad, dotdot.
+
+ * eqn/other.c: When bar or over applies to a single character
+ don't produce an overline_box or an underline_box. Instead produce
+ an accent_box or an underaccent_box, with the accent a line
+ whose width is accent_width. New classes underaccent_box,
+ overline_char_box and underline_char_box.
+ * eqn/box.h: Move overline_box, underline_box, accent_box class
+ declarations into eqn/other.c. Add declarations of
+ make_underline_box, make_overline_box, make_accent_box.
+ * eqn/eqn.y: Call make_overline_box, make_underline_box
+ make_accent_box instead of constructors.
+ * eqn/pbox.h, eqn/box.c: Add accent_width parameter.
+
+ * eqn/other.c: Add accent_box::~accent_box.
+ * eqn/box.h: Declare it.
+
+ * groff.sh: With -Tps, use eqn -D.
+
+ * eqn/other.c (overline_box::output): Use \Z. If draw_flag use \D
+ rather than \l.
+ (underline_box::output): Similarily.
+ (accent_box::output): Use \Z.
+
+ * xditview/tmac.X: Add definitions of ~ and ^ (so that they are a
+ bit smaller.)
+
+Sun Aug 12 09:41:15 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (top_level_diversion::transparent_output(unsigned
+ char)): Use asciify.
+ * troff/input.c (asciify): Don't make it static.
+ * troff/token.h (asciify): Declare it.
+
+ * troff/input.c (get_name, get_long_name, token::get_char,
+ token::delimiter): Add an extra default argument which says
+ whether a warning should be printed.
+ * troff: Pass a non-zero argument to one of these rather than
+ printing a warning directly.
+
+Sat Aug 11 09:02:21 1990 James Clark (jjc at yquem)
+
+ * troff: Consistently use symbol::is_null.
+
+ * troff/dictionary.h: Move some inline functions into
+ dictionary.c.
+
+ * troff/request.h: Move inline functions into input.c.
+ (request_or_macro::invoke): Make it pure.
+
+ * troff/input.c, troff/reg.h: New class `constant_int_reg'.
+ * troff/input.c (init_input_requests): Use class constant_int_reg.
+ (class compatible_reg): Deleted.
+ * troff/div.c (init_div_requests): Use class constant_int_reg.
+ (class last_post_line_extra_space_reg): Deleted.
+
+ * troff/env.c (tab_character): Don't change the tab character if
+ we get an invalid argument.
+ (hyphen_char): Similarily.
+
+ * troff/reg.c (alter_format): Check that nm is not null.
+
+ * Makefile, groff.sh: Make it possible to customize the commands
+ used for printing PostScript and dvi files. Also make it possible
+ to customize the path used by groff.sh.
+
+ * eqn/eqn.y: Make `left' right associative.
+
+Fri Aug 10 18:20:39 1990 James Clark (jjc at yquem)
+
+ * pic/pic.h: Added definition of M_SQRT2 for those systems that
+ don't have it.
+
+ * pic/pic.h: Removed definition of INT_MAX.
+
+ * troff/node.c (italic_corrected_node::vertical_extent): Omit
+ `return'.
+
+ * troff/input.c (token::next): Handle \R like \n.
+
+Tue Aug 7 09:46:33 1990 James Clark (jjc at yquem)
+
+ * ps/tmac.pc (PSPIC): Simplify.
+
+ * troff/env.c (tab_stops::to_string):
+ * pic/pic.y (object_type_name):
+ * pic/troff.c (simple_output::line):
+ * pic/tex.c (tex_output::spline):
+ * pic/object.c (object_spec::make_object):
+ * tbl/main.c (process_data): Add cases to switch statements to
+ avoid cfront warnings. (Some of these are spurious, since the
+ switch already has a default case.)
+
+ * ps/tmac.ps (PSPIC): Reformatted. Prefix all local names with
+ `ps-'. Don't test systat; instead check number of arguments to
+ ps-bb.
+
+Mon Aug 6 00:13:07 1990 James Clark (jjc at yquem)
+
+ * macros/tmac.e: Do not decrease the page offset by 0.5i.
+
+ * ps/ps.c (ps_printer::ps_printer): Use mktemp instead of tempnam.
+ Unlink the file as soon as we have opened it, so that we don't
+ have to bother with signal handlers.
+ (handler): Deleted.
+ (fatal_error_exit): Deleted.
+ (main): Don't call signal.
+
+ * dvi/tfmtodit.c: Add -k option so that kerns with the skewchar
+ can be ignored.
+ * dvi/devdvi/Makefile: Use the -k option with S and MI.
+
+ * pic/pic.y: If there is a label, or an nth construction before
+ the first `.' in the argument to `with', ignore it and generate a
+ warning.
+ * pic/lex.c (lex_warning): New function.
+
+ * tbl/table.c (table::init_output): In section keep and release
+ macro, use 0 indent when diverting and the correct indent when
+ rereading.
+
+ * troff/input.c (interpolate_number_format): Do not interpolate
+ anything if the number register is not defined.
+
+ * tbl/main.c (process_data): Don't add entry when col >= ncolumns.
+
+Sat Aug 4 08:12:05 1990 James Clark (jjc at yquem)
+
+ * ps/devps/prologue (PICTURE): Set components of graphics state to
+ their default values.
+
+ * ps/devps/text.enc: Add trademark
+ * ps/devps/textmap: Add names for club, spade, heart, diamond,
+ carriagereturn, suchthat. Use Upsilon1 rather than Upsilon.
+ * ps/devps/symbolchars: Add names for summation and product.
+
+ * dvi/devdvi/texsy.map: Add names for club, spade, heart, diamond,
+ suchthat. Add pp. Add upper-case letters.
+
+ * xditview/libXdvi/DviChar.c: Add names for club, spade, heart,
+ diamond, carriagereturn, suchthat. Use Upsilon1 rather than
+ Upsilon.
+
+ * dvi/devdvi/texsy.map: Rename lA (left angle bracket) to la, and
+ rA (right angle bracket) to ra. Introduce names for double-headed
+ arrows and double-barred arrows: <>, va, lA, rA, hA, uA, dA, vA.
+ * ps/devps/textmap: Likewise for ps device.
+ * xditview/libXdvi/DviChar.c: Likewise for X100 and X75 devices.
+ * tty/devascii/R.proto: Rename lA to la and rA to ra.
+ * tty/devascii/R.proto: Likewise.
+ * tty/tmac.tty: Provide definitions for \(<>, \(lA, \(rA, \(hA,
+ \(uA, \(dA.
+ * eqn/delim.c: In delim_table, rename \(lA to \(la and \(rA to \(ra.
+
+ * xditview/tmac.X: Add definitions for \(fi \(fl \(ff \(Fi \(Fl.
+
+ * eqn/lex.c: Added definitions of `approx', `grad' and `del' to
+ def_table.
+
+Fri Aug 3 09:59:27 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (when_request): Use symbol::is_null rather than
+ has_arg to determine whether we have an argument.
+ (change_trap): Remove the trap if we get an invalid number. Give
+ an error if we don't get at least the macro name.
+ (diversion_trap): Remove trap if we get an invalid name or number.
+
+ * troff/env.c (environment_switch): Pop if we get an invalid
+ symbol or numeric expression.
+
+ * troff/input.c (do_define_macro): If EOF is encoutered while
+ defining the macro, do tok.next() before returning.
+
+ * troff/token.h (has_arg): Move definition from here, to ...
+ * troff/input.c (has_arg): ... here
+
+ * troff/env.c (space_size): Do nothing if we get an invalid argument.
+ * troff/input.c (shift): Likewise.
+
+ * pic/lex.c (get_token_after_dot): Accept `.center' as a synonym
+ for `.c'.
+
+ * pic/troff.c (troff_output::start_picture): Comment out calls to
+ `..'.
+
+ * eqn/main.c (do_file): Subtract 1 from current_lineno if
+ interpret_lf_args succeeds.
+
+ * eqn/main.c (do_file): Don't recognize delimiter if preceded by
+ \\. This avoids problems with \$N.
+
+ * groff.sh: Pass -C to preprocessors.
+
+ * lib/lf.c (interpret_lf_args): Be more flexible.
+
+ * tbl/main.c (main): Add -C option.
+ (table_input::get): Do not recognize TE if followed by character
+ other than a space or newline unless -C option given.
+ (process_input_file): Likewise for lf, TS.
+ (process_data): Likewise for lf in text blocks.
+
+ * eqn/main.c (main): Add -C option.
+ (do_file): Don't recognize EQ, EN or lf if followed by character
+ other than space or newline unless -C option given.
+ * eqn/lex.c (file_input::read_line): Similarily.
+ * eqn/eqn.h: Declare compatible_flag.
+
+ * etc/soelim.c (main): Add -C option.
+ (interpret_lf_args): Use version in libgroff.
+ (do_file):
+
+ * pic/main.c (main): Add -C option, which sets compatible_flag.
+ (top_input::get), (top_input::peek): If -C option not given,
+ do not recognize .PS/.PE/.PF/.lf if followed by a character
+ other than space or newline.
+ * pic/lex.c (file_input::read_line): Similarily.
+ * pic/pic.h: Add declaration of compatible_flag.
+
+Thu Aug 2 11:11:27 1990 James Clark (jjc at yquem)
+
+ * ps/tmac.ps (PSPIC): Avoid use of `echo -n'.
+
+ * troff/node.c, troff/node.h: Add `asciify' methods to classes
+ derived from node. New class space_char_hmotion_node.
+ * troff/input.c (asciify_macro): New function.
+ * troff/input.c (init_input_requests): New request `asciify' bound
+ to asciify_macro.
+ * macros/mm.diff: New file.
+ * Makefile: In install.mm target use `patch' to apply
+ macros/mm.diff.
+
+ * troff/input.c (macro::print_size): Just print the size in bytes.
+
+ * troff/div.c (return_request): Correct the argument
+ interpretation.
+
+Wed Aug 1 12:38:36 1990 James Clark (jjc at yquem)
+
+ * troff/node.h (class composite_node): Add sz member.
+ * troff/node.c (composite_node::size): Return sz.
+ * troff/input.c (macro_to_node): Use the initial size in the
+ environment as the size of the composite_node.
+
+ * troff/node.c (node::zero_width_tprint): Provide a reasonable
+ default.
+
+Tue Jul 31 10:07:10 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (change_trap): If we get a bad number expression,
+ do nothing.
+
+Mon Jul 30 10:30:49 1990 James Clark (jjc at yquem)
+
+ * lib/matherr.c (matherr): Define this only if math.h defines
+ TLOSS.
+
+Sun Jul 29 10:34:27 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (macro_diversion::distance_to_next_trap): If there
+ no diversion trap return vunits(INT_MAX - vresolution).
+
+Sat Jul 28 14:28:14 1990 James Clark (jjc at yquem)
+
+ * troff/input.c (do_zero_width): New implementation that doesn't
+ use a temporary environment. Use instead:
+ (token::add_to_node_list): New function.
+ * troff/env.c (environment::get_prev_char_height),
+ (environment::get_prev_char_height),
+ (environment::get_prev_char_skew): New functions.
+ (environment::get_prev_char): New function.
+ (environment::get_prev_char_width): Change to use get_prev_char.
+ (init_env_request): Implement new registers .cht, .cdp, .csk.
+ * eqn/sqrt.c (sqrt_box::output): Don't rely upon the argument to
+ \Z being processed in a separate environment.
+
+Fri Jul 27 10:21:25 1990 James Clark (jjc at yquem)
+
+ * tbl/table.c: Removed TABLE_BOTTOM_REG.
+
+ * tbl/table.c (table::init_output): In the section release macro,
+ give a warning message if the section won't fit on one page.
+
+ * tbl/table.c (table::do_top): Emit table keep only if table is
+ boxed.
+ (table::do_bottom): Likewise for table release.
+ (table::table), (table::add_vertical_rule): Remove reference to
+ keep member.
+ * tbl/table.h: Remove keep member.
+
+ * tbl/table.c: New register SUPPRESS_BOTTOM_REG. In
+ SECTION_RELEASE_MACRO, if there's not enough space before the next
+ trap to output the diversion, call T# ourselves, set
+ SUPPRESS_BOTTOM_REG to 1, spring the trap, then set
+ SUPPRESS_BOTTOM_REG back to 0. In T#, do nothing if
+ SUPPRESS_BOTTOM_REG is non-zero. In T#, always mark the current
+ vertical position and return to it before turning traps on again.
+
+Thu Jul 26 02:54:32 1990 James Clark (jjc at yquem)
+
+ * troff/node.c, troff/node.h: In classes derived from node,
+ replace prev_char_width method by last_char_node method.
+ * troff/env.c (environment::get_prev_char_width): Use
+ node::last_char_node rather than node::get_prev_char_width.
+
+ * Makefile: Added comment about -fno-inline on 68030-based
+ Apollos.
+
+ * troff/reg.c (number_format_to_ascii), eqn/delim.c (DELIM_TABLE_SIZE),
+ tty/tty.c (tty_font::load_tty_font), dvi/tfmtodit.c (main): Cast
+ expressions using sizeof to int.
+ * dvi/dvi.c (dvi_font::handle_x_command): Avoid long->int warnings.
+
+ * macros/tmac.e (TS): Don't move @f back past the current
+ position.
+
+Wed Jul 25 09:11:08 1990 James Clark (jjc at yquem)
+
+ * ps/ps.c (main): Buffer stderr.
+ * dvi/dvi.c (main): Likewise.
+ * tty/tty.c (main): Likewise.
+
+ * ps/ps.c (ps_printer::do_import): Improve error handling.
+
+ * troff/input.c (abort_request): Use asciify.
+
+ * driver/printer.h (printer::draw), driver/printer.c (printer::draw),
+ ps/ps.c (ps_printer::draw), dvi/dvi.c (dvi_printer::draw): Make
+ type of first argument int rather than char. This works around a
+ bug on the 68030 based Apollo using g++ 1.37.1.
+
+ * tbl/table.h (class table): Add `keep' member.
+ * tbl/table.c (table::table): Initialize `keep'.
+ (table::add_vertical_rule): Set `keep' to 1.
+ (table::do_top): Only emit table keep macro is `keep' is non-zero.
+ (table::do_bottom): Likewise for table release macro.
+ (table::do_row): Emit section keep macro even if the row is 0.
+
+Tue Jul 24 08:35:07 1990 James Clark (jjc at yquem)
+
+ * macros/tmac.e (@C): Preserve the font family across the change
+ in environments.
+
+Mon Jul 23 10:15:23 1990 James Clark (jjc at yquem)
+
+ * lib/font.c: Initialize font::hor and font::vert to 1.
+ (font::load_desc): Check the values of font::hor and font::vert.
+
+ * lib/lib.h: Added definition of INT_DIGITS. Fix it so that it can
+ be included in a C compilation.
+ (iftoa): Use INT_DIGITS. Include lib.h.
+ (itoa): Likewise.
+ (as_string): Likewise.
+ * tbl/table.c: Removed definition of INT_DIGITS.
+ * eqn/box.c (box::top_level): Use INT_DIGITS + 1 instead of 12.
+ * troff/input.c (input_input_requests): Likewise.
+ * ps/ps.c (make_encoding_name): Likewise.
+ (ps_printer::set_style): Likewise.
+ (ps_output::put_number): Use 1 + INT_DIGITS + 1 instead of 12.
+
+ * tty/devascii/R.proto: Map fm onto '.
+ * tty/devlatin1/R.proto: Likewise.
+
+Sat Jul 21 12:45:07 1990 James Clark (jjc at yquem)
+
+ * tbl/table.c: Use ' instead of DELIMITER_CHAR in places where the
+ argument to \w is at a different input level.
+
+ * tbl/table.c (table::init_output): Define a new macro
+ REPEATED_VPT_MACRO, like vpt but if in a diversion also
+ transparently outputs itself.
+ (table::define_bottom_macro): Use REPEATED_VPT_MACRO instead of
+ vpt.
+ (table::do_row): Likewise.
+
+ * tbl/table.c (vertical_rule::print): Prefix the .sp -1 line with
+ TRANSPARENT_STRING_NAME.
+
+ * tbl/table.c (table::init_output): In the table release macro
+ print an error message and don't produce any output if after
+ issuing the need request the table still will not fit. Also
+ remove the diversion after bringing it back.
+
+ * tbl/table.c (table::init_output): Define a new macro
+ REPEATED_MARK_MACRO, like mk but if in a diversion also
+ transparently outputs itself.
+ (table::do_row): Mark row_top_reg using REPEATED_MARK_MACRO. This
+ is necessary because .TH might not call .T#.
+ (table::do_top): Likewise TOP_REG.
+ (table::define_bottom_macro): If TOP_REG is no longer valid, use
+ #T - DOUBLE_LINE_SEP rather than #T. This is necessary because the
+ table header might contain just the two top rules.
+
+Fri Jul 20 10:51:42 1990 James Clark (jjc at yquem)
+
+ * troff/div.c: Implement new request `ptr' to print all traps.
+
+ * troff/env.c (init_env_requests): Implement `.tabs' reg with
+ init_string_env_reg.
+ * troff/env.c (class tab_reg): Deleted.
+
+Thu Jul 19 12:07:16 1990 James Clark (jjc at yquem)
+
+ * troff/div.c: New number register .pn returns the number of the
+ next page as set by the pn request.
+
+ * macros/tmac.an: Redid headers and footers. Number each manual
+ entry starting from 1 unless \nC is > 0, like Sun. Added an
+ optional 5th argument to .TH which specifies the manual name and
+ appears in the center of the header. Understand the X, P and D
+ registers like Sun.
+
+Wed Jul 18 10:23:31 1990 James Clark (jjc at yquem)
+
+ * troff/env.c (init_env_requests): New number register `.lt' to
+ return the title length.
+
+ * troff/node.h (class transparent_dummy_node): New class.
+ * troff/node.c (class transparent_dummy_node): Provide member
+ functions.
+ * troff/env.c (interrupt): Add a transparent_dummy_node, rather
+ than a dummy_node.
+
+ * troff/input.c (token::next): New escape sequence \).
+ * troff/input.c (get_copy): Recognize \) in copy mode.
+
+ * troff/input.c (input_stack::clear): New function.
+ * troff/input.c (exit_request): Use input_stack::clear.
+
+ * troff/token.h: Removed TOKEN_NO_PRINT_CHAR.
+ * troff/input.c (token::process): Removed case TOKEN_NO_PRINT_CHAR.
+
+ * troff/env.c: Move set_page_character to input.c. Move
+ page_character to input.c also.
+ * troff/env.c (title): Split off the reading of the parts of the
+ title into read_title_parts.
+ * troff/input.c (read_title_parts): New function. Check the
+ input_level when testing whether a token matches the delimiter.
+
+ * troff/input.c (exit_request): New function.
+ * troff/input.c (init_input_requests): Bind ex request to
+ exit_request rather than exit_groff.
+
+ * troff/input.c (exit_groff): Call tok.next() before
+ process_input_stack().
+
+Mon Jul 16 09:47:23 1990 James Clark (jjc at yquem)
+
+ * troff/env.c: ifdef widow control support on WIDOW_CONTROL.
+ * troff/env.h: ditto.
+ * troff/input.c: ditto.
+
+ * troff/env.c (environment::is_empty): Test pending_lines.
+
+ * troff/env.c (environment::have_pending_lines): Removed.
+
+ * troff/input.c: Add request to flush pending lines from the
+ environment.
+
+ * troff/env.c, troff/env.h: Add automatic widow control feature.
+
+ * troff/input.c (exit_groff): Do process_input_stack() after
+ do_break() but before setting exit_flag to 2.
+
+ * troff/input.c: Remove FLUSH_PENDING_LINES and
+ TOKEN_FLUSH_PENDING_LINES. Instead, flush pending lines from
+ environment after END_TRAP token seen, but only if there aren't
+ any more traps still unfinished.
+ * troff/token.h: Remove TOKEN_FLUSH_PENDING_LINES.
+
+Sun Jul 15 10:50:08 1990 James Clark (jjc at yquem)
+
+ * troff/env.c: Rename the `retain_size' member of class
+ pending_output_line to `no_fill'.
+
+ * troff/env.c (title): When the line is output, make the
+ retain_size argument !fill.
+
+ * troff/node.h: Add `hyphenated' member to struct breakpoint.
+ * troff/node.c (space_node::get_breakpoints),
+ (dbreak_node::get_breakpoints): Fill this in.
+ * troff/env.c: Allow specification of maximum number of
+ consecutive hyphenated lines.
+
+ * troff/env.c (environment::is_empty): Add test for !current_tab.
+
+Sat Jul 14 11:23:01 1990 James Clark (jjc at yquem)
+
+ * troff/env.c (environment::hyphenate_line): Don't completely give
+ up if the word is not to be hyphenated; continue so that breaks
+ can be made at break_char_node's.
+
+ * lib/lib.h: Only define INT_MAX if it's not already defined;
+ undef INT_MIN if it's already defined.
+
+ * Makefile: Make it easy to define CFRONT_ANSI_BUG.
+
+ * lib/lib.h: If CFRONT_ANSI_BUG is defined, cast INT_MIN to long.
+ This works around a bug in AT&T C++ 2.0 used with an ANSI C
+ compiler.
+
+ * macros/tmac.an (an-header): Set no-space mode.
+
+ * macros/tmac.an (TH): Start a new page if necessary.
+
+ * Started using ChangeLog at version 0.4.
+
+Local Variables:
+version-control: never
+End:
diff --git a/gnu/usr.bin/groff/Makefile b/gnu/usr.bin/groff/Makefile
new file mode 100644
index 000000000000..0e300d08ec57
--- /dev/null
+++ b/gnu/usr.bin/groff/Makefile
@@ -0,0 +1,12 @@
+# Makefile for groff
+
+SUBDIR= libgroff libdriver libbib\
+ groff troff nroff tbl pic eqn grops grotty grodvi\
+ refer lookbib indxbib lkbib \
+ tfmtodit addftinfo pfbtops psbb \
+ devices tmac mm man xditview
+
+# BSD already provides soelim
+MISC= soelim
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/Makefile.cfg b/gnu/usr.bin/groff/Makefile.cfg
new file mode 100644
index 000000000000..6ef2ce2956e1
--- /dev/null
+++ b/gnu/usr.bin/groff/Makefile.cfg
@@ -0,0 +1,42 @@
+# Libraries
+
+# Bad assumption, if one exists they all exist
+.if exists(${.CURDIR}/../libgroff/obj)
+LIBGROFF= $(.CURDIR)/../libgroff/obj/libgroff.a
+LIBDRIVER= $(.CURDIR)/../libdriver/obj/libdriver.a
+LIBBIB= $(.CURDIR)/../libbib/obj/libbib.a
+.else
+LIBGROFF= $(.CURDIR)/../libgroff/libgroff.a
+LIBDRIVER= $(.CURDIR)/../libdriver/libdriver.a
+LIBBIB= $(.CURDIR)/../libbib/libbib.a
+.endif
+
+DEFINES= -DHAVE_UNISTD_H=1\
+ -DHAVE_DIRENT_H=1\
+ -DHAVE_LIMITS_H=1\
+ -DHAVE_STDLIB_H=1\
+ -DHAVE_SYS_DIR_H=1\
+ -DHAVE_CC_LIMITS_H=1\
+ -DHAVE_CC_UNISTD_H=1\
+ -DSTDLIB_H_DECLARES_GETOPT=1\
+ -DUNISTD_H_DECLARES_GETOPT=1\
+ -DSTDLIB_H_DECLARES_PUTENV=1\
+ -DRETSIGTYPE=void\
+ -DHAVE_MMAP=1\
+ -DHAVE_RENAME=1\
+ -DHAVE_MKSTEMP=1\
+ -DHAVE_SYS_SIGLIST=1\
+ -DARRAY_DELETE_NEEDS_SIZE=1
+
+CFLAGS+=$(DEFINES)
+CXXFLAGS+=$(DEFINES)
+
+.y.o:
+ $(YACC) $(YFLAGS) $(.IMPSRC)
+ mv y.tab.c $(.PREFIX).cc
+ mv y.tab.h $(.PREFIX).tab.h
+ ${CXX} ${CXXFLAGS} -c $(.PREFIX).cc -o ${.TARGET}
+.y.cc:
+ $(YACC) $(YFLAGS) $(.IMPSRC)
+ mv y.tab.c $(.PREFIX).cc
+ mv y.tab.h $(.PREFIX).tab.h
diff --git a/gnu/usr.bin/groff/NEWS b/gnu/usr.bin/groff/NEWS
new file mode 100644
index 000000000000..bbe0c0b510f3
--- /dev/null
+++ b/gnu/usr.bin/groff/NEWS
@@ -0,0 +1,662 @@
+This file describes recent user-visible changes in groff. Bug fixes
+are not described. There are more details in the man pages.
+
+VERSION 1.08
+============
+
+Troff
+-----
+
+The escape sequence \V[xxx] will interpolate the value of the
+environment variable xxx.
+
+Tbl
+---
+
+The decimalpoint option can be used to specify the character to be
+recognized as the decimal point character in place of the default
+period.
+
+VERSION 1.07
+============
+
+Groff
+-----
+
+The environment variable GROFF_COMMAND_PREFIX can be used to control
+whether groff looks for `gtroff' or `troff' (similarily for the
+preprocessors.)
+
+Troff
+-----
+
+Multilingual hyphenation is supported by new `hpf' and `hla' requests,
+and by a `\n[.hla]' number register. The -H option has been removed.
+Files of hyphenation patterns can have comments.
+
+When a font cannot be found, troff gives a warning (of type `font',
+enabled by default) instead of an error.
+
+There's a new request `trnt' that's like `tr' except that it doesn't
+apply to text transparently throughput into a diversion with \!.
+
+Tbl
+---
+
+There is a `nokeep' option which tells tbl not to use diversions to
+try to keep the table on one page.
+
+Eqn
+---
+
+Setting the parameter `nroff' to a non-zero value causes `ndefine' to
+behave like `define' and `tdefine' to be ignored. This is done by
+eqnrc when the current device is ascii or latin1. There's a `neqn'
+script that just does `eqn -Tascii'.
+
+Grotty
+------
+
+grotty uses whatever page length was specified using the `pl' request
+rather than using the paperlength command in the DESC file. The
+paperwidth command in the DESC file is also ignored.
+
+VERSION 1.06
+============
+
+The programs in groff that have Unix counterparts can now be installed
+without a leading `g' prefix. See the `g' variable in the Makefile.
+
+The g?nroff script simulates the nroff command using groff.
+
+New special characters \(+h, \(+f, \(+p, \(Fn, \(Bq, \(bq, \(aq, \(lz,
+\(an. See groff_char(7).
+
+^L is now a legal input character.
+
+Groff
+-----
+
+The Xps pseudo-device has disappeared. Instead there is a new -X
+option that tells groff to use gxditview instead of the usual
+postprocessor. (So instead of -TXps, use -XTps or just -X if your
+default device is ps.)
+
+The postprocessor to be used for a particular device is now specified
+by a `postpro' command in the DESC file rather than being compiled
+into groff. Similarily the command to be used for printing (with the
+-l option) is now specified by a `print' command in the DESC file.
+
+The groff command no longer specifies eqnchar as an input file for
+eqn. Instead eqn automatically loads a file `eqnrc'. The groff
+command no longer passes the -D option to eqn. Instead eqnrc sets the
+draw_lines parameter.
+
+The groff command no longer tells troff to load a device-specific
+macro file. This is handled instead by the `troffrc' file, which is
+always loaded by troff.
+
+The shell script version of groff has been removed.
+
+Troff
+-----
+
+The `rchar' request removes a character definition established with `char'.
+
+Compatibility mode is disabled and the escape character is set to `\'
+while a character definition is being processed.
+
+The `\#' escape sequence is like `\%' except that the terminating
+newline is ignored.
+
+The `shc' request tells troff which character to insert (instead of
+the default \(hy) when a word is hyphenated at a line break.
+
+A font name of 0 (zero) in the DESC file will cause no font to be
+mounted on the corresponding font position. This is useful for
+arranging that special fonts are mounted on positions on which users
+are not likely explicitly to mount fonts. All groff devices now avoid
+initially mounting fonts on positions 5-9.
+
+The `do' request allows a single request or macro to be interpreted
+with compatibility mode disabled.
+
+troff automatically loads a file `troffrc' before any other input file.
+This can be prevented with the -R option. This file is responsible
+for loading the device-specific macros.
+
+Pic
+---
+
+The -x option has been removed and a -n option has been added. By
+default, pic now assumes that the postprocessor supports groff
+extensions. The -n option tells pic to generate output that works
+with ditroff drivers. The -z option now applies only to TeX mode.
+
+The -p option has been removed. Instead if the -n option is not
+specified, pic generates output that uses \X'ps: ...' if the \n(0p
+register is non-zero and tmac.ps sets this register to 1.
+
+In places where you could 1st or 5th you can now say `i'th or `i+1'th
+(the quotes are required).
+
+Eqn
+---
+
+Eqn now automatically reads a file `eqnrc' from the macro directory.
+This performs the same role that the eqnchar files used to. This can
+be prevented by the -R option.
+
+Setting the draw_lines parameter to a non-zero value causes lines to
+be drawn using \D rather than \l. The -D option is now obsolete.
+
+`uparrow', `downarrow' and `updownarrow' can be used with `left' and
+`right'.
+
+The amount of extra space added before and after lines containing
+equations can be controlled using the `body_height' and `body_depth'
+parameters.
+
+Grops
+-----
+
+Font description files have been regenerated from newer AFM files.
+You can get access to the additional characters present in the text
+fonts in newer PostScript printers by using -mpsnew.
+
+The default value of the -b option is specified by a `broken' command
+in the DESC file.
+
+With the -g option, grops will generate PostScript code that guesses
+the page height. This allows documents to be printed on both letter
+(8.5x11) and A4 paper without change.
+
+Grodvi
+------
+
+ISO Latin-1 characters are available with -Tdvi. Format groff_char(7)
+with groff -Tdvi for more information.
+
+Grotty
+------
+
+The -mtty-char macros contain additional character definitions for
+use with grotty.
+
+Macros
+------
+
+In previous releases the groff -me macros treated the $r and $R number
+registers in a way that was incompatible with the BSD -me macros. The
+reason for this was that the approach used by the BSD -me macros does
+not work with low resolution devices such as -TX75 and -TX100.
+However, this caused problems with existing -me documents. In this
+release, the vertical spacing is controlled by the $v and $V registers
+which have the same meaning as $r and $R in earlier groff releases.
+In addition, if the $r or $R register is set to a value that would be
+correct for for the BSD -me macros and a low resolution device is not
+being used, then an appropriate value for the $v or $V register will
+be derived from the $r or $R register.
+
+The groff -me macros work with -C and (I think) with Unix troff.
+
+For backward compatibility with BSD -me, the \*{ and \*} strings are
+also available as \*[ and \*]. Of course, \*[ will only be useable
+with -C.
+
+The \*T string has been deleted. Use \*(Tm instead.
+
+Xditview
+--------
+
+The `n', Space and Return keys are bound to the Next Page action. The
+`p', BackSpace and Delete keys are bound to the Previous Page action.
+The `q' key is bound to the Quit action.
+
+The `r' key is bound to a rerasterize action that reruns groff, and
+redisplays the current page.
+
+VERSION 1.05
+============
+
+Pic
+---
+
+There is a alternative assignment operator `:=' which interacts
+differently with blocks.
+
+There is a new command `command', which allows the values of variables
+to be passed through to troff or TeX.
+
+The `print' command now accepts multiple arguments.
+
+String comparison expressions (using `==' or `!=') are allowed in more
+contexts.
+
+Grotty
+------
+
+Horizontal and vertical lines drawn with \D'l ...' will be rendered
+using -, | and + characters. This is intended to give reasonable
+results with boxed tables. It won't work well with pic.
+
+Macros
+------
+
+The -mdoc macros have been upgraded to the version in the second
+Berkeley networking release. This version is not completely
+compatible with earlier versions; the old version is still available
+as -mdoc.old. The grog script has been enhanced so that it can
+usually determine whether a document requires the old or new versions.
+
+With -TX75, -TX100 and -TXps, the PSPIC macro will produce a box
+around where the picture would appear with -Tps.
+
+VERSION 1.04
+============
+
+An implementation of the -mm macros is included.
+
+The directory in which temporary files are created can be controlled
+by setting the GROFF_TMPDIR or TMPDIR environment variables.
+
+Pic
+---
+
+Some MS-DOS support (see pic/make-dos-dist).
+
+Grops
+-----
+
+There are two new \X commands (\X'ps: invis' and \X'ps: endinvis')
+which make it possible to have substitute characters that are
+displayed when previewing with -TXps but ignored when printing with
+grops.
+
+Xditview
+--------
+
+Support for scalable fonts.
+
+VERSION 1.03
+============
+
+No changes other than bug fixes.
+
+VERSION 1.02
+============
+
+There is an implementation of refer and associated programs. groff -R
+preprocesses with grefer; no mechanism is provided for passing
+arguments to grefer because most grefer options have equivalent
+commands which can be included in the file. grog also supports refer.
+
+There is an alternative perl implementation of the grog script.
+
+The code field in lines in the charset section of font description
+files is now allowed to contain an arbitrary integer (previously it
+was required to lie between 0 and 255). Currently grops and grodvi
+use only the low order 8 bits of the value. Grodvi will use the
+complete value; however, this is unlikely to be useful with
+traditional TeX tools (.tfm files only allow 8 bit character codes.)
+
+Left and right double quotes can be obtained with \(lq and \(rq
+respectively.
+
+There is a new program called pfbtops which translates PostScript
+fonts in pfb format to ASCII.
+
+A slightly modified version of the Berkeley tmac.doc is included.
+
+Troff
+-----
+
+In long escape names the closing ] is now required to be at the same
+input level as the opening [.
+
+The \A'S' escape sequence returns 1 or 0 according as S is or is not
+suitable for use as a name.
+
+\~ produces an unbreakable space that can be stretched when the line
+is adjusted.
+
+The `mso' request is like the `so' request except that it searches for
+the file in the same directories in which tmac.X is searched for when
+the -mX option is given.
+
+The escape sequence `\R' is similar to the `nr' request.
+
+Eqn
+---
+
+A new `special' primitive allows you to add new types of unary
+constructs by writing a troff macro.
+
+Pic
+---
+
+The implementation no longer uses gperf.
+
+Grops
+-----
+
+The compile-time -DBROKEN_SPOOLER option has been replaced by a
+BROKEN_SPOOLER_FLAGS option. This allows more precise control over
+how grops should workaround broken spoolers and previewers. There is
+a new -b option that can change this at run-time.
+
+Grops now generates PostScript that complies with version 3.0 of the
+Document Structuring Convention.
+
+The resource management component of grops (the part that deals with
+imported documents and downloadable fonts) has been rewritten and now
+supports version 3.0 of the Document Structuring Conventions. The
+%%DocumentFonts comment is no longer supported; you must use the
+%%Document{Needed,Supplied}{Fonts,Resources} comments instead
+(or as well.)
+
+tmac.psatk contains some macros that support the mechanism used by the
+Andrew Toolkit for including PostScript graphics in troff documents.
+
+Xditview
+--------
+
+Parts of xditview have been rewritten so that it can be used with the
+output of gtroff -Tps. groff -TXps will run gtroff -Tps with
+gxditview.
+
+There is a new menu entry `Print' which brings up a dialog box for
+specifying a command with which the file being previewed should be
+printed.
+
+Xditview now uses imake.
+
+VERSION 1.01
+============
+
+The groff command now understands the gtroff `-a' and `-i' options.
+
+With the `m' and `n' scale indicators, the scale factor is rounded
+horizontally before being applied. This makes (almost) no difference
+for devices with `hor' equal to 1, but it makes groff with -Tascii or
+-Tlatin1 behave more like nroff in its treatment of these scale
+indicators. Accordingly tmac.tty now calls the `nroff' request so
+that the `n' condition will be true.
+
+The device-specific macros (tmac.ps, tmac.dvi, tmac.tty and tmac.X)
+have been made to work at least somewhat with -C. In particular the
+special characters defined by these macros now work with -C.
+
+groff -Tdvi -p will now pass pic the -x flag; this will enable filling
+of arrowheads and boxes, provided that your dvi driver supports the
+latest version of the tpic specials.
+
+Eqn
+---
+
+There is a new `-N' option that tells eqn not to allow newlines in
+delimiters. This allows eqn to recover better from missing closing
+delimiters. The groff command will pass on a `-N' option to eqn.
+
+Grops
+-----
+
+You can now use psfig with grops. See the file ps/psfig.diff. I do
+not recommend using psfig for new documents.
+
+The command \X'ps: file F' is similar to \X'ps: exec ...' except that
+the PostScript code is read from the file F instead of being contained
+within the \X command. This was added to support psfig.
+
+Grodvi
+------
+
+There are font files HB and HI corresponding to cmsssbx10 and cmssi10.
+
+Macros
+------
+
+The groff -me macros now work with the -C option. As a result, they
+may also work with Unix nroff/troff.
+
+In -me, the $r and $R number registers now contain the line spacing as
+a percentage of the pointsize expressed in units (normally about 120).
+The previous definition was useless with low resolution devices such
+as X75 and X100.
+
+VERSION 1.00
+============
+
+A -ms-like macro-package is now included.
+
+The name for the Icelandic lowercase eth character has been changed
+from \(-d to \(Sd.
+
+Troff
+-----
+
+There is a new request `nroff', which makes the `n' built-in condition
+true and the `t' built-in condition false; also a new request `troff'
+which undoes the effect of the `nroff' request. This is intended only
+for backward compatibility: it is usually better to test \n(.H or
+\n(.V or to use the `c' built-in condition.
+
+The \R escape sequence has been deleted. Use \E instead.
+
+There are `break' and `continue' requests for use with the `while'
+request.
+
+There is a request `hym' that can ensure that when the current
+adjustment mode is not `b' a line will not be hyphenated if it is no
+more than a given amount short, and a request `hys' that can ensure
+that when the current adjustment mode is `b' a line will not be
+hyphenated if it can be justified by adding no more than a given
+amount of extra space to each word space.
+
+There is a request `rj' similar to `ce' that right justifies lines.
+
+A warning of type `space' will be given when a call is made to an
+undefined request or macro with a name longer than two characters, and
+the first two characters of the name make a name that is defined.
+This is intended to find places where a space has been omitted been a
+request or macro and its argument. This type of warning is enabled by
+default.
+
+Pic
+---
+
+A comma is permitted between the arguments to the `reset' command.
+
+For use with TeX, there is a new `-c' option that makes gpic treat
+lines beginning with `.' in a way that is more compatible with tpic
+(but ugly).
+
+Eqn
+---
+
+It is no longer necessary to add `space 0' at the beginning of
+complicated equations inside pictures.
+
+`prime' is now treated as an ordinary character, as in Unix eqn. The
+previous behaviour of `prime' as an operator can now be obtained using
+`opprime'.
+
+Xditview
+--------
+
+There are two new devices X75-12 and X100-12 which are the same as X75
+and X100 except that they are optimized for documents that use mostly
+12 point text.
+
+VERSION 0.6
+===========
+
+The installation process has been refined to make it easy for you to
+share groff with someone who has the same type of machine as you but
+does not have a C++ compiler. See the end of the INSTALL file for
+details.
+
+There is a man page for the tfmtodit program which explains how to use
+your own fonts with groff -Tdvi.
+
+There is a man page for afmtodit which explains how to use your own
+PostScript fonts with groff -Tps.
+
+The \N escape sequence is now fully supported. It can now be used to
+access any character in a font by its output code, even if it doesn't
+have a groff name. This is made possible by a convention in the font
+files that a character name of `---' refers to an unnamed character.
+The drivers now all support the `N' command required for this. The font
+description files have been updated to include unnamed characters.
+
+The `x' command in font description files has been removed: instead
+any unknown commands are automatically made available to the drivers.
+If you constructed your own font files with an earlier version of
+tfmtodit or afmtodit, you must construct them again using the current
+version.
+
+Characters between 0200 and 0237 octal are no longer legal input
+characters. Note that these are not used in ISO 8859.
+
+A command called `grog' has been added, similar to the `doctype'
+command described in Kernighan and Pike.
+
+Groff
+-----
+
+The groff command has some new options: -V prints the pipeline
+instead of executing it; -P passes an argument to the postprocessor,
+-L passes an argument to the spooler.
+
+There is a C++ implementation of the groff command. This handles some
+things slightly better than the shell script. In particular, it can
+correctly handle arguments containing characters that have a special
+meaning to the shell; it can give an error message when child
+processes other than the last in the pipeline terminate abnormally;
+its exit status can take account of the exit statuses of all its child
+processes; it is a little more efficient; when geqn is used, it
+searches for the eqnchar file in the same way that font metric files
+are searched for, rather than expecting to find it in one particular
+directory.
+
+Gtroff
+------
+
+There is font translation feature: For example, you can tell gtroff to
+use font `HR' whenever font `H' is requested with the line
+ .ftr H HR
+This would be useful for a document that uses `H' to refer to
+Helvetica.
+
+There are some new number registers: `.kern' contains the current kern
+mode, `.lg' the current ligature mode, `.x' the major version number,
+`.y' the minor version number, `.ce' the number of lines to be
+centered in the current environment, `.trunc' the amount of vertical
+space truncated by the most recently sprung vertical position trap,
+`.ne' the amount of vertical space needed in the last `ne' request
+that caused a vertical position trap to be sprung.
+
+The `cf' request now behaves sensibly in a diversion. If used in a
+diversion, it will now arrange for the file to be copied to the output
+when the diversion is reread.
+
+There is a new request `trf' (transparent file) similar to `cf', but
+more like `\!'.
+
+There is a new escape sequence `\Y[xxx]', roughly equivalent to
+`\X'\*[xxx]'', except that the contents of string or macro xxx are not
+interpreted, and xxx may contain newlines. This requires an output
+format extension; the drivers have been modified to understand this.
+Grops has also been modified to cope with newlines in the arguments to
+\X commands; grops has a new \X command mdef, which is like def except
+that it has a first argument giving the number of definitions.
+
+There is a new warning category `escape' which warns about unknown
+escape sequences.
+
+The `fp' request now takes an optional third argument giving the external
+name of the font.
+
+The `\_' character is now automatically translated to `\(ul' as in troff.
+
+The environment variable `GROFF_HYPHEN' gives the name of the file
+containing the hyphenation patterns.
+
+There is a `\C'xxx'' escape sequence equivalent to `\[xxx]'.
+
+Characters ", ', ), ], *, \(dg are now initially transparent for the purposes
+of end of sentence recognition.
+
+There is an anti-recusion feature in the `char' request, so you can
+say `.char \(bu \s+2\(bu\s-2'.
+
+The limit on the number of font positions has been removed.
+Accordingly `\n[.fp]' never returns 0.
+
+The restriction on the number of numbered environments has been removed.
+
+There is a new escape sequence `\E' that makes it possible to
+guarantee that an escape sequence won't get interpreted in copy-mode.
+The `\R' escape sequence is accordingly now deprecated.
+
+Gpic
+----
+
+Arguments of the form `X anything X' (in the `copy thru', `sh', `for',
+`if' and `define' constructs) can now be of the form `{ anything }'.
+
+If the `linethick' variable is negative (as it now is initially),
+lines will be drawn with a thickness proportional to the current point
+size.
+
+The `rand' function now takes no arguments and returns a number between
+0 and 1. The old syntax is still supported.
+
+`^' can be used in expressions to indicate exponentiation.
+
+In the `for' construct the argument to the by clause can be prefixed
+by `*' to indicate that the increment is multiplicative.
+
+A bare expression may be used as an attribute. If the current
+direction is `dir', then an attribute `expr' is equivalent to
+`dir expr'
+
+There is a `sprintf' construct that allows numbers to be formatted and used
+wherever a quoted string can be used.
+
+The height of a text object without an explicit height attribute is
+the number of text strings associated with the object times the value
+of the `textht' variable.
+
+The maximum height and width of a picture is controlled by the
+`maxpswid' and `maxpsht' variables.
+
+Gtbl
+----
+
+Gtbl can now handle gracefully the situation where the `ce' request
+has been applied to a table.
+
+Geqn
+----
+
+The `ifdef' primitive has been generalized.
+
+A tilde accent can be put underneath a box using `utilde'. This
+defined using a general `uaccent' primitive.
+
+Grops
+-----
+
+There is a new PostScript font downloading scheme which handles font
+downloading for imported illustrations. Previously, the name of the
+file containing the font was given in the `x download' line in the
+groff font metric file. Now, there is a `download' file which says
+for each PostScript font name which file contains that font. Grops
+can also now handle inter-font dependencies, where one downloadable
+font depends on some other (possibly downloadable) font.
+
+The `T' font has been removed. The characters it used to provide are
+now provided by `char' definitions in tmac.ps. TSymbol.ps has also
+been removed, and the tweaks it provided are now provided by `char'
+definitions.
diff --git a/gnu/usr.bin/groff/PROBLEMS b/gnu/usr.bin/groff/PROBLEMS
new file mode 100644
index 000000000000..16e168c86fbe
--- /dev/null
+++ b/gnu/usr.bin/groff/PROBLEMS
@@ -0,0 +1,458 @@
+This file describes various problems that have been encountered in
+compiling, installing and running groff. Suggestions for additions or
+other improvements to this file are welcome.
+
+* gcc 2.3.3 fails to compile pic/object.cc.
+
+Apply the following patch:
+
+Thu Apr 1 12:06:03 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * cp-init.c (expand_default_init): Don't clear DECL_REGISTER.
+
+*** cp-init.c.~2~ Mon Mar 29 21:48:36 1993
+--- cp-init.c Thu Apr 1 12:00:33 1993
+*************** expand_default_init (binfo, true_exp, ex
+*** 1141,1149 ****
+ }
+
+- /* ARM $7.1.1: "[register] may be ignored and in most implementations
+- it will be ignored if the address of the variable is taken."
+- Since we're likely to do just that in the ctor call, clear this. */
+- DECL_REGISTER (exp) = 0;
+-
+ rval = build_method_call (exp, constructor_name (type),
+ parms, binfo, flags|xxref_init_possible);
+--- 1141,1144 ----
+
+
+* On a DECstation or other machine using a MIPS cpu, gcc/g++ 2.2.2
+gets a fatal signal while compiling tbl/main.c and tbl/table.c.
+
+Upgrade to gcc 2.3 or compile those files without -O.
+
+* I get lots of `numeric overflow' error messages whenever I run
+groff; I compiled groff with AT&T C++ 2.0 with an ANSI C compiler.
+
+Make sure -DCFRONT_ANSI_BUG is included in DEFINES in the top-level
+Makefile. If that doesn't solve the problem, define INT_MIN as
+-INT_MAX in libgroff/lib.h.
+
+* I get errors when I try to compile groff with Sun C++.
+
+Groff requires header files that are moderately compatible with AT&T
+C++ and ANSI C. With some versions of Sun C++, the supplied header
+files need some of the following changes to meet this requirement:
+<string.h> must declare the mem* functions, (just add `#include
+<memory.h>' to <string.h>); the first argument to fopen and freopen
+should be declared as `const char *'; the first argument to fread
+should be declared as `void *'; the first argument to fwrite should be
+declared as `const void *'; malloc should be declared to return `void
+*'; in <alloca.h>, the declaration `extern "C" { void
+*__builtin_alloca(int); }' should be added; declarations of getopt(),
+optarg, optind and opterr should be added to <stdlib.h>; in
+<sys/signal.h> the return type and the second argument type of
+signal() should be changed to be `void (*)(int)'.
+
+You can either change them in place, or copy them to some other
+directory and include that directory with a -I option.
+
+* I get errors when I try to compile groff with DEC C++.
+
+Fix the declaration of write() in <unistd.h> so that the second
+argument is a const char *. Fix the declaration of open() in
+<sys/file.h> so that the first argument is a const char *.
+
+* On Ultrix, the make stops with the message
+
+ *** Error code 1
+
+ Stop.
+
+for no apparent reason.
+
+Use GNU make.
+
+* I'm having problems compiling groff on 386BSD 0.1.
+
+If you're using ash as /bin/sh, you'll need the following patch.
+
+*** gendef.sh.org Sun Jun 30 13:30:36 1991
+--- gendef.sh Sun Feb 28 10:23:49 1993
+***************
+*** 3,9 ****
+ file=$1
+ shift
+
+! defs="#define $1"
+ shift
+ for def
+ do
+--- 3,10 ----
+ file=$1
+ shift
+
+! x=$1
+! defs="#define $x"
+ shift
+ for def
+ do
+
+You'll also need to change dirnamemax.c so that it doesn't use
+pathconf().
+
+* While compiling on Xenix, ranlib libgroff.a fails.
+
+The system ranlib can't handle externals longer than 40 characters.
+Use the ranlib included in demon.co.uk:/pub/xenix/g++-1.40.3a.v1
+instead.
+
+* Groff can't handle my troff document. It works fine with AT&T troff.
+
+Read the section on incompatibilities in gtroff(1). Try using the -C
+option. Alternatively there's the sed script in tmac/fixmacros.sed
+which will attempt to edit a file of macros so that it can be used
+with groff without the -C flag.
+
+* groff -Tdvi produces dvi files that use fonts at weird magnifications.
+
+Yes, it does. You may need to compile fonts with Metafont at these
+magnifications. The CompileFonts script in the devdvi/generate
+directory may help you to do this. (It will take a *long* time.)
+
+* pic output is not centered horizontally; pictures sometimes run off
+the bottom of the page.
+
+The macro package you are using is not supplying appropriate definitions
+of PS and PE. Give groff a -mpic option.
+
+* I'm having problems including PostScript illustrations using the PSPIC
+macro.
+
+A PostScript document must meet three requirements in order to be
+included with the PSPIC macro: it must comply with the Adobe Document
+Structuring Conventions; it must contain a BoundingBox line; it must
+be ``well-behaved''. The BoundingBox line should be of the form:
+
+ %%BoundingBox: llx lly urx ury
+
+where llx, lly, urx, ury are the coordinates of the lower left x,
+lower left y, upper right x, upper right y of the bounding box of
+marks on the page expressed as integers in the default PostScript
+coordinate system (72 units per inch, origin at bottom left corner).
+A useful tactic is to print out the illustration by itself (you may
+need to add a `showpage' at the end), and physically measure the
+bounding box. For more detail on these requirements, read the
+specification of Encapsulated PostScript format. (This is available
+from the Adobe file server; send a message with a body of `help' to
+ps-file-server@adobe.com.)
+
+* I've configured groff for A4 paper, but gtroff still seems to think
+that the length of a page (as returned by \n(.p) is 11 inches.
+
+This is intentional. The PAGE option is used only by grops. For
+compatibility with ditroff, the default page length in gtroff is
+always 11 inches. The page length can be changed with the `pl'
+request.
+
+* Groff doesn't use the font names I'm used to.
+
+Use the `ftr' request. See gtroff(1).
+
+* I get errors using the Unix -ms macros with groff -e -C.
+
+Apply this change:
+
+*** /usr/lib/ms/ms.eqn Tue Apr 25 02:14:28 1989
+--- ms.eqn Sun Nov 11 10:33:59 1990
+***************
+*** 22,29 ****
+ ..
+ . \" EN - end of a displayed equation
+ .de EN
+! .if !\\*(10 .br
+ .di
+ .rm EZ
+ .nr ZN \\n(dn
+ .if \\n(ZN>0 .if \\n(YE=0 .LP
+--- 22,30 ----
+ ..
+ . \" EN - end of a displayed equation
+ .de EN
+! .if \\n(.k>0 .br
+ .di
++ .ds 10 \\*(EZ\\
+ .rm EZ
+ .nr ZN \\n(dn
+ .if \\n(ZN>0 .if \\n(YE=0 .LP
+
+
+* gpic doesn't accept the syntax `chop N M' for chopping both ends of a
+line.
+
+The correct syntax is `chop N chop M'.
+
+* With gpic -t, when I print `line ->; box' using a dvi to ps
+program, the arrow head sticks through into the inside of the box.
+
+The dvi to ps program should be modified to set the line cap and
+line join parameters to 1 while printing tpic specials.
+
+* When I print the output groff -Tps, the output is always shifted up
+by about 0.7 inches; I'm using 8.5x11 inch paper.
+
+Make sure that PAGE is defined to be `letter' in the top-level
+Makefile.
+
+* When I try to print the output of groff -Tps, I get no output at all
+from the printer, and the log file shows the error
+%%[ error: undefined; offendingcommand: BP ]%%
+I using TranScript spooling software.
+
+This is a bug in the page reversal filter in early versions of
+TranScript. Change the `broken' parameter in
+/usr/local/lib/groff/font/devps/DESC to 7.
+
+* When I preview groff -Tps output using the Sun OpenWindows 2.0 pageview
+program, all the pages are displayed on top of each other.
+
+This is a defect in pageview. Change the `broken' parameter in
+/usr/local/lib/groff/font/devps/DESC to 2.
+
+* With groff -TX75, -TX100or -X, I can only view the first page.
+
+The left mouse button brings up a menu that allows you to view other
+pages.
+
+* When I print the output of groff -Tdvi, I just get a black dot in
+upper left corner.
+
+Some dvi drivers (notably early versions of xtex) do not correctly
+handle dvi files that use a resolution different from that used by dvi
+files produced by TeX. Try getting a more up to date driver.
+
+* I get lots of errors when I use groff with the AT&T -mm macros.
+
+The AT&T -mm macros need a few changes to work with groff; `make
+install.dwbmm' will copy your -mm macros to groff's macro directory
+and make the necessary changes. You may need to edit the commands for
+the install.mm target in the Makefile. Alternatively use the groff
+-mm macros.
+
+* gtroff doesn't understand lines like `.ce99' with no space between
+the name of the request or macro and the arguments.
+
+Gtroff requires a space between macro or request and its arguments
+because it allows the use of long names for macros and requests. You
+can use the -C option or the `cp' request to put gtroff into a
+compatibility mode in which it is not possible to use long names for
+macros but in which no space is required between macros and their
+arguments. The use of compatibility mode is strongly discouraged.
+
+* gtroff gives warnings about lines like
+ .ev \" a comment
+(with a tab after the .ev).
+
+A tab character cannot be used as a substitute for a space character
+(except in one case: between a control character at the beginning of a
+line and the name of a macro or request). For example, in Unix troff
+ .ps \" restore the previous point size
+(with a tab after the .ps) will NOT restore the previous point-size;
+instead it will be silently ignored. Since this is very likely to be
+an error, gtroff can give a warning about it. If you want to align
+comments, you can do it like this:
+ .ev\" \" a comment
+
+* I don't like the page headers and footers produced by groff -man.
+
+There seem to be many different styles of page header and footer
+produced by different versions of the -man macros. You will need to
+modify macros/tmac.an to suit your personal taste. For example, if
+you want the center of the page header to say
+ UNIX Programmer's Manual
+you will need to change the line
+ .el .ds an-extra3 \"UNIX Programmer's Manual
+to
+ .el .ds an-extra3 UNIX Programmer's Manual
+
+* While formatting a manual page, groff complains about not being able to
+break lines. The problem seems to be caused by a line like:
+ .TP \w'label'+2
+
+The -man documentation says that the default scale indicator for TP
+macro is `n'. The groff -man macros implement this correctly, so that
+the argument will be evaluated as if it were
+ \w'label'n+2n
+The Unix -man macros don't implement this correctly (probably because
+it's hard to do in Unix troff); they just append `n' to the entire
+argument, so that it will be evaluated as if it were
+ \w'label'u+2n
+The solution is to fix the manual page:
+ .TP \w'label'u+2
+
+* I'm having problems formatting Ultrix man pages with groff -man.
+
+The Ultrix man pages use a number of non-standard extensions to the
+Unix man macros. One solution is to use the Ultrix -man macros with
+groff. Rename /usr/local/lib/groff/tmac/tmac.an to
+/usr/local/lib/groff/tmac/tmac.an.gnu, copy /usr/lib/tmac/tmac.an to
+/usr/local/lib/groff/tmac/tmac.an and apply the following patch (from
+Frank Wortner):
+
+*** /usr/local/lib/groff/tmac/tmac.an Wed Sep 9 12:29:28 1992
+--- /usr/lib/tmac/tmac.an Fri Jul 24 19:58:19 1992
+***************
+*** 489,495 ****
+ . \" make special case of shift out of italic
+ .de }S
+ .ds ]F
+! .if \\$12 .if !\\$5 .ds ]F \^
+ .ie !\\$4 .}S \\$2 \\$1 "\\$3\f\\$1\\$4\\*(]F" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+ .el \\$3
+ .}f
+--- 489,495 ----
+ . \" make special case of shift out of italic
+ .de }S
+ .ds ]F
+! .if \\$12 .if !\\$5 .ds ]F\^
+ .ie !\\$4 .}S \\$2 \\$1 "\\$3\f\\$1\\$4\\*(]F" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+ .el \\$3
+ .}f
+
+Another possible solution is to install tmac/man.ultrix as
+/usr/local/lib/groff/tmac/man.local.
+
+* I'm having problems formatting HP-UX 9.0 man pages with groff -man.
+
+Rename /usr/local/lib/groff/tmac/tmac.an to (for example)
+/usr/local/lib/groff/tmac/tmac.gan, copy HP's tmac.an into
+/usr/local/lib/groff/tmac/tmac.an, and either put `.cp 1' at the
+beginning or filter it (and any files it .so's) through
+tmac/fixmacros.sed.
+
+* I'm having problems formatting man pages produced by the perl
+wrapman script.
+
+Some versions of wrapman have a superfluous blank line before the .TH
+line. This must be deleted. Then either use groff -C, or apply the
+following patch:
+
+*** wrapman.~2~ Sun Jan 19 12:10:24 1992
+--- wrapman Fri Apr 2 12:12:57 1993
+***************
+*** 35,41 ****
+ $line1 .= <IN> if $line1 =~ /eval/;
+ $line1 .= <IN> if $line1 =~ /argv/;
+ $line2 = <IN>;
+! next if $line2 eq "'di';\n";
+
+ # Pull the old switcheroo.
+
+--- 35,41 ----
+ $line1 .= <IN> if $line1 =~ /eval/;
+ $line1 .= <IN> if $line1 =~ /argv/;
+ $line2 = <IN>;
+! next if $line2 eq "'di ';\n";
+
+ # Pull the old switcheroo.
+
+***************
+*** 49,56 ****
+
+ print OUT $line1;
+ print OUT <<EOF;
+! 'di';
+! 'ig00';
+ #
+ # $header
+ #
+--- 49,57 ----
+
+ print OUT $line1;
+ print OUT <<EOF;
+! 'di ';
+! 'ds 00 \\"';
+! 'ig 00 ';
+ #
+ # $header
+ #
+***************
+*** 72,85 ****
+
+ # These next few lines are legal in both Perl and nroff.
+
+! $null.00; # finish .ig
+
+ 'di \\" finish diversion--previous line must be blank
+ .nr nl 0-1 \\" fake up transition to first page again
+ .nr % 0 \\" start at page 1
+! '; __END__ ##### From here on it's a standard manual page #####
+ .TH $PROG 1 "$month $mday, 19$year"
+- .AT 3
+ .SH NAME
+ $prog \\- whatever
+ .SH SYNOPSIS
+--- 73,85 ----
+
+ # These next few lines are legal in both Perl and nroff.
+
+! $null.00 ; # finish .ig
+
+ 'di \\" finish diversion--previous line must be blank
+ .nr nl 0-1 \\" fake up transition to first page again
+ .nr % 0 \\" start at page 1
+! .\\"'; __END__ ##### From here on it's a standard manual page #####
+ .TH $PROG 1 "$month $mday, 19$year"
+ .SH NAME
+ $prog \\- whatever
+ .SH SYNOPSIS
+
+
+* When I preview documents using -TX75 or -TX100, the layout is not the same
+as when I print the document with -Tps: the line and page breaks come
+in different places.
+
+Use groff -X -Tps.
+
+* When I try to run gxditview, I get the error:
+Error: Widget viewport has zero width and/or height
+
+This error means you haven't correctly installed the application
+defaults file, GXditview.ad; ``make install'' does this for you
+automatically, so either you didn't do ``make install'', or you don't
+have imake configured correctly.
+
+* groff uses up an enormous amount of memory processing large files.
+I'm using 386BSD 0.1.
+
+386BSD includes an old version of g++, 1.39, which has a bug that
+causes a major memory leak in gtroff. Apply the following fix to g++
+and recompile groff:
+
+*** cplus-decl.c.~1~ Mon Aug 6 05:28:59 1990
+--- cplus-decl.c Wed Jun 5 08:55:04 1991
+***************
+*** 7951,7961 ****
+
+ /* At the end, call delete if that's what's requested. */
+ if (TREE_GETS_DELETE (current_class_type))
+ exprstmt = build_method_call (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), error_mark_node),
+ get_identifier (OPERATOR_DELETE_FORMAT),
+! build_tree_list (NULL_TREE, integer_zero_node),
+ NULL_TREE, LOOKUP_NORMAL);
+ else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0);
+ else
+ exprstmt = 0;
+--- 7951,7961 ----
+
+ /* At the end, call delete if that's what's requested. */
+ if (TREE_GETS_DELETE (current_class_type))
+ exprstmt = build_method_call (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), error_mark_node),
+ get_identifier (OPERATOR_DELETE_FORMAT),
+! build_tree_list (NULL_TREE, current_class_decl),
+ NULL_TREE, LOOKUP_NORMAL);
+ else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0);
+ else
+ exprstmt = 0;
diff --git a/gnu/usr.bin/groff/PROJECTS b/gnu/usr.bin/groff/PROJECTS
new file mode 100644
index 000000000000..2b6e6684aa54
--- /dev/null
+++ b/gnu/usr.bin/groff/PROJECTS
@@ -0,0 +1,19 @@
+Here are some things that would be useful additions to groff:
+
+ a driver for the HP Laserjet 2 and 3
+
+ grap
+
+ -mv macros (for typesetting viewgraphs and slides)
+
+ a deroff that understands long names
+
+ a page-makeup postprocessor and associated macro package
+ (like pm and -mpm)
+
+ a complete, self-contained manual
+
+If you want to work on one of these, I suggest you contact me first.
+
+James Clark
+jjc@jclark.com
diff --git a/gnu/usr.bin/groff/README.gnu b/gnu/usr.bin/groff/README.gnu
new file mode 100644
index 000000000000..a8982c20ef2e
--- /dev/null
+++ b/gnu/usr.bin/groff/README.gnu
@@ -0,0 +1,38 @@
+This is the GNU groff document formatting system. The version number
+is given in the file VERSION.
+
+Included in this release are implementations of troff, pic, eqn, tbl,
+refer, the -man macros and the -ms macros, and drivers for PostScript,
+TeX dvi format, and typewriter-like devices. Also included is a
+modified version of the Berkeley -me macros, an enhanced version of
+the X11 xditview previewer, and an implementation of the -mm macros
+contributed by Joergen Haegg (jh@efd.lth.se).
+
+See the file INSTALL for installation instructions. You will require
+a C++ compiler.
+
+The file NEWS describes recent user-visible changes to groff.
+
+Groff is free software. See the file COPYING for copying permission.
+
+The file PROBLEMS describes various problems that have been
+encountered in compiling, installing, and running groff.
+
+For the moment, the documentation assumes that you are already
+familiar with the Unix versions of troff, -man, -ms and the
+preprocessors.
+
+The most recent released version of groff is always available by
+anonymous ftp from prep.ai.mit.edu in the directory pub/gnu.
+
+Please report bugs using the form in the file BUG-REPORT; the idea of
+this is to make sure that I have all the information I need to fix the
+bug. At the very least, read the BUG-REPORT form and make sure that
+you supply all the information that it asks for. Even if you are not
+sure that something is a bug, report it using BUG-REPORT: this will
+enable me to determine whether it really is a bug or not. As well as
+bug reports, I welcome suggestions for improvements to groff (no
+matter how small).
+
+James Clark
+jjc@jclark.com
diff --git a/gnu/usr.bin/groff/TODO b/gnu/usr.bin/groff/TODO
new file mode 100644
index 000000000000..0adedbc98291
--- /dev/null
+++ b/gnu/usr.bin/groff/TODO
@@ -0,0 +1,24 @@
+Provide man.sun implementing .TX.
+
+Improve GROFF_PRINT macro in acgroff.m4.
+
+Guess value for `g' variable.
+
+Guess appropriate value for tmac_m and tmac_s
+(if /usr/lib/tmac/tmac.s or /usr/local/lib/groff/tmac/tmac.s exists
+and is not the groff -ms macros then install as -mgs else install as -ms).
+
+Put all dev* files in a separate subdirectory `font'.
+
+Provide a `check' target.
+
+Provide a `bindist' target.
+
+Implement tmac.bib in terms of tmac.s.
+
+Support long options using GNU getopt.
+
+Catch the following error in -me:
+.(z
+.(l C
+.)z
diff --git a/gnu/usr.bin/groff/VERSION b/gnu/usr.bin/groff/VERSION
new file mode 100644
index 000000000000..986607cab0b6
--- /dev/null
+++ b/gnu/usr.bin/groff/VERSION
@@ -0,0 +1 @@
+1.08
diff --git a/gnu/usr.bin/groff/addftinfo/Makefile b/gnu/usr.bin/groff/addftinfo/Makefile
new file mode 100644
index 000000000000..d587fd22c60e
--- /dev/null
+++ b/gnu/usr.bin/groff/addftinfo/Makefile
@@ -0,0 +1,12 @@
+# Makefile for addftinfo
+
+PROG= addftinfo
+SRCS= addftinfo.cc guess.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF)
+DPADD+= $(LIBGROFF)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/addftinfo/addftinfo.1 b/gnu/usr.bin/groff/addftinfo/addftinfo.1
new file mode 100644
index 000000000000..9f3eaaee6e24
--- /dev/null
+++ b/gnu/usr.bin/groff/addftinfo/addftinfo.1
@@ -0,0 +1,85 @@
+.\" -*- nroff -*-
+.TH ADDFTINFO 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+addftinfo \- add information to troff font files for use with groff
+.SH SYNOPSIS
+.B addftinfo
+[
+.BI \- param\ value\fR.\|.\|.
+]
+.I res
+.I unitwidth
+.I font
+.SH DESCRIPTION
+.B addftinfo
+reads a troff font file
+and adds some additional font-metric information
+that is used by the groff system.
+The font file with the information added is written on the
+standard output.
+The information added is guessed using
+some parametric information about the font
+and assumptions
+about the traditional troff names for characters.
+The main information added is the heights and depths of characters.
+The
+.I res
+and
+.I unitwidth
+arguments should be the same as the corresponding parameters
+in the DESC file;
+.I font
+is the name of the file describing the font;
+if
+.I font
+ends with
+.B I
+the font will be assumed to be italic.
+.SH OPTIONS
+Each of the options changes one of the parameters that is used
+to derive the heights and depths.
+Like the existing quantities in the font
+file, each
+.I value
+is in
+.RI inches/ res
+for a font whose point size is
+.IR unitwidth .
+.I param
+must be one of:
+.TP
+.B x-height
+The height of lowercase letters without ascenders such as x.
+.TP
+.B fig-height
+The height of figures (digits).
+.TP
+.B asc-height
+The height of characters with ascenders, such as b, d or l.
+.TP
+.B body-height
+The height of characters such as parentheses.
+.TP
+.B cap-height
+The height of uppercase letters such as A.
+.TP
+.B comma-depth
+The depth of a comma.
+.TP
+.B desc-depth
+The depth of characters with descenders, such as p,q, or y.
+.TP
+.B body-depth
+The depth of characters such as parentheses.
+.LP
+.B addftinfo
+makes no attempt to use the specified parameters to guess
+the unspecified parameters.
+If a parameter is not specified the default will be used.
+The defaults are chosen to have the reasonable values for
+a Times font.
+.SH "SEE ALSO"
+.BR font (5)
+.BR groff_font (5),
+.BR groff (1),
+.BR groff_char (7)
diff --git a/gnu/usr.bin/groff/addftinfo/addftinfo.cc b/gnu/usr.bin/groff/addftinfo/addftinfo.cc
new file mode 100644
index 000000000000..e6d96695c8a7
--- /dev/null
+++ b/gnu/usr.bin/groff/addftinfo/addftinfo.cc
@@ -0,0 +1,194 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "guess.h"
+
+static void usage();
+static void convert_font(const font_params &, FILE *, FILE *);
+
+typedef font_params::*param_t;
+
+static struct {
+ const char *name;
+ param_t par;
+} param_table[] = {
+ "x-height", &font_params::x_height,
+ "fig-height", &font_params::fig_height,
+ "asc-height", &font_params::asc_height,
+ "body-height", &font_params::body_height,
+ "cap-height", &font_params::cap_height,
+ "comma-depth", &font_params::comma_depth,
+ "desc-depth", &font_params::desc_depth,
+ "body-depth", &font_params::body_depth,
+};
+
+// These are all in thousandths of an em.
+// These values are correct for PostScript Times Roman.
+
+#define DEFAULT_X_HEIGHT 448
+#define DEFAULT_FIG_HEIGHT 676
+#define DEFAULT_ASC_HEIGHT 682
+#define DEFAULT_BODY_HEIGHT 676
+#define DEFAULT_CAP_HEIGHT 662
+#define DEFAULT_COMMA_DEPTH 143
+#define DEFAULT_DESC_DEPTH 217
+#define DEFAULT_BODY_DEPTH 177
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ if (argc < 4)
+ usage();
+ int resolution;
+ if (sscanf(argv[argc-3], "%d", &resolution) != 1)
+ usage();
+ if (resolution <= 0)
+ fatal("resolution must be > 0");
+ int unitwidth;
+ if (sscanf(argv[argc-2], "%d", &unitwidth) != 1)
+ usage();
+ if (unitwidth <= 0)
+ fatal("unitwidth must be > 0");
+ font_params param;
+ const char *font = argv[argc-1];
+ param.italic = (font[0] != '\0' && strchr(font, '\0')[-1] == 'I');
+ param.em = (resolution*unitwidth)/72;
+ param.x_height = DEFAULT_X_HEIGHT;
+ param.fig_height = DEFAULT_FIG_HEIGHT;
+ param.asc_height = DEFAULT_ASC_HEIGHT;
+ param.body_height = DEFAULT_BODY_HEIGHT;
+ param.cap_height = DEFAULT_CAP_HEIGHT;
+ param.comma_depth = DEFAULT_COMMA_DEPTH;
+ param.desc_depth = DEFAULT_DESC_DEPTH;
+ param.body_depth = DEFAULT_BODY_DEPTH;
+ for (int i = 1; i < argc && argv[i][0] == '-'; i++) {
+ if (argv[i][1] == '-' && argv[i][2] == '\0') {
+ i++;
+ break;
+ }
+ if (i + 1 >= argc)
+ usage();
+ for (int j = 0;; j++) {
+ if (j >= sizeof(param_table)/sizeof(param_table[0]))
+ fatal("parameter `%1' not recognized", argv[i] + 1);
+ if (strcmp(param_table[j].name, argv[i] + 1) == 0)
+ break;
+ }
+ if (sscanf(argv[i+1], "%d", &(param.*(param_table[j].par))) != 1)
+ fatal("invalid argument `%1'", argv[i+1]);
+ i++;
+ }
+ if (argc - i != 3)
+ usage();
+ errno = 0;
+ FILE *infp = fopen(font, "r");
+ if (infp == 0)
+ fatal("can't open `%1': %2", font, strerror(errno));
+ convert_font(param, infp, stdout);
+ exit(0);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-param value] ... resolution unitwidth font\n",
+ program_name);
+ exit(1);
+}
+
+static int get_line(FILE *fp, string *p)
+{
+ int c;
+ p->clear();
+ while ((c = getc(fp)) != EOF) {
+ *p += char(c);
+ if (c == '\n')
+ break;
+ }
+ return p->length() > 0;
+}
+
+static void convert_font(const font_params &param, FILE *infp, FILE *outfp)
+{
+ string s;
+ while (get_line(infp, &s)) {
+ put_string(s, outfp);
+ if (s.length() >= 8
+ && strncmp(&s[0], "charset", 7))
+ break;
+ }
+ while (get_line(infp, &s)) {
+ s += '\0';
+ string name;
+ const char *p = s.contents();
+ while (csspace(*p))
+ p++;
+ while (*p != '\0' && !csspace(*p))
+ name += *p++;
+ while (csspace(*p))
+ p++;
+ for (const char *q = s.contents(); q < p; q++)
+ putc(*q, outfp);
+ char *next;
+ char_metric metric;
+ metric.width = (int)strtol(p, &next, 10);
+ if (next != p) {
+ printf("%d", metric.width);
+ p = next;
+ metric.type = (int)strtol(p, &next, 10);
+ if (next != p) {
+ name += '\0';
+ guess(name.contents(), param, &metric);
+ if (metric.sk == 0) {
+ if (metric.left_ic == 0) {
+ if (metric.ic == 0) {
+ if (metric.depth == 0) {
+ if (metric.height != 0)
+ printf(",%d", metric.height);
+ }
+ else
+ printf(",%d,%d", metric.height, metric.depth);
+ }
+ else
+ printf(",%d,%d,%d", metric.height, metric.depth, metric.ic);
+ }
+ else
+ printf(",%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
+ metric.left_ic);
+ }
+ else
+ printf(",%d,%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
+ metric.left_ic, metric.sk);
+ }
+ }
+ fputs(p, outfp);
+ }
+}
+
diff --git a/gnu/usr.bin/groff/addftinfo/guess.cc b/gnu/usr.bin/groff/addftinfo/guess.cc
new file mode 100644
index 000000000000..44b5f914b16d
--- /dev/null
+++ b/gnu/usr.bin/groff/addftinfo/guess.cc
@@ -0,0 +1,490 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "guess.h"
+
+void guess(const char *s, const font_params &param, char_metric *metric)
+{
+ int &height = metric->height;
+ int &depth = metric->depth;
+
+ metric->ic = 0;
+ metric->left_ic = 0;
+ metric->sk = 0;
+ height = 0;
+ depth = 0;
+ if (s[0] == '\0' || (s[1] != '\0' && s[2] != '\0'))
+ goto do_default;
+#define HASH(c1, c2) (((unsigned char)(c1) << 8) | (unsigned char)(c2))
+ switch (HASH(s[0], s[1])) {
+ default:
+ do_default:
+ if (metric->type & 01)
+ depth = param.desc_depth;
+ if (metric->type & 02)
+ height = param.asc_height;
+ else
+ height = param.x_height;
+ break;
+ case HASH('\\', '|'):
+ case HASH('\\', '^'):
+ case HASH('\\', '&'):
+ // these have zero height and depth
+ break;
+ case HASH('f', 0):
+ height = param.asc_height;
+ if (param.italic)
+ depth = param.desc_depth;
+ break;
+ case HASH('a', 0):
+ case HASH('c', 0):
+ case HASH('e', 0):
+ case HASH('m', 0):
+ case HASH('n', 0):
+ case HASH('o', 0):
+ case HASH('r', 0):
+ case HASH('s', 0):
+ case HASH('u', 0):
+ case HASH('v', 0):
+ case HASH('w', 0):
+ case HASH('x', 0):
+ case HASH('z', 0):
+ height = param.x_height;
+ break;
+ case HASH('i', 0):
+ height = param.x_height;
+ break;
+ case HASH('b', 0):
+ case HASH('d', 0):
+ case HASH('h', 0):
+ case HASH('k', 0):
+ case HASH('l', 0):
+ case HASH('F', 'i'):
+ case HASH('F', 'l'):
+ case HASH('f', 'f'):
+ case HASH('f', 'i'):
+ case HASH('f', 'l'):
+ height = param.asc_height;
+ break;
+ case HASH('t', 0):
+ height = param.asc_height;
+ break;
+ case HASH('g', 0):
+ case HASH('p', 0):
+ case HASH('q', 0):
+ case HASH('y', 0):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('j', 0):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('A', 0):
+ case HASH('B', 0):
+ case HASH('C', 0):
+ case HASH('D', 0):
+ case HASH('E', 0):
+ case HASH('F', 0):
+ case HASH('G', 0):
+ case HASH('H', 0):
+ case HASH('I', 0):
+ case HASH('J', 0):
+ case HASH('K', 0):
+ case HASH('L', 0):
+ case HASH('M', 0):
+ case HASH('N', 0):
+ case HASH('O', 0):
+ case HASH('P', 0):
+ case HASH('Q', 0):
+ case HASH('R', 0):
+ case HASH('S', 0):
+ case HASH('T', 0):
+ case HASH('U', 0):
+ case HASH('V', 0):
+ case HASH('W', 0):
+ case HASH('X', 0):
+ case HASH('Y', 0):
+ case HASH('Z', 0):
+ height = param.cap_height;
+ break;
+ case HASH('*', 'A'):
+ case HASH('*', 'B'):
+ case HASH('*', 'C'):
+ case HASH('*', 'D'):
+ case HASH('*', 'E'):
+ case HASH('*', 'F'):
+ case HASH('*', 'G'):
+ case HASH('*', 'H'):
+ case HASH('*', 'I'):
+ case HASH('*', 'K'):
+ case HASH('*', 'L'):
+ case HASH('*', 'M'):
+ case HASH('*', 'N'):
+ case HASH('*', 'O'):
+ case HASH('*', 'P'):
+ case HASH('*', 'Q'):
+ case HASH('*', 'R'):
+ case HASH('*', 'S'):
+ case HASH('*', 'T'):
+ case HASH('*', 'U'):
+ case HASH('*', 'W'):
+ case HASH('*', 'X'):
+ case HASH('*', 'Y'):
+ case HASH('*', 'Z'):
+ height = param.cap_height;
+ break;
+ case HASH('0', 0):
+ case HASH('1', 0):
+ case HASH('2', 0):
+ case HASH('3', 0):
+ case HASH('4', 0):
+ case HASH('5', 0):
+ case HASH('6', 0):
+ case HASH('7', 0):
+ case HASH('8', 0):
+ case HASH('9', 0):
+ case HASH('1', '2'):
+ case HASH('1', '4'):
+ case HASH('3', '4'):
+ height = param.fig_height;
+ break;
+ case HASH('(', 0):
+ case HASH(')', 0):
+ case HASH('[', 0):
+ case HASH(']', 0):
+ case HASH('{', 0):
+ case HASH('}', 0):
+ height = param.body_height;
+ depth = param.body_depth;
+ break;
+ case HASH('i', 's'):
+ height = (param.em*3)/4;
+ depth = param.em/4;
+ break;
+ case HASH('*', 'a'):
+ case HASH('*', 'e'):
+ case HASH('*', 'i'):
+ case HASH('*', 'k'):
+ case HASH('*', 'n'):
+ case HASH('*', 'o'):
+ case HASH('*', 'p'):
+ case HASH('*', 's'):
+ case HASH('*', 't'):
+ case HASH('*', 'u'):
+ case HASH('*', 'w'):
+ height = param.x_height;
+ break;
+ case HASH('*', 'd'):
+ case HASH('*', 'l'):
+ height = param.asc_height;
+ break;
+ case HASH('*', 'g'):
+ case HASH('*', 'h'):
+ case HASH('*', 'm'):
+ case HASH('*', 'r'):
+ case HASH('*', 'x'):
+ case HASH('*', 'y'):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('*', 'b'):
+ case HASH('*', 'c'):
+ case HASH('*', 'f'):
+ case HASH('*', 'q'):
+ case HASH('*', 'z'):
+ height = param.asc_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('t', 's'):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('!', 0):
+ case HASH('?', 0):
+ case HASH('"', 0):
+ case HASH('#', 0):
+ case HASH('$', 0):
+ case HASH('%', 0):
+ case HASH('&', 0):
+ case HASH('*', 0):
+ case HASH('+', 0):
+ height = param.asc_height;
+ break;
+ case HASH('`', 0):
+ case HASH('\'', 0):
+ height = param.asc_height;
+ break;
+ case HASH('~', 0):
+ case HASH('^', 0):
+ case HASH('a', 'a'):
+ case HASH('g', 'a'):
+ height = param.asc_height;
+ break;
+ case HASH('r', 'u'):
+ case HASH('.', 0):
+ break;
+ case HASH(',', 0):
+ depth = param.comma_depth;
+ break;
+ case HASH('m', 'i'):
+ case HASH('-', 0):
+ case HASH('h', 'y'):
+ case HASH('e', 'm'):
+ height = param.x_height;
+ break;
+ case HASH(':', 0):
+ height = param.x_height;
+ break;
+ case HASH(';', 0):
+ height = param.x_height;
+ depth = param.comma_depth;
+ break;
+ case HASH('=', 0):
+ case HASH('e', 'q'):
+ height = param.x_height;
+ break;
+ case HASH('<', 0):
+ case HASH('>', 0):
+ case HASH('>', '='):
+ case HASH('<', '='):
+ case HASH('@', 0):
+ case HASH('/', 0):
+ case HASH('|', 0):
+ case HASH('\\', 0):
+ height = param.asc_height;
+ break;
+ case HASH('_', 0):
+ case HASH('u', 'l'):
+ case HASH('\\', '_'):
+ depth = param.em/4;
+ break;
+ case HASH('r', 'n'):
+ height = (param.em*3)/4;
+ break;
+ case HASH('s', 'r'):
+ height = (param.em*3)/4;
+ depth = param.em/4;
+ break;
+ case HASH('b', 'u'):
+ case HASH('s', 'q'):
+ case HASH('d', 'e'):
+ case HASH('d', 'g'):
+ case HASH('f', 'm'):
+ case HASH('c', 't'):
+ case HASH('r', 'g'):
+ case HASH('c', 'o'):
+ case HASH('p', 'l'):
+ case HASH('*', '*'):
+ case HASH('s', 'c'):
+ case HASH('s', 'l'):
+ case HASH('=', '='):
+ case HASH('~', '='):
+ case HASH('a', 'p'):
+ case HASH('!', '='):
+ case HASH('-', '>'):
+ case HASH('<', '-'):
+ case HASH('u', 'a'):
+ case HASH('d', 'a'):
+ case HASH('m', 'u'):
+ case HASH('d', 'i'):
+ case HASH('+', '-'):
+ case HASH('c', 'u'):
+ case HASH('c', 'a'):
+ case HASH('s', 'b'):
+ case HASH('s', 'p'):
+ case HASH('i', 'b'):
+ case HASH('i', 'p'):
+ case HASH('i', 'f'):
+ case HASH('p', 'd'):
+ case HASH('g', 'r'):
+ case HASH('n', 'o'):
+ case HASH('p', 't'):
+ case HASH('e', 's'):
+ case HASH('m', 'o'):
+ case HASH('b', 'r'):
+ case HASH('d', 'd'):
+ case HASH('r', 'h'):
+ case HASH('l', 'h'):
+ case HASH('o', 'r'):
+ case HASH('c', 'i'):
+ height = param.asc_height;
+ break;
+ case HASH('l', 't'):
+ case HASH('l', 'b'):
+ case HASH('r', 't'):
+ case HASH('r', 'b'):
+ case HASH('l', 'k'):
+ case HASH('r', 'k'):
+ case HASH('b', 'v'):
+ case HASH('l', 'f'):
+ case HASH('r', 'f'):
+ case HASH('l', 'c'):
+ case HASH('r', 'c'):
+ height = (param.em*3)/4;
+ depth = param.em/4;
+ break;
+#if 0
+ case HASH('%', '0'):
+ case HASH('-', '+'):
+ case HASH('-', 'D'):
+ case HASH('-', 'd'):
+ case HASH('-', 'd'):
+ case HASH('-', 'h'):
+ case HASH('.', 'i'):
+ case HASH('.', 'j'):
+ case HASH('/', 'L'):
+ case HASH('/', 'O'):
+ case HASH('/', 'l'):
+ case HASH('/', 'o'):
+ case HASH('=', '~'):
+ case HASH('A', 'E'):
+ case HASH('A', 'h'):
+ case HASH('A', 'N'):
+ case HASH('C', 's'):
+ case HASH('D', 'o'):
+ case HASH('F', 'c'):
+ case HASH('F', 'o'):
+ case HASH('I', 'J'):
+ case HASH('I', 'm'):
+ case HASH('O', 'E'):
+ case HASH('O', 'f'):
+ case HASH('O', 'K'):
+ case HASH('O', 'm'):
+ case HASH('O', 'R'):
+ case HASH('P', 'o'):
+ case HASH('R', 'e'):
+ case HASH('S', '1'):
+ case HASH('S', '2'):
+ case HASH('S', '3'):
+ case HASH('T', 'P'):
+ case HASH('T', 'p'):
+ case HASH('Y', 'e'):
+ case HASH('\\', '-'):
+ case HASH('a', '"'):
+ case HASH('a', '-'):
+ case HASH('a', '.'):
+ case HASH('a', '^'):
+ case HASH('a', 'b'):
+ case HASH('a', 'c'):
+ case HASH('a', 'd'):
+ case HASH('a', 'e'):
+ case HASH('a', 'h'):
+ case HASH('a', 'o'):
+ case HASH('a', 't'):
+ case HASH('a', '~'):
+ case HASH('b', 'a'):
+ case HASH('b', 'b'):
+ case HASH('b', 's'):
+ case HASH('c', '*'):
+ case HASH('c', '+'):
+ case HASH('f', '/'):
+ case HASH('f', 'a'):
+ case HASH('f', 'c'):
+ case HASH('f', 'o'):
+ case HASH('h', 'a'):
+ case HASH('h', 'o'):
+ case HASH('i', 'j'):
+ case HASH('l', 'A'):
+ case HASH('l', 'B'):
+ case HASH('l', 'C'):
+ case HASH('m', 'd'):
+ case HASH('n', 'c'):
+ case HASH('n', 'e'):
+ case HASH('n', 'm'):
+ case HASH('o', 'A'):
+ case HASH('o', 'a'):
+ case HASH('o', 'e'):
+ case HASH('o', 'q'):
+ case HASH('p', 'l'):
+ case HASH('p', 'p'):
+ case HASH('p', 's'):
+ case HASH('r', '!'):
+ case HASH('r', '?'):
+ case HASH('r', 'A'):
+ case HASH('r', 'B'):
+ case HASH('r', 'C'):
+ case HASH('r', 's'):
+ case HASH('s', 'h'):
+ case HASH('s', 's'):
+ case HASH('t', 'e'):
+ case HASH('t', 'f'):
+ case HASH('t', 'i'):
+ case HASH('t', 'm'):
+ case HASH('~', '~'):
+ case HASH('v', 'S'):
+ case HASH('v', 'Z'):
+ case HASH('v', 's'):
+ case HASH('v', 'z'):
+ case HASH('^', 'A'):
+ case HASH('^', 'E'):
+ case HASH('^', 'I'):
+ case HASH('^', 'O'):
+ case HASH('^', 'U'):
+ case HASH('^', 'a'):
+ case HASH('^', 'e'):
+ case HASH('^', 'i'):
+ case HASH('^', 'o'):
+ case HASH('^', 'u'):
+ case HASH('`', 'A'):
+ case HASH('`', 'E'):
+ case HASH('`', 'I'):
+ case HASH('`', 'O'):
+ case HASH('`', 'U'):
+ case HASH('`', 'a'):
+ case HASH('`', 'e'):
+ case HASH('`', 'i'):
+ case HASH('`', 'o'):
+ case HASH('`', 'u'):
+ case HASH('~', 'A'):
+ case HASH('~', 'N'):
+ case HASH('~', 'O'):
+ case HASH('~', 'a'):
+ case HASH('~', 'n'):
+ case HASH('~', 'o'):
+ case HASH('\'', 'A'):
+ case HASH('\'', 'C'):
+ case HASH('\'', 'E'):
+ case HASH('\'', 'I'):
+ case HASH('\'', 'O'):
+ case HASH('\'', 'U'):
+ case HASH('\'', 'a'):
+ case HASH('\'', 'c'):
+ case HASH('\'', 'e'):
+ case HASH('\'', 'i'):
+ case HASH('\'', 'o'):
+ case HASH('\'', 'u')
+ case HASH(':', 'A'):
+ case HASH(':', 'E'):
+ case HASH(':', 'I'):
+ case HASH(':', 'O'):
+ case HASH(':', 'U'):
+ case HASH(':', 'Y'):
+ case HASH(':', 'a'):
+ case HASH(':', 'e'):
+ case HASH(':', 'i'):
+ case HASH(':', 'o'):
+ case HASH(':', 'u'):
+ case HASH(':', 'y'):
+ case HASH(',', 'C'):
+ case HASH(',', 'c'):
+#endif
+ }
+}
diff --git a/gnu/usr.bin/groff/addftinfo/guess.h b/gnu/usr.bin/groff/addftinfo/guess.h
new file mode 100644
index 000000000000..6712045e1327
--- /dev/null
+++ b/gnu/usr.bin/groff/addftinfo/guess.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct font_params {
+ int italic;
+ int em;
+ int x_height;
+ int fig_height;
+ int cap_height;
+ int asc_height;
+ int body_height;
+ int comma_depth;
+ int desc_depth;
+ int body_depth;
+};
+
+struct char_metric {
+ int width;
+ int type;
+ int height;
+ int depth;
+ int ic;
+ int left_ic;
+ int sk;
+};
+
+void guess(const char *s, const font_params &param, char_metric *metric);
diff --git a/gnu/usr.bin/groff/afmtodit/Makefile b/gnu/usr.bin/groff/afmtodit/Makefile
new file mode 100644
index 000000000000..3678700de227
--- /dev/null
+++ b/gnu/usr.bin/groff/afmtodit/Makefile
@@ -0,0 +1,9 @@
+MAN1= afmtodit.1
+
+afterinstall:
+ install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ $(.CURDIR)/afmtodit.pl $(DESTDIR)$(BINDIR)/afmtodit
+
+.include <../../../usr.bin/Makefile.inc>
+.include <../Makefile.cfg>
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/afmtodit/afmtodit.1 b/gnu/usr.bin/groff/afmtodit/afmtodit.1
new file mode 100644
index 000000000000..343a665f3470
--- /dev/null
+++ b/gnu/usr.bin/groff/afmtodit/afmtodit.1
@@ -0,0 +1,204 @@
+.\" -*- nroff -*-
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH AFMTODIT 1 "23 February 1993" "Groff Version 1.08"
+.SH NAME
+afmtodit \- create font files for use with groff \-Tps
+.SH SYNOPSIS
+.B afmtodit
+[
+.B \-ns
+]
+[
+.BI \-d desc_file
+]
+[
+.BI \-e enc_file
+]
+[
+.BI \-i n
+]
+[
+.BI \-a n
+]
+.I afm_file
+.I map_file
+.I font
+.SH DESCRIPTION
+.B afmtodit
+creates a font file for use with groff and
+.BR grops .
+.B afmtodit
+is written in perl;
+you must have perl version 3 installed in order to run
+.BR afmtodit .
+.I afm_file
+is the AFM (Adobe Font Metric) file for the font.
+.I map_file
+is a file that says which groff character names map onto
+each PostScript character name;
+this file should contain a sequence of lines of the form
+.IP
+.I
+ps_char groff_char
+.LP
+where
+.I ps_char
+is the PostScript name of the character
+and
+.I groff_char
+is the groff name of the character (as used in the groff font file.)
+The same
+.I ps_char
+can occur multiple times in the file;
+each
+.I groff_char
+must occur at most once.
+.I font
+is the groff name of the font.
+If a PostScript character is in the encoding to be used for the font
+but is not mentioned in
+.I map_file
+then
+.B afmtodit
+will put it in the groff font file as an unnamed character,
+which can be accessed by the
+.B \eN
+escape sequence in
+.BR troff .
+The groff font file will be output to a file called
+.IR font .
+.LP
+If there is a downloadable font file for the font, it may be listed in
+the file
+.BR /usr/share/groff_font/devps/download ;
+see
+.BR grops (1).
+.LP
+If the
+.B \-i
+option is used,
+.B afmtodit
+will automatically generate an italic correction,
+a left italic correction and a subscript correction
+for each character
+(the significance of these parameters is explained in
+.BR groff_font (5));
+these parameters may be specified for individual characters by
+adding to the
+.I afm_file
+lines of the form:
+.IP
+.BI italicCorrection\ ps_char\ n
+.br
+.BI leftItalicCorrection\ ps_char\ n
+.br
+.BI subscriptCorrection\ ps_char\ n
+.LP
+where
+.I ps_char
+is the PostScript name of the character,
+and
+.I n
+is the desired value of the corresponding parameter in thousandths of an em.
+These parameters are normally needed only for italic (or oblique) fonts.
+.SH OPTIONS
+.TP
+.B \-n
+Don't output a
+.B ligatures
+command for this font.
+Use this with constant-width fonts.
+.TP
+.B \-s
+The font is special.
+The effect of this option is to add the
+.B special
+command to the font file.
+.TP
+.BI \-d desc_file
+The device description file is
+.I desc_file
+rather than the default
+.BR DESC .
+.TP
+.BI \-e enc_file
+The PostScript font should be reencoded to use the encoding described
+in enc_file.
+The format of
+.I enc_file
+is described in
+.BR grops (1).
+.TP
+.BI \-a n
+Use
+.I n
+as the slant parameter in the font file;
+this is used by groff in the positioning of accents.
+By default
+.B afmtodit
+uses the negative of the ItalicAngle specified in the afm file;
+with true italic fonts it is sometimes desirable to use
+a slant that is less than this.
+If you find that characters from an italic font have accents
+placed too far to the right over them,
+then use the
+.B \-a
+option to give the font a smaller slant.
+.TP
+.BI \-i n
+Generate an italic correction for each character so that
+the character's width plus the character's italic correction
+is equal to
+.I n
+thousandths of an em
+plus the amount by which the right edge of the character's bounding
+is to the right of the character's origin.
+If this would result in a negative italic correction, use a zero
+italic correction instead.
+.IP
+Also generate a subscript correction equal to the
+product of the tangent of the slant of the font and
+four fifths of the x-height of the font.
+If this would result in a subscript correction greater than the italic
+correction, use a subscript correction equal to the italic correction
+instead.
+.IP
+Also generate a left italic correction for each character
+equal to
+.I n
+thousandths of an em
+plus the amount by which the left edge of the character's bounding box
+is to the left of the character's origin.
+The left italic correction may be negative.
+.IP
+This option is normally needed only with italic (or oblique) fonts.
+The font files distributed with groff were created using an option of
+.B \-i50
+for italic fonts.
+.SH FILES
+.Tp \w'\fB/usr/share/groff_font/devps/download'u+2n
+.B /usr/share/groff_font/devps/DESC
+Device desciption file.
+.TP
+.BI /usr/share/groff_font/devps/ F
+Font description file for font
+.IR F .
+.TP
+.B /usr/share/groff_font/devps/download
+List of downloadable fonts.
+.TP
+.B /usr/share/groff_font/devps/text.enc
+Encoding used for text fonts.
+.TP
+.B /usr/share/groff_font/devps/generate/textmap
+Standard mapping.
+.SH "SEE ALSO"
+.BR groff (1),
+.BR grops (1),
+.BR groff_font (5),
+.BR perl (1)
diff --git a/gnu/usr.bin/groff/afmtodit/afmtodit.pl b/gnu/usr.bin/groff/afmtodit/afmtodit.pl
new file mode 100644
index 000000000000..1d1a24969703
--- /dev/null
+++ b/gnu/usr.bin/groff/afmtodit/afmtodit.pl
@@ -0,0 +1,325 @@
+#! /usr/bin/perl -P- # -*- Perl -*-
+#Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff is free software; you can redistribute 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.
+#
+#groff is distributed in the hope that it will be useful, but WITHOUT ANY
+#WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+#for more details.
+#
+#You should have received a copy of the GNU General Public License along
+#with groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$prog = $0;
+$prog =~ s@.*/@@;
+
+do 'getopts.pl';
+do Getopts('e:sd:i:a:n');
+
+if ($#ARGV != 2) {
+ die "Usage: $prog [-ns] [-d DESC] [-e encoding] [-i n] [-a angle] afmfile mapfile font\n";
+}
+
+$afm = $ARGV[0];
+$map = $ARGV[1];
+$font = $ARGV[2];
+$desc = $opt_d || "DESC";
+
+# read the afm file
+
+open(AFM, $afm) || die "$prog: can't open \`$ARGV[0]': $!\n";
+
+while (<AFM>) {
+ chop;
+ @field = split(' ');
+ if ($field[0] eq "FontName") {
+ $psname = $field[1];
+ }
+ elsif($field[0] eq "ItalicAngle") {
+ $italic_angle = -$field[1];
+ }
+ elsif ($field[0] eq "KPX") {
+ if ($#field == 3) {
+ push(kern1, $field[1]);
+ push(kern2, $field[2]);
+ push(kernx, $field[3]);
+ }
+ }
+ elsif ($field[0] eq "italicCorrection") {
+ $italic_correction{$field[1]} = $field[2];
+ }
+ elsif ($field[0] eq "leftItalicCorrection") {
+ $left_italic_correction{$field[1]} = $field[2];
+ }
+ elsif ($field[0] eq "subscriptCorrection") {
+ $subscript_correction{$field[1]} = $field[2];
+ }
+ elsif ($field[0] eq "StartCharMetrics") {
+ while (<AFM>) {
+ @field = split(' ');
+ last if ($field[0] eq "EndCharMetrics");
+ if ($field[0] eq "C") {
+ $c = -1;
+ $wx = 0;
+ $n = "";
+ $lly = 0;
+ $ury = 0;
+ $llx = 0;
+ $urx = 0;
+ $c = $field[1];
+ $i = 2;
+ while ($i <= $#field) {
+ if ($field[$i] eq "WX") {
+ $w = $field[$i + 1];
+ $i += 2;
+ }
+ elsif ($field[$i] eq "N") {
+ $n = $field[$i + 1];
+ $i += 2;
+ }
+ elsif ($field[$i] eq "B") {
+ $llx = $field[$i + 1];
+ $lly = $field[$i + 2];
+ $urx = $field[$i + 3];
+ $ury = $field[$i + 4];
+ $i += 5;
+ }
+ elsif ($field[$i] eq "L") {
+ push(ligatures, $field[$i + 2]);
+ $i += 3;
+ }
+ else {
+ while ($i <= $#field && $field[$i] ne ";") {
+ $i++;
+ }
+ $i++;
+ }
+ }
+ if (!$opt_e && $c != -1) {
+ $encoding[$c] = $n;
+ $in_encoding{$n} = 1;
+ }
+ $width{$n} = $w;
+ $height{$n} = $ury;
+ $depth{$n} = -$lly;
+ $left_side_bearing{$n} = -$llx;
+ $right_side_bearing{$n} = $urx - $w;
+ }
+ }
+ }
+}
+close(AFM);
+
+# read the DESC file
+
+$sizescale = 1;
+
+open(DESC, $desc) || die "$prog: can't open \`$desc': $!\n";
+while (<DESC>) {
+ next if /^#/;
+ chop;
+ @field = split(' ');
+ last if $field[0] eq "charset";
+ if ($field[0] eq "res") { $resolution = $field[1]; }
+ if ($field[0] eq "unitwidth") { $unitwidth = $field[1]; }
+ if ($field[0] eq "sizescale") { $sizescale = $field[1]; }
+}
+close(DESC);
+
+if ($opt_e) {
+ # read the encoding file
+
+ open(ENCODING, $opt_e) || die "$prog: can't open \`$opt_e': $!\n";
+ while (<ENCODING>) {
+ chop;
+ @field = split(' ');
+ if ($#field == 1) {
+ if ($field[1] >= 0 && defined $width{$field[0]}) {
+ $encoding[$field[1]] = $field[0];
+ $in_encoding{$field[0]} = 1;
+ }
+ }
+ }
+ close(ENCODING);
+}
+
+# read the map file
+
+open(MAP, $map) || die "$prog: can't open \`$map': $!\n";
+while (<MAP>) {
+ next if /^#/;
+ chop;
+ @field = split(' ');
+ if ($#field == 1 && $in_encoding{$field[0]}) {
+ if (defined $mapped{$field[1]}) {
+ warn "Both $mapped{$field[1]} and $field[0] map to $field[1]";
+ }
+ elsif ($field[1] eq "space") {
+ # the PostScript character `space' is automatically mapped
+ # to the groff character `space'; this is for grops
+ warn "you are not allowed to map to the groff character `space'";
+ }
+ elsif ($field[0] eq "space") {
+ warn "you are not allowed to map the PostScript character `space'";
+ }
+ else {
+ $nmap{$field[0]} += 0;
+ $map{$field[0],$nmap{$field[0]}} = $field[1];
+ $nmap{$field[0]} += 1;
+ $mapped{$field[1]} = $field[0];
+ }
+ }
+}
+close(MAP);
+
+$italic_angle = $opt_a if $opt_a;
+
+# print it all out
+
+open(FONT, ">$font") || die "$prog: can't open \`$font' for output: $!\n";
+select(FONT);
+
+print("name $font\n");
+print("internalname $psname\n") if $psname;
+print("special\n") if $opt_s;
+printf("slant %g\n", $italic_angle) if $italic_angle != 0;
+printf("spacewidth %d\n", do conv($width{"space"})) if defined $width{"space"};
+
+if ($opt_e) {
+ $e = $opt_e;
+ $e =~ s@.*/@@;
+ print("encoding $e\n");
+}
+
+if (!$opt_n && $#ligatures >= 0) {
+ print("ligatures");
+ foreach $lig (@ligatures) {
+ print(" $lig");
+ }
+ print(" 0\n");
+}
+
+if ($#kern1 >= 0) {
+ print("kernpairs\n");
+
+ for ($i = 0; $i <= $#kern1; $i++) {
+ $c1 = $kern1[$i];
+ $c2 = $kern2[$i];
+ if ($in_encoding{$c1} == 1 && $nmap{$c1} != 0
+ && $in_encoding{$c2} == 1 && $nmap{$c2} != 0) {
+ for ($j = 0; $j < $nmap{$c1}; $j++) {
+ for ($k = 0; $k < $nmap{$c2}; $k++) {
+ if ($kernx[$i] != 0) {
+ printf("%s %s %d\n",
+ $map{$c1,$j},
+ $map{$c2,$k},
+ do conv($kernx[$i]));
+ }
+ }
+ }
+ }
+ }
+}
+
+# characters not shorter than asc_boundary are considered to have ascenders
+$asc_boundary = $height{"t"} - 1;
+
+# likewise for descenders
+$desc_boundary = $depth{"g"};
+$desc_boundary = $depth{"j"} if $depth{"j"} < $desc_boundary;
+$desc_boundary = $depth{"p"} if $depth{"p"} < $desc_boundary;
+$desc_boundary = $depth{"q"} if $depth{"q"} < $desc_boundary;
+$desc_boundary = $depth{"y"} if $depth{"y"} < $desc_boundary;
+$desc_boundary -= 1;
+
+if (defined $height{"x"}) {
+ $xheight = $height{"x"};
+}
+elsif (defined $height{"alpha"}) {
+ $xheight = $height{"alpha"};
+}
+else {
+ $xheight = 450;
+}
+
+$italic_angle = $italic_angle*3.14159265358979323846/180.0;
+$slant = sin($italic_angle)/cos($italic_angle);
+$slant = 0 if $slant < 0;
+
+print("charset\n");
+for ($i = 0; $i < 256; $i++) {
+ $ch = $encoding[$i];
+ if ($ch ne "" && $ch ne "space") {
+ $map{$ch,"0"} = "---" if $nmap{$ch} == 0;
+ $type = 0;
+ $h = $height{$ch};
+ $h = 0 if $h < 0;
+ $d = $depth{$ch};
+ $d = 0 if $d < 0;
+ $type = 1 if $d >= $desc_boundary;
+ $type += 2 if $h >= $asc_boundary;
+ printf("%s\t%d", $map{$ch,"0"}, do conv($width{$ch}));
+ $italic_correction = 0;
+ $left_math_fit = 0;
+ $subscript_correction = 0;
+ if (defined $opt_i) {
+ $italic_correction = $right_side_bearing{$ch} + $opt_i;
+ $italic_correction = 0 if $italic_correction < 0;
+ $subscript_correction = $slant * $xheight * .8;
+ $subscript_correction = $italic_correction if
+ $subscript_correction > $italic_correction;
+ $left_math_fit = $left_side_bearing{$ch} + $opt_i;
+ }
+ if (defined $italic_correction{$ch}) {
+ $italic_correction = $italic_correction{$ch};
+ }
+ if (defined $left_italic_correction{$ch}) {
+ $left_math_fit = $left_italic_correction{$ch};
+ }
+ if (defined $subscript_correction{$ch}) {
+ $subscript_correction = $subscript_correction{$ch};
+ }
+ if ($subscript_correction != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ printf(",%d,%d,%d", do conv($italic_correction),
+ do conv($left_math_fit),
+ do conv($subscript_correction));
+ }
+ elsif ($left_math_fit != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ printf(",%d,%d", do conv($italic_correction),
+ do conv($left_math_fit));
+ }
+ elsif ($italic_correction != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ printf(",%d", do conv($italic_correction));
+ }
+ elsif ($d != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ }
+ else {
+ # always put the height in to stop groff guessing
+ printf(",%d", do conv($h));
+ }
+ printf("\t%d", $type);
+ printf("\t0%03o\t%s\n", $i, $ch);
+ for ($j = 1; $j < $nmap{$ch}; $j++) {
+ printf("%s\t\"\n", $map{$ch,$j});
+ }
+ }
+ if ($ch eq "space" && defined $width{"space"}) {
+ printf("space\t%d\t0\t0%03o\n", do conv($width{"space"}), $i);
+ }
+}
+
+sub conv {
+ $_[0]*$unitwidth*$resolution/(72*1000*$sizescale) + ($_[0] < 0 ? -.5 : .5);
+}
diff --git a/gnu/usr.bin/groff/devices/Makefile b/gnu/usr.bin/groff/devices/Makefile
new file mode 100644
index 000000000000..eb10a3478e35
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/Makefile
@@ -0,0 +1,10 @@
+# Makefile for groff devices
+
+SUBDIR= devascii devlatin1 devdvi devps \
+ devX100 devX100-12 devX75 devX75-12
+
+tags:
+
+depend:
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/devices/Makefile.dev b/gnu/usr.bin/groff/devices/Makefile.dev
new file mode 100644
index 000000000000..521b063da4e4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/Makefile.dev
@@ -0,0 +1,43 @@
+# @(#)Makefile.dev 6.2 (Berkeley) 3/16/91
+
+# Client Makefiles define DEVICE and FONTFILES and provide rules for
+# individual font files
+
+.include "../../Makefile.cfg"
+
+FONTDIR?= /usr/share/groff_font
+DEVICEDIR?= $(FONTDIR)/dev$(DEVICE)
+FONTOWN?= bin
+FONTGRP?= bin
+FONTMODE?= 444
+
+CLEANFILES+= $(FONTFILES)
+
+all: $(FONTFILES)
+
+.if !target(maninstall)
+maninstall:
+ @echo -n
+.endif
+
+.if !target(install)
+install:
+ -if test ! -d $(DESTDIR)$(DEVICEDIR); then \
+ mkdir $(DESTDIR)$(DEVICEDIR); \
+ chown $(BINOWN).$(BINGRP) $(DESTDIR)$(DEVICEDIR); \
+ chmod 755 $(DESTDIR)$(DEVICEDIR); \
+ fi
+ -if test -d $(.CURDIR)/generate; then \
+ if test ! -d $(DESTDIR)$(DEVICEDIR)/generate; then \
+ mkdir $(DESTDIR)$(DEVICEDIR)/generate; \
+ chown $(BINOWN).$(BINGRP) $(DESTDIR)$(DEVICEDIR)/generate; \
+ chmod 755 $(DESTDIR)$(DEVICEDIR)/generate; \
+ fi; \
+ fi
+ -for f in $(FONTFILES); do \
+ install -c -o $(FONTOWN) -g $(FONTGRP) -m $(FONTMODE) $$f \
+ $(DESTDIR)$(DEVICEDIR)/$$f; \
+ done
+.endif
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/devices/Makefile.tty b/gnu/usr.bin/groff/devices/Makefile.tty
new file mode 100644
index 000000000000..0c4b9ba02706
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/Makefile.tty
@@ -0,0 +1,52 @@
+# @(#)Makefile.tty 6.1 (Berkeley) 3/3/91
+#
+# Modified for Berkeley Unix by Donn Seeley, donn@okeeffe.berkeley.edu
+#
+#Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.uucp)
+#
+#This file is part of groff.
+#
+#groff is free software; you can redistribute it and/or modify it under
+#the terms of the GNU General Public License as published by the Free
+#Software Foundation; either version 1, or (at your option) any later
+#version.
+#
+#groff is distributed in the hope that it will be useful, but WITHOUT ANY
+#WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+#for more details.
+#
+#You should have received a copy of the GNU General Public License along
+#with groff; see the file LICENSE. If not, write to the Free Software
+#Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+.MAIN: all
+
+RES=240
+CPI=10
+LPI=6
+FONTS=R I B BI
+
+FONTFILES=$(FONTS) DESC
+
+$(FONTS): R.proto
+ @${ECHO} Making $@
+ @(charwidth=`echo $(RES) / $(CPI) | bc` ; \
+ sed -e "s/^name [A-Z]*$$/name $@/" \
+ -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" \
+ $(.CURDIR)/R.proto >$@)
+
+DESC: DESC.proto
+ @${ECHO} Making $@
+ @sed -e "s/^res .*$$/res $(RES)/" \
+ -e "s/^hor .*$$/hor `echo $(RES) / $(CPI) | bc`/" \
+ -e "s/^vert .*$$/vert `echo $(RES) / $(LPI) | bc`/" \
+ -e "s/^fonts .*$$/fonts `set $(FONTS); echo $$#` $(FONTS)/" \
+ $(.CURDIR)/DESC.proto >$@
diff --git a/gnu/usr.bin/groff/devices/devX100-12/CB b/gnu/usr.bin/groff/devices/devX100-12/CB
new file mode 100644
index 000000000000..3751184aadcc
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,11 0 052
++ 10,9 0 053
+, 10,2,3 0 054
+\- 10,6 0 055
+. 10,2 0 056
+/ 10,12,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,3 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,12,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,11 0 0142
+c 10,7 0 0143
+d 10,11 0 0144
+e 10,7 0 0145
+f 10,11 0 0146
+g 10,7,3 0 0147
+h 10,11 0 0150
+i 10,10 0 0151
+j 10,10,3 0 0152
+k 10,11 0 0153
+l 10,11 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,11,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,3 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,11,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 10,6 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,10 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,1,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,12 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,12 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/CBI b/gnu/usr.bin/groff/devices/devX100-12/CBI
new file mode 100644
index 000000000000..d7d0145a09a9
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,11 0 052
++ 10,9 0 053
+, 10,2,3 0 054
+\- 10,6 0 055
+. 10,2 0 056
+/ 10,12,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,3 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,12,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,11 0 0142
+c 10,7 0 0143
+d 10,11 0 0144
+e 10,7 0 0145
+f 10,11 0 0146
+g 10,7,3 0 0147
+h 10,11 0 0150
+i 10,10 0 0151
+j 10,10,3 0 0152
+k 10,11 0 0153
+l 10,11 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,11,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,4 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,11,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 10,6 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,9 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,10 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,0,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,4 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,10 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,11 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,12 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/CI b/gnu/usr.bin/groff/devices/devX100-12/CI
new file mode 100644
index 000000000000..804f71f779e6
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,10 0 052
++ 10,9 0 053
+, 10,2,2 0 054
+\- 10,5 0 055
+. 10,2 0 056
+/ 10,11,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,2 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,11,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,10 0 0142
+c 10,7 0 0143
+d 10,10 0 0144
+e 10,7 0 0145
+f 10,10 0 0146
+g 10,7,3 0 0147
+h 10,10 0 0150
+i 10,11 0 0151
+j 10,11,3 0 0152
+k 10,10 0 0153
+l 10,10 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,10,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,4 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,11,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 10,5 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,10 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,0,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,10 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,11 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/CR b/gnu/usr.bin/groff/devices/devX100-12/CR
new file mode 100644
index 000000000000..140ec55d0756
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,11 0 052
++ 10,9 0 053
+, 10,2,2 0 054
+\- 10,5 0 055
+. 10,2 0 056
+/ 10,11,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,2 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,11,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,10 0 0142
+c 10,7 0 0143
+d 10,10 0 0144
+e 10,7 0 0145
+f 10,10 0 0146
+g 10,7,3 0 0147
+h 10,10 0 0150
+i 10,10 0 0151
+j 10,10,3 0 0152
+k 10,10 0 0153
+l 10,10 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,10,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,3 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,10,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 10,5 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,9 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,1,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,10 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,12 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/DESC b/gnu/usr.bin/groff/devices/devX100-12/DESC
new file mode 100644
index 000000000000..ead70b97f03a
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 100
+X11
+hor 1
+vert 1
+unitwidth 12
+postpro gxditview
diff --git a/gnu/usr.bin/groff/devices/devX100-12/HB b/gnu/usr.bin/groff/devices/devX100-12/HB
new file mode 100644
index 000000000000..e68615e14aa1
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 5
+charset
+--- 5,1 0 040
+! 6,12 0 041
+" 8,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 12,12 0 046
+' 5,12 0 047
+( 6,12,3 0 050
+) 6,12,3 0 051
+* 6,12 0 052
++ 10,8 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 10,12 0 077
+@ 16,12,2 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 9,12 0 0112
+K 12,12 0 0113
+L 10,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 6,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 6,12,3 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 5,12 0 0140
+oq "
+a 9,9 0 0141
+b 10,12 0 0142
+c 9,9 0 0143
+d 10,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 10,9,4 0 0147
+h 10,12 0 0150
+i 4,12 0 0151
+j 5,12,4 0 0152
+k 9,12 0 0153
+l 5,12 0 0154
+m 14,9 0 0155
+n 10,9 0 0156
+o 10,9 0 0157
+p 10,9,4 0 0160
+q 10,9,4 0 0161
+r 6,9 0 0162
+s 9,9 0 0163
+t 6,11 0 0164
+u 10,9 0 0165
+v 9,9 0 0166
+w 13,9 0 0167
+x 9,9 0 0170
+y 9,9,4 0 0171
+z 8,9 0 0172
+{ 6,12,3 0 0173
+lC "
+| 4,12,4 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,1 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,9 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 5,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 10,9,3 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 12,12,4 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,9 0 0327
+× "
+/O 13,12 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 9,9,4 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 10,12 0 0360
+ð "
+~n 10,12 0 0361
+ñ "
+`o 10,13 0 0362
+ò "
+'o 10,13 0 0363
+ó "
+^o 10,13 0 0364
+ô "
+~o 10,12 0 0365
+õ "
+:o 10,12 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,9 0 0370
+ø "
+`u 10,13 0 0371
+ù "
+'u 10,13 0 0372
+ú "
+^u 10,13 0 0373
+û "
+:u 10,12 0 0374
+ü "
+'y 9,13,4 0 0375
+ý "
+Tp 10,12,4 0 0376
+þ "
+:y 9,12,4 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/HBI b/gnu/usr.bin/groff/devices/devX100-12/HBI
new file mode 100644
index 000000000000..6723ddff1286
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 5
+charset
+--- 5,1 0 040
+! 6,12 0 041
+" 8,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 12,12 0 046
+' 5,12 0 047
+( 6,12,3 0 050
+) 6,12,3 0 051
+* 6,12 0 052
++ 10,8 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 10,12 0 060
+1 9,12 0 061
+2 10,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 10,12 0 077
+@ 16,12,2 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 9,12 0 0112
+K 12,12 0 0113
+L 10,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 6,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 6,12,3 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 5,12 0 0140
+oq "
+a 9,9 0 0141
+b 10,12 0 0142
+c 9,9 0 0143
+d 10,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 10,9,4 0 0147
+h 10,12 0 0150
+i 4,12 0 0151
+j 5,12,4 0 0152
+k 9,12 0 0153
+l 5,12 0 0154
+m 14,9 0 0155
+n 10,9 0 0156
+o 10,9 0 0157
+p 10,9,4 0 0160
+q 10,9,4 0 0161
+r 6,9 0 0162
+s 9,9 0 0163
+t 6,12 0 0164
+u 10,9 0 0165
+v 9,9 0 0166
+w 13,9 0 0167
+x 9,9 0 0170
+y 9,9,4 0 0171
+z 8,9 0 0172
+{ 6,12,3 0 0173
+lC "
+| 3,12,4 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,1 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,9 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 5,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 10,9,4 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,15 0 0305
+Å "
+AE 17,12 0 0306
+Æ "
+,C 12,12,4 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,12 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 9,9,4 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 10,13 0 0360
+ð "
+~n 10,12 0 0361
+ñ "
+`o 10,13 0 0362
+ò "
+'o 10,13 0 0363
+ó "
+^o 10,13 0 0364
+ô "
+~o 10,12 0 0365
+õ "
+:o 10,12 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,9 0 0370
+ø "
+`u 10,13 0 0371
+ù "
+'u 10,13 0 0372
+ú "
+^u 10,13 0 0373
+û "
+:u 10,12 0 0374
+ü "
+'y 9,13,4 0 0375
+ý "
+Tp 10,12,4 0 0376
+þ "
+:y 9,12,4 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/HI b/gnu/usr.bin/groff/devices/devX100-12/HI
new file mode 100644
index 000000000000..f002cd630433
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 5
+charset
+--- 5,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 11,12 0 046
+' 4,12 0 047
+( 6,12,3 0 050
+) 6,12,3 0 051
+* 6,12 0 052
++ 10,9 0 053
+, 4,2,2 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 4,9 0 072
+; 4,9,2 0 073
+< 10,9 0 074
+= 10,6 0 075
+eq "
+> 10,9 0 076
+? 9,12 0 077
+@ 17,12,1 0 0100
+at "
+A 11,12 0 0101
+B 11,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 8,12 0 0112
+K 11,12 0 0113
+L 9,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 16,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 5,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 5,12,3 0 0135
+rB "
+^ 8,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 4,12 0 0140
+oq "
+a 9,9 0 0141
+b 9,12 0 0142
+c 8,9 0 0143
+d 9,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 9,9,4 0 0147
+h 9,12 0 0150
+i 3,12 0 0151
+j 4,12,4 0 0152
+k 8,12 0 0153
+l 4,12 0 0154
+m 14,9 0 0155
+n 9,9 0 0156
+o 9,9 0 0157
+p 9,9,4 0 0160
+q 9,9,4 0 0161
+r 5,9 0 0162
+s 8,9 0 0163
+t 5,11 0 0164
+u 9,9 0 0165
+v 8,9 0 0166
+w 12,9 0 0167
+x 8,9 0 0170
+y 8,9,4 0 0171
+z 8,9 0 0172
+{ 6,12,3 0 0173
+lC "
+| 3,12,4 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,1 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 4,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 5,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 9,9,4 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,7 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,13 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 11,16 0 0300
+À "
+'A 11,16 0 0301
+Á "
+^A 11,16 0 0302
+Â "
+~A 11,15 0 0303
+Ã "
+:A 11,15 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 12,12,3 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,12 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 8,9,3 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 9,12 0 0360
+ð "
+~n 9,12 0 0361
+ñ "
+`o 9,13 0 0362
+ò "
+'o 9,13 0 0363
+ó "
+^o 9,13 0 0364
+ô "
+~o 9,12 0 0365
+õ "
+:o 9,12 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,9 0 0370
+ø "
+`u 9,13 0 0371
+ù "
+'u 9,13 0 0372
+ú "
+^u 9,13 0 0373
+û "
+:u 9,12 0 0374
+ü "
+'y 8,13,4 0 0375
+ý "
+Tp 9,12,4 0 0376
+þ "
+:y 8,12,4 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/HR b/gnu/usr.bin/groff/devices/devX100-12/HR
new file mode 100644
index 000000000000..d2b296f64e7e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 5
+charset
+--- 5,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 9,11 0 043
+sh "
+$ 9,13,2 0 044
+Do "
+% 14,12 0 045
+& 11,12 0 046
+' 4,12 0 047
+( 6,12,4 0 050
+) 6,12,4 0 051
+* 6,12 0 052
++ 10,9 0 053
+, 4,2,2 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 4,9 0 072
+; 4,9,2 0 073
+< 10,9 0 074
+= 10,6 0 075
+eq "
+> 10,9 0 076
+? 9,12 0 077
+@ 17,12,2 0 0100
+at "
+A 11,12 0 0101
+B 11,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 8,12 0 0112
+K 11,12 0 0113
+L 9,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 5,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 5,12,3 0 0135
+rB "
+^ 8,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 4,12 0 0140
+oq "
+a 9,9 0 0141
+b 9,12 0 0142
+c 8,9 0 0143
+d 9,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 9,9,4 0 0147
+h 9,12 0 0150
+i 3,12 0 0151
+j 4,12,4 0 0152
+k 8,12 0 0153
+l 3,12 0 0154
+m 14,9 0 0155
+n 9,9 0 0156
+o 9,9 0 0157
+p 9,9,4 0 0160
+q 9,9,4 0 0161
+r 5,9 0 0162
+s 8,9 0 0163
+t 5,11 0 0164
+u 9,9 0 0165
+v 8,9 0 0166
+w 12,9 0 0167
+x 8,9 0 0170
+y 8,9,3 0 0171
+z 8,9 0 0172
+{ 6,12,4 0 0173
+lC "
+| 4,12,4 0 0174
+or "
+ba "
+} 6,12,4 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,11,2 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 4,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 5,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 9,9,4 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,13 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 11,16 0 0300
+À "
+'A 11,16 0 0301
+Á "
+^A 11,16 0 0302
+Â "
+~A 11,15 0 0303
+Ã "
+:A 11,15 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 12,12,4 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,13,1 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 8,9,4 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 9,12 0 0360
+ð "
+~n 9,12 0 0361
+ñ "
+`o 9,13 0 0362
+ò "
+'o 9,13 0 0363
+ó "
+^o 9,13 0 0364
+ô "
+~o 9,12 0 0365
+õ "
+:o 9,12 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,10 0 0370
+ø "
+`u 9,13 0 0371
+ù "
+'u 9,13 0 0372
+ú "
+^u 9,13 0 0373
+û "
+:u 9,12 0 0374
+ü "
+'y 8,13,3 0 0375
+ý "
+Tp 9,12,4 0 0376
+þ "
+:y 8,12,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/Makefile b/gnu/usr.bin/groff/devices/devX100-12/Makefile
new file mode 100644
index 000000000000..4936ceb28a1f
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/Makefile
@@ -0,0 +1,10 @@
+# Makefile for devX100-12
+
+DEVICE= X100-12
+FONTFILES= CB CBI CI CR HB HBI HI HR NB NBI NI NR S TB TBI TI TR DESC
+
+NOOBJ= noobj
+
+clean cleandir:
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devX100-12/NB b/gnu/usr.bin/groff/devices/devX100-12/NB
new file mode 100644
index 000000000000..f997df5961df
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 10,12 0 043
+sh "
+$ 10,14,1 0 044
+Do "
+% 14,12 0 045
+& 14,12 0 046
+' 4,12 0 047
+( 6,12,2 0 050
+) 6,12,2 0 051
+* 8,12 0 052
++ 10,8 0 053
+, 5,3,3 0 054
+\- 10,5 0 055
+. 5,3 0 056
+/ 5,12 0 057
+sl "
+0 10,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 10,12 0 063
+4 9,12 0 064
+5 10,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 10,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 8,12 0 077
+@ 12,12,1 0 0100
+at "
+A 13,12 0 0101
+B 13,12 0 0102
+C 13,12 0 0103
+D 14,12 0 0104
+E 12,12 0 0105
+F 12,12 0 0106
+G 14,12 0 0107
+H 15,12 0 0110
+I 7,12 0 0111
+J 11,12 0 0112
+K 13,12 0 0113
+L 12,12 0 0114
+M 16,12 0 0115
+N 14,12 0 0116
+O 14,12 0 0117
+P 13,12 0 0120
+Q 14,12,3 0 0121
+R 14,12 0 0122
+S 11,12 0 0123
+T 12,12 0 0124
+U 14,12 0 0125
+V 13,12 0 0126
+W 16,12 0 0127
+X 12,12 0 0130
+Y 12,12 0 0131
+Z 11,12 0 0132
+[ 6,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 7,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 4,12 0 0140
+oq "
+a 10,8 0 0141
+b 11,12 0 0142
+c 9,8 0 0143
+d 11,12 0 0144
+e 10,8 0 0145
+f 7,12 0 0146
+g 10,9,3 0 0147
+h 11,12 0 0150
+i 6,12 0 0151
+j 6,12,3 0 0152
+k 11,12 0 0153
+l 6,12 0 0154
+m 16,8 0 0155
+n 11,8 0 0156
+o 11,8 0 0157
+p 11,8,3 0 0160
+q 10,8,3 0 0161
+r 9,8 0 0162
+s 8,8 0 0163
+t 7,11 0 0164
+u 11,8 0 0165
+v 10,8 0 0166
+w 15,8 0 0167
+x 10,8 0 0170
+y 10,8,3 0 0171
+z 9,8 0 0172
+{ 6,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 6,12,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,9,3 0 0241
+¡ "
+ct 10,10,2 0 0242
+¢ "
+Po 10,12 0 0243
+£ "
+Cs 10,10 0 0244
+¤ "
+Ye 10,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 11,8,3 0 0265
+ps 12,12 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 8,9,3 0 0277
+¿ "
+`A 13,16 0 0300
+À "
+'A 13,16 0 0301
+Á "
+^A 13,16 0 0302
+Â "
+~A 13,15 0 0303
+Ã "
+:A 13,15 0 0304
+Ä "
+oA 13,16 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 13,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 14,12 0 0320
+Ð "
+~N 14,15 0 0321
+Ñ "
+`O 14,16 0 0322
+Ò "
+'O 14,16 0 0323
+Ó "
+^O 14,16 0 0324
+Ô "
+~O 14,15 0 0325
+Õ "
+:O 14,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 14,13,1 0 0330
+Ø "
+`U 14,16 0 0331
+Ù "
+'U 14,16 0 0332
+Ú "
+^U 14,16 0 0333
+Û "
+:U 14,15 0 0334
+Ü "
+'Y 12,16 0 0335
+Ý "
+TP 13,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 10,12 0 0340
+à "
+'a 10,12 0 0341
+á "
+^a 10,12 0 0342
+â "
+~a 10,11 0 0343
+ã "
+:a 10,11 0 0344
+ä "
+oa 10,12 0 0345
+å "
+ae 15,8 0 0346
+æ "
+,c 9,8,3 0 0347
+ç "
+`e 10,12 0 0350
+è "
+'e 10,12 0 0351
+é "
+^e 10,12 0 0352
+ê "
+:e 10,11 0 0353
+ë "
+`i 6,12 0 0354
+ì "
+'i 6,12 0 0355
+í "
+^i 6,12 0 0356
+î "
+:i 6,11 0 0357
+ï "
+Sd 11,13 0 0360
+ð "
+~n 11,11 0 0361
+ñ "
+`o 11,12 0 0362
+ò "
+'o 11,12 0 0363
+ó "
+^o 11,12 0 0364
+ô "
+~o 11,11 0 0365
+õ "
+:o 11,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,10,2 0 0370
+ø "
+`u 11,12 0 0371
+ù "
+'u 11,12 0 0372
+ú "
+^u 11,12 0 0373
+û "
+:u 11,11 0 0374
+ü "
+'y 10,12,3 0 0375
+ý "
+Tp 11,12,3 0 0376
+þ "
+:y 10,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/NBI b/gnu/usr.bin/groff/devices/devX100-12/NBI
new file mode 100644
index 000000000000..38c32819b37c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,12 0 041
+" 7,12 0 042
+# 10,12 0 043
+sh "
+$ 9,14,1 0 044
+Do "
+% 15,12 0 045
+& 15,12 0 046
+' 4,12 0 047
+( 7,12,2 0 050
+) 7,12,2 0 051
+* 8,12 0 052
++ 10,8 0 053
+, 5,3,3 0 054
+\- 10,5 0 055
+. 5,3 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 10,12 0 065
+6 10,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 8,12 0 077
+@ 12,12 0 0100
+at "
+A 12,12 0 0101
+B 13,12 0 0102
+C 13,12 0 0103
+D 14,12 0 0104
+E 12,12 0 0105
+F 12,12 0 0106
+G 14,12 0 0107
+H 14,12 0 0110
+I 7,12 0 0111
+J 11,12 0 0112
+K 13,12 0 0113
+L 12,12 0 0114
+M 16,12 0 0115
+N 14,12 0 0116
+O 14,12 0 0117
+P 12,12 0 0120
+Q 14,12,3 0 0121
+R 14,12 0 0122
+S 11,12 0 0123
+T 12,12 0 0124
+U 14,12 0 0125
+V 12,12 0 0126
+W 16,12 0 0127
+X 12,12 0 0130
+Y 12,12 0 0131
+Z 12,12 0 0132
+[ 7,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 7,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 4,12 0 0140
+oq "
+a 11,8 0 0141
+b 10,12 0 0142
+c 9,8 0 0143
+d 11,12 0 0144
+e 9,8 0 0145
+f 6,12,3 0 0146
+g 10,9,3 0 0147
+h 11,12 0 0150
+i 6,12 0 0151
+j 6,12,3 0 0152
+k 11,12 0 0153
+l 6,12 0 0154
+m 15,8 0 0155
+n 11,8 0 0156
+o 10,8 0 0157
+p 11,8,3 0 0160
+q 10,8,3 0 0161
+r 9,8 0 0162
+s 8,8 0 0163
+t 7,11 0 0164
+u 11,8 0 0165
+v 9,8 0 0166
+w 14,8 0 0167
+x 9,8 0 0170
+y 9,8,3 0 0171
+z 9,8 0 0172
+{ 7,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 7,12,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 10,10,2 0 0242
+¢ "
+Po 10,12 0 0243
+£ "
+Cs 10,10 0 0244
+¤ "
+Ye 10,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 7,12 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,8 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 11,8,3 0 0265
+ps 11,12 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 8,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 15,12 0 0306
+Æ "
+,C 13,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 14,12 0 0320
+Ð "
+~N 14,15 0 0321
+Ñ "
+`O 14,16 0 0322
+Ò "
+'O 14,16 0 0323
+Ó "
+^O 14,16 0 0324
+Ô "
+~O 14,15 0 0325
+Õ "
+:O 14,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 14,13,1 0 0330
+Ø "
+`U 14,16 0 0331
+Ù "
+'U 14,16 0 0332
+Ú "
+^U 14,16 0 0333
+Û "
+:U 14,15 0 0334
+Ü "
+'Y 12,16 0 0335
+Ý "
+TP 12,12 0 0336
+Þ "
+ss 10,12,3 0 0337
+ß "
+`a 11,12 0 0340
+à "
+'a 11,12 0 0341
+á "
+^a 11,12 0 0342
+â "
+~a 11,11 0 0343
+ã "
+:a 11,11 0 0344
+ä "
+oa 11,13 0 0345
+å "
+ae 14,8 0 0346
+æ "
+,c 9,8,3 0 0347
+ç "
+`e 9,12 0 0350
+è "
+'e 9,12 0 0351
+é "
+^e 9,12 0 0352
+ê "
+:e 9,11 0 0353
+ë "
+`i 6,12 0 0354
+ì "
+'i 6,12 0 0355
+í "
+^i 6,12 0 0356
+î "
+:i 6,11 0 0357
+ï "
+Sd 10,13 0 0360
+ð "
+~n 11,11 0 0361
+ñ "
+`o 10,12 0 0362
+ò "
+'o 10,12 0 0363
+ó "
+^o 10,12 0 0364
+ô "
+~o 10,11 0 0365
+õ "
+:o 10,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,10,2 0 0370
+ø "
+`u 11,12 0 0371
+ù "
+'u 11,12 0 0372
+ú "
+^u 11,12 0 0373
+û "
+:u 11,11 0 0374
+ü "
+'y 9,12,3 0 0375
+ý "
+Tp 11,11,3 0 0376
+þ "
+:y 9,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/NI b/gnu/usr.bin/groff/devices/devX100-12/NI
new file mode 100644
index 000000000000..7a34f2af98e8
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,12 0 041
+" 7,12 0 042
+# 9,12 0 043
+sh "
+$ 9,14,1 0 044
+Do "
+% 14,12 0 045
+& 14,12 0 046
+' 3,12 0 047
+( 6,12,2 0 050
+) 5,12,2 0 051
+* 8,12 0 052
++ 10,9 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 10,12,2 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,9 0 074
+= 10,6 0 075
+eq "
+> 10,9 0 076
+? 7,12 0 077
+@ 12,12 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 13,12 0 0104
+E 12,12 0 0105
+F 11,12 0 0106
+G 13,12 0 0107
+H 14,12 0 0110
+I 7,12 0 0111
+J 10,12 0 0112
+K 12,12 0 0113
+L 11,12 0 0114
+M 16,12 0 0115
+N 13,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,3 0 0121
+R 13,12 0 0122
+S 11,12 0 0123
+T 11,12 0 0124
+U 13,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 12,12 0 0130
+Y 11,12 0 0131
+Z 11,12 0 0132
+[ 6,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 6,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,12 0 0140
+oq "
+a 10,8 0 0141
+b 9,12 0 0142
+c 8,8 0 0143
+d 10,12 0 0144
+e 7,8 0 0145
+f 5,12,3 0 0146
+g 9,9,3 0 0147
+h 10,12 0 0150
+i 6,12 0 0151
+j 5,12,3 0 0152
+k 9,12 0 0153
+l 6,12 0 0154
+m 15,8 0 0155
+n 10,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 7,8 0 0162
+s 7,8 0 0163
+t 6,11 0 0164
+u 10,8 0 0165
+v 8,8 0 0166
+w 13,8 0 0167
+x 8,8 0 0170
+y 8,8,3 0 0171
+z 8,8 0 0172
+{ 6,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 6,12,2 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,2 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 8,12,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 7,12 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 5,12 0 0264
+´ "
+µ 10,8,3 0 0265
+ps 11,12 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 7,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 14,12 0 0306
+Æ "
+,C 12,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 13,12 0 0320
+Ð "
+~N 13,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,13,1 0 0330
+Ø "
+`U 13,16 0 0331
+Ù "
+'U 13,16 0 0332
+Ú "
+^U 13,16 0 0333
+Û "
+:U 13,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 9,12,3 0 0337
+ß "
+`a 10,12 0 0340
+à "
+'a 10,12 0 0341
+á "
+^a 10,12 0 0342
+â "
+~a 10,11 0 0343
+ã "
+:a 10,11 0 0344
+ä "
+oa 10,13 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 6,12 0 0354
+ì "
+'i 6,12 0 0355
+í "
+^i 6,12 0 0356
+î "
+:i 6,11 0 0357
+ï "
+Sd 8,13 0 0360
+ð "
+~n 10,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 8,10,2 0 0370
+ø "
+`u 10,12 0 0371
+ù "
+'u 10,12 0 0372
+ú "
+^u 10,12 0 0373
+û "
+:u 10,11 0 0374
+ü "
+'y 8,12,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 8,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/NR b/gnu/usr.bin/groff/devices/devX100-12/NR
new file mode 100644
index 000000000000..0a9a0cfa8200
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,2 0 044
+Do "
+% 14,12 0 045
+& 13,12 0 046
+' 3,12 0 047
+( 6,12,2 0 050
+) 6,12,2 0 051
+* 8,12 0 052
++ 10,9 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 4,8 0 072
+; 4,8,3 0 073
+< 10,8 0 074
+= 10,6 0 075
+eq "
+> 10,8 0 076
+? 7,12 0 077
+@ 12,12,1 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 13,12 0 0104
+E 12,12 0 0105
+F 11,12 0 0106
+G 13,12 0 0107
+H 14,12 0 0110
+I 7,12 0 0111
+J 9,12 0 0112
+K 13,12 0 0113
+L 11,12 0 0114
+M 16,12 0 0115
+N 13,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,3 0 0121
+R 12,12 0 0122
+S 10,12 0 0123
+T 11,12 0 0124
+U 13,12 0 0125
+V 12,12 0 0126
+W 16,12 0 0127
+X 11,12 0 0130
+Y 12,12 0 0131
+Z 10,12 0 0132
+[ 6,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 6,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 3,12 0 0140
+oq "
+a 9,8 0 0141
+b 9,12 0 0142
+c 7,8 0 0143
+d 10,12 0 0144
+e 8,8 0 0145
+f 6,12 0 0146
+g 9,8,3 0 0147
+h 10,12 0 0150
+i 5,12 0 0151
+j 5,12,3 0 0152
+k 10,12 0 0153
+l 5,12 0 0154
+m 15,8 0 0155
+n 10,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 7,8 0 0162
+s 8,8 0 0163
+t 7,11 0 0164
+u 10,8 0 0165
+v 9,8 0 0166
+w 13,8 0 0167
+x 9,8 0 0170
+y 9,8,3 0 0171
+z 8,8 0 0172
+{ 6,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 6,12,2 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,9,3 0 0241
+¡ "
+ct 9,10,2 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 8,12,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 5,12 0 0264
+´ "
+µ 10,8,3 0 0265
+ps 10,12,3 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 5,12 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 13,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 7,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 17,12 0 0306
+Æ "
+,C 12,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 13,12 0 0320
+Ð "
+~N 13,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,13,1 0 0330
+Ø "
+`U 13,16 0 0331
+Ù "
+'U 13,16 0 0332
+Ú "
+^U 13,16 0 0333
+Û "
+:U 13,15 0 0334
+Ü "
+'Y 12,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,12 0 0340
+à "
+'a 9,12 0 0341
+á "
+^a 9,12 0 0342
+â "
+~a 9,11 0 0343
+ã "
+:a 9,11 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 8,12 0 0350
+è "
+'e 8,12 0 0351
+é "
+^e 8,12 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,13 0 0360
+ð "
+~n 10,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 10,12 0 0371
+ù "
+'u 10,12 0 0372
+ú "
+^u 10,12 0 0373
+û "
+:u 10,11 0 0374
+ü "
+'y 9,12,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 9,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/S b/gnu/usr.bin/groff/devices/devX100-12/S
new file mode 100644
index 000000000000..1d235dab52de
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+fa 11,12 0 042
+# 8,11 0 043
+sh "
+te 9,12 0 044
+% 13,11,1 0 045
+& 13,11 0 046
+st 7,8 0 047
+( 5,12,2 0 050
+) 5,12,2 0 051
+** 8,8 0 052
++ 9,9 0 053
+pl "
+, 4,3,2 0 054
+\- 9,5 0 055
+mi "
+. 4,3 0 056
+/ 5,11 0 057
+sl "
+0 8,12 0 060
+1 8,12 0 061
+2 8,12 0 062
+3 8,12 0 063
+4 8,12 0 064
+5 8,12 0 065
+6 8,12 0 066
+7 8,12 0 067
+8 8,12 0 070
+9 8,12 0 071
+: 4,8 0 072
+; 4,8,2 0 073
+< 9,9 0 074
+= 9,6 0 075
+eq "
+> 9,9 0 076
+? 7,11 0 077
+=~ 9,8 0 0100
+*A 12,11 0 0101
+*B 11,11 0 0102
+*X 12,11 0 0103
+*D 10,11 0 0104
+*E 10,11 0 0105
+*F 12,11 0 0106
+*G 10,11 0 0107
+*Y 12,11 0 0110
+*I 6,11 0 0111
++h 10,12 0 0112
+*K 12,11 0 0113
+*L 11,11 0 0114
+*M 14,11 0 0115
+*N 11,11 0 0116
+*O 12,11 0 0117
+*P 12,11 0 0120
+*H 12,11 0 0121
+*R 9,11 0 0122
+*S 10,11 0 0123
+*T 10,11 0 0124
+--- 11,11 0 0125
+ts 8,8,4 0 0126
+*W 12,12 0 0127
+*C 11,11 0 0130
+*Q 13,11 0 0131
+*Z 10,11 0 0132
+[ 6,12,2 0 0133
+lB "
+tf 14,8 0 0134
+3d "
+] 5,12,2 0 0135
+rB "
+pp 11,11 0 0136
+_ 8,0,4 0 0137
+rn 8,13 0 0140
+*a 11,9 0 0141
+*b 9,13,4 0 0142
+*x 9,9,3 0 0143
+*d 8,12 0 0144
+*e 7,9 0 0145
+*f 9,11,3 0 0146
+*g 7,9,4 0 0147
+*y 10,9,3 0 0150
+*i 5,9 0 0151
++f 10,9,3 0 0152
+*k 9,9 0 0153
+*l 9,13 0 0154
+*m 9,9,4 0 0155
+µ "
+*n 8,9 0 0156
+*o 9,9 0 0157
+*p 9,9 0 0160
+*h 9,12 0 0161
+*r 9,9,4 0 0162
+*s 10,9 0 0163
+*t 7,9 0 0164
+*u 9,9 0 0165
++p 11,10 0 0166
+*w 11,9 0 0167
+*c 8,13,4 0 0170
+*q 11,9,4 0 0171
+*z 8,13,4 0 0172
+lC 8,12,2 0 0173
+{ "
+ba 3,11,3 0 0174
+or "
+| "
+rC 8,12,2 0 0175
+} "
+ap 9,5 0 0176
+*U 10,11 0 0241
+fm 4,12 0 0242
+<= 9,11 0 0243
+f/ 3,11 0 0244
+if 12,7 0 0245
+Fn 8,12,3 0 0246
+CL 12,9,1 0 0247
+DI 12,9 0 0250
+HE 12,9 0 0251
+SP 12,9,1 0 0252
+<> 17,9 0 0253
+<- 16,9 0 0254
+ua 10,13,2 0 0255
+arrowverttp "
+-> 16,9 0 0256
+da 10,13,2 0 0257
+arrowvertbt "
+de 6,11 0 0260
+° "
++- 9,11 0 0261
+± "
+sd 7,12 0 0262
+>= 9,11 0 0263
+mu 9,9 0 0264
+× "
+pt 11,7 0 0265
+pd 8,13,1 0 0266
+bu 8,8 0 0267
+di 9,8 0 0270
+÷ "
+!= 9,9,1 0 0271
+== 9,8 0 0272
+~= 9,7 0 0273
+~~ "
+--- 16,3 0 0274
+arrowvertex 10,13,4 0 0275
+an 16,5 0 0276
+CR 10,10,1 0 0277
+Ah 13,11 0 0300
+Im 11,13,1 0 0301
+Re 13,13 0 0302
+wp 16,9,4 0 0303
+c* 12,11 0 0304
+c+ 12,11 0 0305
+es 13,12 0 0306
+ca 12,9 0 0307
+cu 12,9 0 0310
+sp 11,8 0 0311
+ip 11,7,3 0 0312
+--- 11,9,1 0 0313
+sb 11,8 0 0314
+ib 11,8,2 0 0315
+mo 11,7 0 0316
+nm 11,8,1 0 0317
+/_ 12,11 0 0320
+gr 11,12 0 0321
+rg 13,11 0 0322
+co 13,11 0 0323
+tm 14,11 0 0324
+--- 13,13,2 0 0325
+sr 9,13,3 0 0326
+md 4,5 0 0327
+no 12,5 0 0330
+¬ "
+AN 10,8 0 0331
+OR 10,8 0 0332
+hA 17,9 0 0333
+lA 16,9 0 0334
+uA 10,13,2 0 0335
+rA 16,9 0 0336
+dA 10,13,2 0 0337
+lz 8,12 0 0340
+la 5,13,2 0 0341
+--- 13,11 0 0342
+--- 13,11 0 0343
+--- 13,11 0 0344
+--- 11,13,2 0 0345
+parenlefttp 6,13,4 0 0346
+parenleftex 6,13,4 0 0347
+parenleftbt 6,13,4 0 0350
+bracketlefttp 6,13,4 0 0351
+lc "
+bracketleftex 6,13,4 0 0352
+bracketleftbt 6,13,4 0 0353
+lf "
+bracelefttp 8,13,4 0 0354
+lt "
+braceleftmid 8,13,4 0 0355
+lk "
+braceleftbt 8,13,4 0 0356
+lb "
+bracerightex 8,13,4 0 0357
+braceleftex "
+bv "
+--- 13,13 0 0360
+ra 5,13,2 0 0361
+is 5,13,4 0 0362
+--- 11,13,4 0 0363
+--- 11,13,4 0 0364
+--- 11,13,4 0 0365
+parenrighttp 7,13,4 0 0366
+parenrightex 6,13,4 0 0367
+parenrightbt 6,13,4 0 0370
+bracketrighttp 6,13,4 0 0371
+rc "
+bracketrightex 6,13,4 0 0372
+bracketrightbt 6,13,4 0 0373
+rf "
+bracerighttp 8,13,4 0 0374
+rt "
+bracerightmid 8,13,4 0 0375
+rk "
+bracerightbt 8,13,4 0 0376
+rb "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/TB b/gnu/usr.bin/groff/devices/devX100-12/TB
new file mode 100644
index 000000000000..83073d528178
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 9,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 16,12 0 045
+& 14,11 0 046
+' 6,11 0 047
+( 6,11,3 0 050
+) 6,11,3 0 051
+* 8,11 0 052
++ 9,8 0 053
+, 4,2,3 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,7 0 072
+; 5,7,3 0 073
+< 9,8 0 074
+= 9,7 0 075
+eq "
+> 9,8 0 076
+? 8,11 0 077
+@ 16,11,2 0 0100
+at "
+A 12,11 0 0101
+B 11,11 0 0102
+C 12,11 0 0103
+D 12,11 0 0104
+E 11,11 0 0105
+F 10,11 0 0106
+G 13,11 0 0107
+H 13,11 0 0110
+I 6,11 0 0111
+J 8,11,2 0 0112
+K 13,11 0 0113
+L 11,11 0 0114
+M 15,11 0 0115
+N 12,11 0 0116
+O 13,11 0 0117
+P 10,11 0 0120
+Q 13,11,3 0 0121
+R 12,11 0 0122
+S 9,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 12,11 0 0126
+W 16,11 0 0127
+X 12,11 0 0130
+Y 12,11 0 0131
+Z 11,11 0 0132
+[ 6,11,3 0 0133
+lB "
+\ 5,11 0 0134
+rs "
+] 6,11,3 0 0135
+rB "
+^ 9,11 0 0136
+a^ "
+ha "
+_ 8,0,4 0 0137
+` 6,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 7,8 0 0143
+d 9,11 0 0144
+e 7,8 0 0145
+f 6,11 0 0146
+g 8,8,4 0 0147
+h 9,11 0 0150
+i 5,11 0 0151
+j 5,11,4 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 14,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 9,8,4 0 0160
+q 9,8,4 0 0161
+r 7,8 0 0162
+s 6,8 0 0163
+t 6,11 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 12,8 0 0167
+x 8,8 0 0170
+y 8,8,4 0 0171
+z 7,8 0 0172
+{ 7,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 7,11,3 0 0175
+rC "
+~ 9,8 0 0176
+a~ "
+ap "
+ti "
+r! 6,8,4 0 0241
+¡ "
+ct 8,10,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 4,12,3 0 0246
+¦ "
+sc 8,11,4 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 9,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 6,10 0 0257
+¯ "
+de 7,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 9,11,4 0 0266
+¶ "
+md 4,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 12,15 0 0300
+À "
+'A 12,15 0 0301
+Á "
+^A 12,15 0 0302
+Â "
+~A 12,14 0 0303
+Ã "
+:A 12,14 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 16,11 0 0306
+Æ "
+,C 12,11,4 0 0307
+Ç "
+`E 11,15 0 0310
+È "
+'E 11,15 0 0311
+É "
+^E 11,15 0 0312
+Ê "
+:E 11,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 13,15 0 0322
+Ò "
+'O 13,15 0 0323
+Ó "
+^O 13,15 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 13,12,1 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 12,15 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 8,12 0 0340
+à "
+'a 8,12 0 0341
+á "
+^a 8,12 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,13 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 7,8,4 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 9,12 0 0371
+ù "
+'u 9,12 0 0372
+ú "
+^u 9,12 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 8,12,4 0 0375
+ý "
+Tp 9,11,4 0 0376
+þ "
+:y 8,11,4 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/TBI b/gnu/usr.bin/groff/devices/devX100-12/TBI
new file mode 100644
index 000000000000..71ca713620cb
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 9,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 6,11 0 047
+( 6,11,3 0 050
+) 6,11,3 0 051
+* 8,11 0 052
++ 10,9 0 053
+, 4,2,3 0 054
+\- 10,6 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,7 0 072
+; 5,7,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 8,11 0 077
+@ 14,11,2 0 0100
+at "
+A 11,11 0 0101
+B 11,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 11,11 0 0105
+F 11,11 0 0106
+G 12,11 0 0107
+H 13,11 0 0110
+I 6,11 0 0111
+J 8,11,2 0 0112
+K 11,11 0 0113
+L 10,11 0 0114
+M 15,11 0 0115
+N 12,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,4 0 0121
+R 11,11 0 0122
+S 9,11 0 0123
+T 10,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 15,11 0 0127
+X 11,11 0 0130
+Y 10,11 0 0131
+Z 10,11 0 0132
+[ 6,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 6,12,3 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 6,11 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 7,8 0 0145
+f 6,11,3 0 0146
+g 8,8,3 0 0147
+h 9,11 0 0150
+i 5,11 0 0151
+j 5,11,3 0 0152
+k 8,11 0 0153
+l 5,11 0 0154
+m 13,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 6,8 0 0162
+s 6,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 7,8 0 0166
+w 11,8 0 0167
+x 8,8 0 0170
+y 7,8,3 0 0171
+z 6,8,1 0 0172
+{ 6,12,3 0 0173
+lC "
+| 4,12 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,8,4 0 0241
+¡ "
+ct 8,10,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 4,12 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 4,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 10,5 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 6,10 0 0257
+¯ "
+de 7,11 0 0260
+° "
++- 10,10 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 6,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 13,11 0 0274
+¼ "
+12 13,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 8,8,4 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 11,15 0 0310
+È "
+'E 11,15 0 0311
+É "
+^E 11,15 0 0312
+Ê "
+:E 11,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 10,9 0 0327
+× "
+/O 12,12,2 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 10,15 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,12,3 0 0337
+ß "
+`a 8,12 0 0340
+à "
+'a 8,12 0 0341
+á "
+^a 8,12 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,12 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 8,10,2 0 0370
+ø "
+`u 9,12 0 0371
+ù "
+'u 9,12 0 0372
+ú "
+^u 9,12 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 7,12,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/TI b/gnu/usr.bin/groff/devices/devX100-12/TI
new file mode 100644
index 000000000000..fad269f92525
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 7,10 0 042
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 6,10 0 047
+( 6,11,3 0 050
+) 6,11,3 0 051
+* 8,11 0 052
++ 11,9 0 053
+, 4,2,2 0 054
+\- 11,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,7 0 072
+; 5,7,2 0 073
+< 11,9 0 074
+= 11,6 0 075
+eq "
+> 11,9 0 076
+? 8,11 0 077
+@ 15,11,3 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 12,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 7,11 0 0112
+K 11,11 0 0113
+L 9,11 0 0114
+M 14,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,3 0 0121
+R 10,11 0 0122
+S 8,11 0 0123
+T 9,11 0 0124
+U 12,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 6,11,3 0 0133
+lB "
+\ 5,11 0 0134
+rs "
+] 6,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,4 0 0137
+` 6,10 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 7,8 0 0145
+f 5,11,4 0 0146
+g 8,8,4 0 0147
+h 8,11 0 0150
+i 5,11 0 0151
+j 5,11,4 0 0152
+k 7,11 0 0153
+l 5,11 0 0154
+m 12,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,4 0 0160
+q 8,8,4 0 0161
+r 6,8 0 0162
+s 6,8 0 0163
+t 5,10 0 0164
+u 8,8 0 0165
+v 7,8 0 0166
+w 11,8 0 0167
+x 7,8 0 0170
+y 7,8,4 0 0171
+z 6,8 0 0172
+{ 7,11,3 0 0173
+lC "
+| 5,11,3 0 0174
+or "
+ba "
+} 7,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 5,11,3 0 0246
+¦ "
+sc 8,12,1 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 13,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 11,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 13,11 0 0256
+® "
+a- 6,10 0 0257
+¯ "
+de 7,11 0 0260
+° "
++- 11,11 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 8,8,4 0 0265
+ps 9,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 6,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 13,11 0 0274
+¼ "
+12 13,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 10,15 0 0300
+À "
+'A 10,15 0 0301
+Á "
+^A 10,15 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,14 0 0304
+Ä "
+oA 10,15 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 11,9 0 0327
+× "
+/O 12,12,1 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,15 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11,4 0 0337
+ß "
+`a 8,12 0 0340
+à "
+'a 8,12 0 0341
+á "
+^a 8,12 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,13 0 0345
+å "
+ae 11,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,12 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 11,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 8,12 0 0371
+ù "
+'u 8,12 0 0372
+ú "
+^u 8,12 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,12,4 0 0375
+ý "
+Tp 8,11,4 0 0376
+þ "
+:y 7,11,4 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100-12/TR b/gnu/usr.bin/groff/devices/devX100-12/TR
new file mode 100644
index 000000000000..85a79be4aaec
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100-12/TR
Binary files differ
diff --git a/gnu/usr.bin/groff/devices/devX100/CB b/gnu/usr.bin/groff/devices/devX100/CB
new file mode 100644
index 000000000000..7239ed1e0dcb
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,10,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,9,2 0 050
+) 9,9,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,9,2 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,9,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,9,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,9,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,9,1 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,10,1 0 0247
+§ "
+ad 9,10 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 9,5 0 0255
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,9 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,9 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,10,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,4 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,10 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,4 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,10 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/CBI b/gnu/usr.bin/groff/devices/devX100/CBI
new file mode 100644
index 000000000000..55e27f4065bf
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/CBI
Binary files differ
diff --git a/gnu/usr.bin/groff/devices/devX100/CI b/gnu/usr.bin/groff/devices/devX100/CI
new file mode 100644
index 000000000000..07fd0a685a5b
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,10,1 0 043
+sh "
+$ 9,10,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,10,3 0 050
+) 9,10,3 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,3 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,10,3 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,3 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,3 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,10 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,9,1 0 0247
+§ "
+ad 9,9 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 0255
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,9 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,9,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,11 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,9 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,3 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,9 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,9 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,9 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/CR b/gnu/usr.bin/groff/devices/devX100/CR
new file mode 100644
index 000000000000..e425fa602bb2
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,9,1 0 043
+sh "
+$ 9,11,2 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,10,2 0 050
+) 9,10,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,1 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9,1 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,2 0 0133
+lB "
+\ 9,10,1 0 0134
+rs "
+] 9,10,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,9 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,9,1 0 0247
+§ "
+ad 9,9 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 0255
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,10 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,9,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,0,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,11 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,9 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,3 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,9 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,9 0 0357
+ï "
+Sd 9,12 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,9 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/DESC b/gnu/usr.bin/groff/devices/devX100/DESC
new file mode 100644
index 000000000000..7f63535e0e65
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 100
+X11
+hor 1
+vert 1
+unitwidth 10
+postpro gxditview
diff --git a/gnu/usr.bin/groff/devices/devX100/HB b/gnu/usr.bin/groff/devices/devX100/HB
new file mode 100644
index 000000000000..d877fd65a080
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 7,11 0 042
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,1 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,1 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 8,7 0 076
+? 9,11 0 077
+@ 14,11,1 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 9,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 8,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 9,8,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,14 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,14 0 0322
+Ò "
+'O 12,14 0 0323
+Ó "
+^O 12,14 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 9,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,11 0 0357
+ï "
+Sd 9,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 9,11 0 0362
+ò "
+'o 9,11 0 0363
+ó "
+^o 9,11 0 0364
+ô "
+~o 9,11 0 0365
+õ "
+:o 9,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,8 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 8,11,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 8,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/HBI b/gnu/usr.bin/groff/devices/devX100/HBI
new file mode 100644
index 000000000000..1cf0e56e638d
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 7,11 0 042
+# 10,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+( 5,11,3 0 050
+) 6,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,2 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 9,7 0 076
+? 9,11 0 077
+@ 14,11,2 0 0100
+at "
+A 9,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 10,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 5,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 11,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 9,8 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 9,11,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 11,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 5,11 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 11,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 9,14 0 0300
+À "
+'A 9,14 0 0301
+Á "
+^A 9,14 0 0302
+Â "
+~A 9,14 0 0303
+Ã "
+:A 9,14 0 0304
+Ä "
+oA 9,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,14 0 0322
+Ò "
+'O 12,14 0 0323
+Ó "
+^O 12,14 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,8 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/HI b/gnu/usr.bin/groff/devices/devX100/HI
new file mode 100644
index 000000000000..7908492d431c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 8,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,8 0 072
+; 4,8,2 0 073
+< 9,7 0 074
+= 9,6 0 075
+eq "
+> 9,7 0 076
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 11,11 0 0110
+I 5,11 0 0111
+J 9,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 14,11 0 0115
+N 11,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 4,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 8,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 4,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 4,11 0 0264
+´ "
+µ 8,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,13 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 9,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 8,11 0 0371
+ù "
+'u 8,11 0 0372
+ú "
+^u 8,11 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/HR b/gnu/usr.bin/groff/devices/devX100/HR
new file mode 100644
index 000000000000..c2f6af390348
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 7,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 3,8 0 072
+; 4,8,2 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 8,7 0 076
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 9,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 7,11 0 0112
+K 9,11 0 0113
+L 8,11 0 0114
+M 12,11 0 0115
+N 10,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 9,11 0 0124
+U 10,11 0 0125
+V 9,11 0 0126
+W 13,11 0 0127
+X 9,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 4,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 4,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 7,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 3,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 7,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 3,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 7,11 0 0245
+¥ "
+bb 3,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 4,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 8,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 9,14 0 0300
+À "
+'A 9,14 0 0301
+Á "
+^A 9,14 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,14 0 0304
+Ä "
+oA 9,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,13 0 0317
+Ï "
+-D 10,11 0 0320
+Ð "
+~N 10,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 9,11 0 0336
+Þ "
+ss 7,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,12 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,8 0 0370
+ø "
+`u 8,11 0 0371
+ù "
+'u 8,11 0 0372
+ú "
+^u 8,11 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/Makefile b/gnu/usr.bin/groff/devices/devX100/Makefile
new file mode 100644
index 000000000000..0cf8d281d131
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/Makefile
@@ -0,0 +1,10 @@
+# Makefile for devX100
+
+DEVICE= X100
+FONTFILES= CB CBI CI CR HB HBI HI HR NB NBI NI NR S TB TBI TI TR DESC
+
+NOOBJ= noobj
+
+clean cleandir:
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devX100/NB b/gnu/usr.bin/groff/devices/devX100/NB
new file mode 100644
index 000000000000..d47fdb2e1e4c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 11
+charset
+--- 11,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,3,2 0 054
+\- 8,5 0 055
+. 4,3 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 6,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,8 0 074
+= 8,6 0 075
+eq "
+> 8,8 0 076
+? 7,11 0 077
+@ 14,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 12,11 0 0107
+H 12,11 0 0110
+I 7,11 0 0111
+J 9,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,3 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 12,11 0 0130
+Y 11,11 0 0131
+Z 9,11 0 0132
+[ 5,11,2 0 0133
+lB "
+\ 7,11 0 0134
+rs "
+] 5,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 10,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 9,7 0 0145
+f 6,11 0 0146
+g 8,8,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 5,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 9,7 0 0157
+p 10,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 6,10 0 0164
+u 10,7 0 0165
+v 7,7 0 0166
+w 12,7 0 0167
+x 9,7 0 0170
+y 7,7,3 0 0171
+z 7,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 8,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 11,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 7,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 7,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 7,8,3 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 7,15 0 0314
+Ì "
+'I 7,15 0 0315
+Í "
+^I 7,15 0 0316
+Î "
+:I 7,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 11,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 9,11 0 0340
+à "
+'a 9,11 0 0341
+á "
+^a 9,11 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 14,7 0 0346
+æ "
+,c 8,7,3 0 0347
+ç "
+`e 9,11 0 0350
+è "
+'e 9,11 0 0351
+é "
+^e 9,11 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 5,11 0 0354
+ì "
+'i 5,11 0 0355
+í "
+^i 5,11 0 0356
+î "
+:i 5,10 0 0357
+ï "
+Sd 9,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 9,11 0 0362
+ò "
+'o 9,11 0 0363
+ó "
+^o 9,11 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 9,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/NBI b/gnu/usr.bin/groff/devices/devX100/NBI
new file mode 100644
index 000000000000..c46b945ae863
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11,1 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 8,8 0 053
+, 4,2,3 0 054
+\- 8,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 5,7,3 0 073
+< 9,9 0 074
+= 9,7 0 075
+eq "
+> 9,9 0 076
+? 7,11 0 077
+@ 13,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 8,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 15,11 0 0115
+N 13,11 0 0116
+O 12,11 0 0117
+P 11,11 0 0120
+Q 12,11,2 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 15,11 0 0127
+X 11,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 7,11,2 0 0133
+lB "
+\ 9,11 0 0134
+rs "
+] 7,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 10,7 0 0141
+b 8,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 8,7 0 0145
+f 5,11,3 0 0146
+g 8,9,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 8,7 0 0157
+p 8,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 8,7 0 0163
+t 5,9 0 0164
+u 10,7 0 0165
+v 8,7 0 0166
+w 13,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 11,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 10,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 10,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 9,11,2 0 0247
+§ "
+ad 6,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 8,11 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 9,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 9,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 8,11 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 7,8,3 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 13,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,15 0 0335
+Ý "
+TP 11,11 0 0336
+Þ "
+ss 10,11,3 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,11 0 0345
+å "
+ae 13,7 0 0346
+æ "
+,c 8,7,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,10 0 0353
+ë "
+`i 5,11 0 0354
+ì "
+'i 5,11 0 0355
+í "
+^i 5,11 0 0356
+î "
+:i 5,10 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,10 0 0365
+õ "
+:o 8,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 8,7 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 9,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/NI b/gnu/usr.bin/groff/devices/devX100/NI
new file mode 100644
index 000000000000..3216f64a0543
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+# 11,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 12,11,1 0 045
+& 11,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 9,11,3 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 9,8 0 074
+= 8,6 0 075
+eq "
+> 9,8 0 076
+? 6,11 0 077
+@ 12,11 0 0100
+at "
+A 11,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 10,11 0 0107
+H 11,11 0 0110
+I 7,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 9,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 10,11 0 0117
+P 10,11 0 0120
+Q 10,11,2 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 10,11 0 0124
+U 12,11 0 0125
+V 10,11 0 0126
+W 13,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 6,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 6,11,2 0 0135
+rB "
+^ 6,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 7,11 0 0142
+c 6,7 0 0143
+d 9,11 0 0144
+e 6,7 0 0145
+f 5,11,3 0 0146
+g 7,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 8,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 8,7 0 0170
+y 7,7,3 0 0171
+z 8,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,2 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 7,10 0 0250
+¨ "
+co 13,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 13,11 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 4,11 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 6,8,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 7,14 0 0314
+Ì "
+'I 7,14 0 0315
+Í "
+^I 7,14 0 0316
+Î "
+:I 7,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,14 0 0325
+Õ "
+:O 10,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 10,11 0 0330
+Ø "
+`U 12,14 0 0331
+Ù "
+'U 12,14 0 0332
+Ú "
+^U 12,14 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11,3 0 0337
+ß "
+`a 9,11 0 0340
+à "
+'a 9,11 0 0341
+á "
+^a 9,11 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 6,11 0 0350
+è "
+'e 6,11 0 0351
+é "
+^e 6,11 0 0352
+ê "
+:e 6,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 7,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/NR b/gnu/usr.bin/groff/devices/devX100/NR
new file mode 100644
index 000000000000..8e6717eef145
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,11 0 041
+" 5,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 10,7 0 074
+= 9,6 0 075
+eq "
+> 10,7 0 076
+? 6,11 0 077
+@ 13,11 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 7,11 0 0112
+K 11,11 0 0113
+L 10,11 0 0114
+M 16,11 0 0115
+N 13,11 0 0116
+O 11,11 0 0117
+P 10,11 0 0120
+Q 11,11,2 0 0121
+R 11,11 0 0122
+S 8,11 0 0123
+T 10,11 0 0124
+U 13,11 0 0125
+V 10,11 0 0126
+W 16,11 0 0127
+X 13,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 4,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 4,11,2 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 8,7 0 0141
+b 7,11 0 0142
+c 7,7 0 0143
+d 8,11 0 0144
+e 7,7 0 0145
+f 5,11 0 0146
+g 8,7,3 0 0147
+h 9,11 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 7,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 8,7 0 0166
+w 12,7 0 0167
+x 8,7 0 0170
+y 8,7,3 0 0171
+z 7,7 0 0172
+{ 4,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 5,11,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 9,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 6,10 0 0250
+¨ "
+co 14,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 14,11 0 0256
+® "
+a- 5,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,7 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,11,2 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 6,8,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,14 0 0314
+Ì "
+'I 6,14 0 0315
+Í "
+^I 6,14 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 13,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,14 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 13,14 0 0331
+Ù "
+'U 13,14 0 0332
+Ú "
+^U 13,14 0 0333
+Û "
+:U 13,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,10 0 0343
+ã "
+:a 8,10 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 12,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 9,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 8,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 8,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/S b/gnu/usr.bin/groff/devices/devX100/S
new file mode 100644
index 000000000000..5e914124602f
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,10 0 041
+fa 9,10 0 042
+# 7,10 0 043
+sh "
+te 8,10 0 044
+% 12,10 0 045
+& 11,10 0 046
+st 6,7 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+** 7,8 0 052
++ 8,7 0 053
+pl "
+, 3,2,2 0 054
+\- 8,4 0 055
+mi "
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,10 0 077
+=~ 8,7 0 0100
+*A 11,10 0 0101
+*B 9,10 0 0102
+*X 11,10 0 0103
+*D 9,10 0 0104
+*E 9,10 0 0105
+*F 11,10 0 0106
+*G 9,10 0 0107
+*Y 11,10 0 0110
+*I 5,10 0 0111
++h 9,10 0 0112
+*K 10,10 0 0113
+*L 10,10 0 0114
+*M 13,10 0 0115
+*N 11,10 0 0116
+*O 10,10 0 0117
+*P 11,10 0 0120
+*H 10,10 0 0121
+*R 8,10 0 0122
+*S 9,10 0 0123
+*T 9,10 0 0124
+--- 9,10 0 0125
+ts 7,7,3 0 0126
+*W 11,10 0 0127
+*C 9,10 0 0130
+*Q 11,10 0 0131
+*Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+tf 10,7 0 0134
+3d "
+] 5,10,3 0 0135
+rB "
+pp 10,10 0 0136
+_ 7,0,3 0 0137
+rn 7,12 0 0140
+*a 9,7 0 0141
+*b 8,11,3 0 0142
+*x 8,7,3 0 0143
+*d 7,11 0 0144
+*e 6,7 0 0145
+*f 9,10,3 0 0146
+*g 6,7,3 0 0147
+*y 8,7,3 0 0150
+*i 5,7 0 0151
++f 9,7,3 0 0152
+*k 8,7 0 0153
+*l 8,10 0 0154
+*m 8,7,2 0 0155
+µ "
+*n 8,7 0 0156
+*o 8,7 0 0157
+*p 8,7 0 0160
+*h 7,10 0 0161
+*r 8,7,3 0 0162
+*s 8,7 0 0163
+*t 6,7 0 0164
+*u 8,7 0 0165
++p 11,8 0 0166
+*w 11,7 0 0167
+*c 7,12,3 0 0170
+*q 9,7,3 0 0171
+*z 7,11,3 0 0172
+lC 7,10,3 0 0173
+{ "
+ba 3,10,3 0 0174
+or "
+| "
+rC 7,10,3 0 0175
+} "
+ap 8,5 0 0176
+*U 9,10 0 0241
+fm 4,10 0 0242
+<= 8,9 0 0243
+f/ 4,10 0 0244
+if 10,6 0 0245
+Fn 7,10,3 0 0246
+CL 11,7 0 0247
+DI 11,7 0 0250
+HE 11,7 0 0251
+SP 11,7 0 0252
+<> 15,7 0 0253
+<- 14,7 0 0254
+ua 9,12,3 0 0255
+arrowverttp "
+-> 14,7 0 0256
+da 9,12,3 0 0257
+arrowvertbt "
+de 6,10 0 0260
+° "
++- 8,9 0 0261
+± "
+sd 6,10 0 0262
+>= 8,9 0 0263
+mu 8,7 0 0264
+× "
+pt 10,6 0 0265
+pd 7,11 0 0266
+bu 7,6 0 0267
+di 8,7 0 0270
+÷ "
+!= 8,7 0 0271
+== 8,6 0 0272
+~= 8,7 0 0273
+~~ "
+--- 15,2 0 0274
+arrowvertex 9,12,3 0 0275
+an 15,4 0 0276
+CR 10,9 0 0277
+Ah 12,10 0 0300
+Im 10,11,1 0 0301
+Re 12,11 0 0302
+wp 12,9,3 0 0303
+c* 11,9 0 0304
+c+ 11,9 0 0305
+es 12,11 0 0306
+ca 10,7 0 0307
+cu 10,7 0 0310
+sp 10,7 0 0311
+ip 10,7,2 0 0312
+--- 10,8,1 0 0313
+sb 10,7 0 0314
+ib 10,7,2 0 0315
+mo 10,7 0 0316
+nm 10,8,1 0 0317
+/_ 11,10 0 0320
+gr 10,11 0 0321
+rg 12,10 0 0322
+co 12,10 0 0323
+tm 11,10 0 0324
+--- 12,11,1 0 0325
+sr 8,12 0 0326
+md 4,5 0 0327
+no 10,5 0 0330
+¬ "
+AN 9,7 0 0331
+OR 9,7 0 0332
+hA 15,7 0 0333
+lA 14,7 0 0334
+uA 9,12 0 0335
+rA 14,7 0 0336
+dA 9,12 0 0337
+lz 7,11 0 0340
+la 5,12,3 0 0341
+--- 12,10 0 0342
+--- 12,10 0 0343
+--- 11,10 0 0344
+--- 10,11,1 0 0345
+parenlefttp 6,12,3 0 0346
+parenleftex 6,12,3 0 0347
+parenleftbt 6,12,3 0 0350
+bracketlefttp 6,12,3 0 0351
+lc "
+bracketleftex 6,12,3 0 0352
+bracketleftbt 6,12,3 0 0353
+lf "
+bracelefttp 7,12,3 0 0354
+lt "
+braceleftmid 7,12,3 0 0355
+lk "
+braceleftbt 7,12,3 0 0356
+lb "
+bracerightex 7,12,3 0 0357
+braceleftex "
+bv "
+--- 12,12 0 0360
+ra 5,12,3 0 0361
+is 4,12,1 0 0362
+--- 10,12,3 0 0363
+--- 10,12,3 0 0364
+--- 10,12,3 0 0365
+parenrighttp 6,12,3 0 0366
+parenrightex 6,12,3 0 0367
+parenrightbt 6,12,3 0 0370
+bracketrighttp 6,12,3 0 0371
+rc "
+bracketrightex 6,12,3 0 0372
+bracketrightbt 6,12,3 0 0373
+rf "
+bracerighttp 7,12,3 0 0374
+rt "
+bracerightmid 7,12,3 0 0375
+rk "
+bracerightbt 7,12,3 0 0376
+rb "
diff --git a/gnu/usr.bin/groff/devices/devX100/TB b/gnu/usr.bin/groff/devices/devX100/TB
new file mode 100644
index 000000000000..ebafbac74b3a
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,10 0 041
+" 7,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 12,10 0 046
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 3,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 7,10 0 077
+@ 14,10,2 0 0100
+at "
+A 10,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 10,10 0 0116
+O 11,10 0 0117
+P 9,10 0 0120
+Q 11,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 14,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 8,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 6,7 0 0145
+f 5,10 0 0146
+g 7,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 8,10 0 0153
+l 4,10 0 0154
+m 12,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 10,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10,2 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,7 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241
+¡ "
+ct 7,9,2 0 0242
+¢ "
+Po 8,10 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,10 0 0245
+¥ "
+bb 3,10,2 0 0246
+¦ "
+sc 7,10,2 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 5,10 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 5,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 8,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 7,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 14,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 11,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,13 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 11,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 8,10 0 0337
+ß "
+`a 7,11 0 0340
+à "
+'a 7,11 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,10 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 8,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,11 0 0371
+ù "
+'u 7,11 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,10,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/TBI b/gnu/usr.bin/groff/devices/devX100/TBI
new file mode 100644
index 000000000000..2297b4b2b663
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 7,10 0 041
+" 7,10 0 042
+# 8,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 10,10 0 046
+' 5,10 0 047
+( 6,10,3 0 050
+) 6,10,3 0 051
+* 7,10 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 6,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 5,7 0 072
+; 4,7,2 0 073
+< 8,6 0 074
+= 10,5 0 075
+eq "
+> 8,6 0 076
+? 8,10 0 077
+@ 15,10,2 0 0100
+at "
+A 9,10 0 0101
+B 9,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 13,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 6,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 5,10 0 0140
+oq "
+a 8,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 11,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 6,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 4,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,10 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 4,10 0 0246
+¦ "
+sc 8,10,3 0 0247
+§ "
+ad 6,9 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 6,10 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 6,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 6,10 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 8,7,3 0 0277
+¿ "
+`A 9,13 0 0300
+À "
+'A 9,13 0 0301
+Á "
+^A 9,13 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,13 0 0304
+Ä "
+oA 9,13 0 0305
+Å "
+AE 14,10 0 0306
+Æ "
+,C 9,10,3 0 0307
+Ç "
+`E 10,13 0 0310
+È "
+'E 10,13 0 0311
+É "
+^E 10,13 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 5,13 0 0314
+Ì "
+'I 5,13 0 0315
+Í "
+^I 5,13 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,13 0 0321
+Ñ "
+`O 10,13 0 0322
+Ò "
+'O 10,13 0 0323
+Ó "
+^O 10,13 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,13 0 0331
+Ù "
+'U 10,13 0 0332
+Ú "
+^U 10,13 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 8,13 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 7,10,3 0 0337
+ß "
+`a 8,10 0 0340
+à "
+'a 8,10 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,10 0 0343
+ã "
+:a 8,10 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,10 0 0354
+ì "
+'i 4,10 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 8,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 9,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 6,10,2 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 6,10,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/TI b/gnu/usr.bin/groff/devices/devX100/TI
new file mode 100644
index 000000000000..80a2f1c4049d
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 5,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 10,7 0 053
+, 4,2,1 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,1 0 073
+< 10,7,1 0 074
+= 10,5 0 075
+eq "
+> 10,7,1 0 076
+? 7,10 0 077
+@ 13,10,3 0 0100
+at "
+A 9,10 0 0101
+B 8,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 8,10 0 0114
+M 12,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 7,10 0 0123
+T 8,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 11,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 6,10,3 0 0135
+rB "
+^ 6,10 0 0136
+a^ "
+ha "
+_ 7,0,4 0 0137
+` 5,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 7,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 10,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 6,10,3 0 0173
+lC "
+| 4,10,3 0 0174
+or "
+ba "
+} 6,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,7,3 0 0241
+¡ "
+ct 7,9,2 0 0242
+¢ "
+Po 7,10 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 4,10,3 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 5,10 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 4,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,4 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 7,7,3 0 0277
+¿ "
+`A 9,13 0 0300
+À "
+'A 9,13 0 0301
+Á "
+^A 9,13 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,13 0 0305
+Å "
+AE 13,10 0 0306
+Æ "
+,C 9,10,3 0 0307
+Ç "
+`E 9,13 0 0310
+È "
+'E 9,13 0 0311
+É "
+^E 9,13 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 5,13 0 0314
+Ì "
+'I 5,13 0 0315
+Í "
+^I 5,13 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,13 0 0321
+Ñ "
+`O 10,13 0 0322
+Ò "
+'O 10,13 0 0323
+Ó "
+^O 10,13 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,12 0 0326
+Ö "
+mu 10,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,13 0 0331
+Ù "
+'U 10,13 0 0332
+Ú "
+^U 10,13 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 8,13 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 7,10,3 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 4,10 0 0354
+ì "
+'i 4,10 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 10,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 7,10,3 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX100/TR b/gnu/usr.bin/groff/devices/devX100/TR
new file mode 100644
index 000000000000..eafc811b264c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX100/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 4,1,2 0 054
+\- 9,4 0 055
+. 4,1 0 056
+/ 4,10,2 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,10 0 077
+@ 13,10,2 0 0100
+at "
+A 11,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 8,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 13,10 0 0127
+X 10,10 0 0130
+Y 9,10 0 0131
+Z 8,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 7,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 7,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 4,10 0 0146
+g 7,7,3 0 0147
+h 7,10 0 0150
+i 3,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 3,10 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 4,8 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 8,10 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 3,10 0 0246
+¦ "
+sc 7,10,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 4,10 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,10,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 6,7,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,13 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 13,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,14 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 8,10 0 0336
+Þ "
+ss 7,10 0 0337
+ß "
+`a 7,11 0 0340
+à "
+'a 7,11 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,11 0 0343
+ã "
+:a 7,10 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,11 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,11 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,11 0 0371
+ù "
+'u 7,11 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/CB b/gnu/usr.bin/groff/devices/devX75-12/CB
new file mode 100644
index 000000000000..a5d1baff2215
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+# 7,8 0 043
+sh "
+$ 7,10,2 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,9 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,2 0 056
+/ 7,8,2 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,6 0 072
+; 7,6,1 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 7,8 0 077
+@ 7,8 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,8,2 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,9,2 0 0173
+lC "
+| 7,8,2 0 0174
+or "
+ba "
+} 7,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,2 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,9 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,9 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,5 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,9 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 7,9,1 0 0274
+¼ "
+12 7,9,1 0 0275
+½ "
+34 7,9,1 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,9 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,8,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/CBI b/gnu/usr.bin/groff/devices/devX75-12/CBI
new file mode 100644
index 000000000000..764eaf778410
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+# 7,9 0 043
+sh "
+$ 7,10,2 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,8 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,2 0 056
+/ 7,9,1 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,6 0 072
+; 7,6,1 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 7,8 0 077
+@ 7,8,1 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,9,1 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,9,2 0 0173
+lC "
+| 7,8,1 0 0174
+or "
+ba "
+} 7,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,2 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,1 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,9 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,8 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,5 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,8 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 7,9 0 0274
+¼ "
+12 7,9 0 0275
+½ "
+34 7,9 0 0276
+¾ "
+r? 7,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,8,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/CI b/gnu/usr.bin/groff/devices/devX75-12/CI
new file mode 100644
index 000000000000..acc9ec864705
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,8 0 041
+" 7,8 0 042
+# 7,8 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,8 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,1 0 056
+/ 7,8,1 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,5 0 072
+; 7,5,1 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 7,8 0 077
+@ 7,8 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,8,1 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,9,2 0 0173
+lC "
+| 7,8,1 0 0174
+or "
+ba "
+} 7,9,2 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,2 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,8 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,8 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,4 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,8 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 7,9,1 0 0274
+¼ "
+12 7,9,1 0 0275
+½ "
+34 7,9,1 0 0276
+¾ "
+r? 7,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/CR b/gnu/usr.bin/groff/devices/devX75-12/CR
new file mode 100644
index 000000000000..666e837b435c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,8 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,1 0 056
+/ 7,9,1 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,5 0 072
+; 7,5,1 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 7,8 0 077
+@ 7,8 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,9,1 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,8,2 0 0173
+lC "
+| 7,8,2 0 0174
+or "
+ba "
+} 7,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,2 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,8 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,8 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,4 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,8 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 7,9,1 0 0274
+¼ "
+12 7,9,1 0 0275
+½ "
+34 7,9,1 0 0276
+¾ "
+r? 7,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,9,1 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/DESC b/gnu/usr.bin/groff/devices/devX75-12/DESC
new file mode 100644
index 000000000000..4793e599e0a6
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 75
+X11
+hor 1
+vert 1
+unitwidth 12
+postpro gxditview
diff --git a/gnu/usr.bin/groff/devices/devX75-12/HB b/gnu/usr.bin/groff/devices/devX75-12/HB
new file mode 100644
index 000000000000..b8cbb6ef55e6
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+# 8,8 0 043
+sh "
+$ 7,9,2 0 044
+Do "
+% 12,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 6,9,3 0 050
+) 6,9,3 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 4,2,2 0 054
+\- 8,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 8,9 0 077
+@ 12,9,1 0 0100
+at "
+A 8,9 0 0101
+B 9,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 7,9 0 0106
+G 10,9 0 0107
+H 9,9 0 0110
+I 4,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 10,9 0 0117
+P 8,9 0 0120
+Q 10,9 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 8,9 0 0124
+U 9,9 0 0125
+V 8,9 0 0126
+W 10,9 0 0127
+X 8,9 0 0130
+Y 8,9 0 0131
+Z 7,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 4,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 7,9 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 7,7 0 0141
+b 7,9 0 0142
+c 7,7 0 0143
+d 7,9 0 0144
+e 7,7 0 0145
+f 5,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 3,9 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 8,7 0 0166
+w 11,7 0 0167
+x 7,7 0 0170
+y 8,7,3 0 0171
+z 6,7 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 4,9,2 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 4,1,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 8,7,3 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 4,12 0 0314
+Ì "
+'I 4,12 0 0315
+Í "
+^I 4,12 0 0316
+Î "
+:I 4,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 10,9,1 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 8,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 8,9 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,10 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 8,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 8,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/HBI b/gnu/usr.bin/groff/devices/devX75-12/HBI
new file mode 100644
index 000000000000..3014c9027d7c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 13,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 5,9,3 0 050
+) 5,9,3 0 051
+* 6,9 0 052
++ 8,6 0 053
+, 3,2,2 0 054
+\- 8,4 0 055
+. 3,2 0 056
+/ 5,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 8,9 0 077
+@ 11,9,1 0 0100
+at "
+A 8,9 0 0101
+B 9,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 7,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 7,9 0 0114
+M 12,9 0 0115
+N 10,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9 0 0121
+R 9,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 10,9 0 0127
+X 9,9 0 0130
+Y 7,9 0 0131
+Z 7,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 5,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 6,7 0 0141
+b 7,9 0 0142
+c 7,7 0 0143
+d 7,9 0 0144
+e 7,7 0 0145
+f 5,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 3,9 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 10,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 4,9,2 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 10,6 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 4,1,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 10,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,7,2 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 10,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 8,6 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 7,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 6,10 0 0340
+à "
+'a 6,10 0 0341
+á "
+^a 6,10 0 0342
+â "
+~a 6,10 0 0343
+ã "
+:a 6,9 0 0344
+ä "
+oa 6,10 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 8,6 0 0367
+÷ "
+/o 7,8 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 7,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/HI b/gnu/usr.bin/groff/devices/devX75-12/HI
new file mode 100644
index 000000000000..587e1451eb29
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 3,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 5,9 0 052
++ 7,6 0 053
+, 3,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 8,6 0 074
+= 7,5 0 075
+eq "
+> 8,6 0 076
+? 7,9 0 077
+@ 12,9,1 0 0100
+at "
+A 9,9 0 0101
+B 8,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 8,9 0 0107
+H 10,9 0 0110
+I 4,9 0 0111
+J 8,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 12,9 0 0115
+N 10,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9 0 0121
+R 8,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 9,9 0 0125
+V 8,9 0 0126
+W 11,9 0 0127
+X 9,9 0 0130
+Y 8,9 0 0131
+Z 9,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 4,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 3,9 0 0140
+oq "
+a 7,7 0 0141
+b 7,9 0 0142
+c 6,7 0 0143
+d 7,9 0 0144
+e 6,7 0 0145
+f 3,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 4,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 6,7,3 0 0171
+z 6,7 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 4,9,2 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 3,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,8 0 0262
+² "
+S3 4,8 0 0263
+³ "
+aa 2,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,9,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,1,3 0 0270
+¸ "
+S1 4,8 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 4,12 0 0314
+Ì "
+'I 4,12 0 0315
+Í "
+^I 4,12 0 0316
+Î "
+:I 4,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 10,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 10,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 8,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,10 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 6,10 0 0350
+è "
+'e 6,10 0 0351
+é "
+^e 6,10 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 6,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/HR b/gnu/usr.bin/groff/devices/devX75-12/HR
new file mode 100644
index 000000000000..86958ed6b56f
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+# 7,8 0 043
+sh "
+$ 6,9,2 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 3,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 5,9 0 052
++ 7,6 0 053
+, 4,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 7,9 0 077
+@ 12,9,1 0 0100
+at "
+A 9,9 0 0101
+B 8,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 3,9 0 0111
+J 7,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 10,9 0 0117
+P 8,9 0 0120
+Q 10,9 0 0121
+R 8,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 11,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 3,9,3 0 0133
+lB "
+\ 4,9 0 0134
+rs "
+] 3,9,3 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 7,7 0 0141
+b 7,9 0 0142
+c 7,7 0 0143
+d 7,9 0 0144
+e 7,7 0 0145
+f 3,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 4,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 4,9,3 0 0173
+lC "
+| 3,9,3 0 0174
+or "
+ba "
+} 4,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 3,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 3,9,2 0 0246
+¦ "
+sc 6,9,3 0 0247
+§ "
+ad 3,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,8 0 0262
+² "
+S3 4,8 0 0263
+³ "
+aa 2,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,1,3 0 0270
+¸ "
+S1 4,8 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 3,12 0 0314
+Ì "
+'I 3,12 0 0315
+Í "
+^I 3,12 0 0316
+Î "
+:I 3,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 10,10,1 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,10 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 7,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/Makefile b/gnu/usr.bin/groff/devices/devX75-12/Makefile
new file mode 100644
index 000000000000..705e3ea2a951
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/Makefile
@@ -0,0 +1,10 @@
+# Makefile for devX75-12
+
+DEVICE= X75-12
+FONTFILES= CB CBI CI CR HB HBI HI HR NB NBI NI NR S TB TBI TI TR DESC
+
+NOOBJ= noobj
+
+clean cleandir:
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devX75-12/NB b/gnu/usr.bin/groff/devices/devX75-12/NB
new file mode 100644
index 000000000000..5fea01717d2f
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 8,9 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 13,9 0 045
+& 11,9 0 046
+' 3,9 0 047
+( 5,9,2 0 050
+) 5,9,2 0 051
+* 6,9 0 052
++ 8,7 0 053
+, 4,2,2 0 054
+\- 7,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 5,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 7,9 0 077
+@ 11,9 0 0100
+at "
+A 11,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 10,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 10,9 0 0107
+H 11,9 0 0110
+I 5,9 0 0111
+J 8,9 0 0112
+K 10,9 0 0113
+L 9,9 0 0114
+M 12,9 0 0115
+N 11,9 0 0116
+O 10,9 0 0117
+P 9,9 0 0120
+Q 10,9,2 0 0121
+R 10,9 0 0122
+S 8,9 0 0123
+T 9,9 0 0124
+U 10,9 0 0125
+V 11,9 0 0126
+W 14,9 0 0127
+X 10,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 5,9,2 0 0133
+lB "
+\ 6,9 0 0134
+rs "
+] 5,9,2 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 8,6 0 0141
+b 8,9 0 0142
+c 7,6 0 0143
+d 9,9 0 0144
+e 7,6 0 0145
+f 5,9 0 0146
+g 7,7,3 0 0147
+h 9,9 0 0150
+i 5,9 0 0151
+j 3,9,3 0 0152
+k 8,9 0 0153
+l 5,9 0 0154
+m 13,6 0 0155
+n 9,6 0 0156
+o 8,6 0 0157
+p 8,6,3 0 0160
+q 8,6,3 0 0161
+r 6,6 0 0162
+s 6,6 0 0163
+t 5,9 0 0164
+u 9,6 0 0165
+v 7,6 0 0166
+w 11,6 0 0167
+x 8,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 5,9,2 0 0173
+lC "
+| 8,9 0 0174
+or "
+ba "
+} 5,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 8,9 0 0246
+¦ "
+sc 6,9,1 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 10,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 6,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 5,9 0 0264
+´ "
+µ 9,6,3 0 0265
+ps 10,9 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 11,12 0 0300
+À "
+'A 11,12 0 0301
+Á "
+^A 11,12 0 0302
+Â "
+~A 11,12 0 0303
+Ã "
+:A 11,12 0 0304
+Ä "
+oA 11,12 0 0305
+Å "
+AE 14,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 10,9 0 0320
+Ð "
+~N 11,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 10,9 0 0330
+Ø "
+`U 10,12 0 0331
+Ù "
+'U 10,12 0 0332
+Ú "
+^U 10,12 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 8,9 0 0337
+ß "
+`a 8,9 0 0340
+à "
+'a 8,9 0 0341
+á "
+^a 8,9 0 0342
+â "
+~a 8,9 0 0343
+ã "
+:a 8,9 0 0344
+ä "
+oa 8,9 0 0345
+å "
+ae 11,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 5,9 0 0354
+ì "
+'i 5,9 0 0355
+í "
+^i 5,9 0 0356
+î "
+:i 5,9 0 0357
+ï "
+Sd 8,9 0 0360
+ð "
+~n 9,9 0 0361
+ñ "
+`o 8,9 0 0362
+ò "
+'o 8,9 0 0363
+ó "
+^o 8,9 0 0364
+ô "
+~o 8,9 0 0365
+õ "
+:o 8,9 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 8,7,1 0 0370
+ø "
+`u 9,9 0 0371
+ù "
+'u 9,9 0 0372
+ú "
+^u 9,9 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 8,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/NBI b/gnu/usr.bin/groff/devices/devX75-12/NBI
new file mode 100644
index 000000000000..0da124adf093
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,9 0 041
+" 6,9 0 042
+# 8,8 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 12,9 0 045
+& 12,9 0 046
+' 3,9 0 047
+( 5,9,2 0 050
+) 5,9,2 0 051
+* 6,9 0 052
++ 8,7 0 053
+, 3,2,2 0 054
+\- 8,4 0 055
+. 3,2 0 056
+/ 6,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 6,9 0 077
+@ 11,9 0 0100
+at "
+A 10,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 10,9 0 0104
+E 9,9 0 0105
+F 8,9 0 0106
+G 10,9 0 0107
+H 11,9 0 0110
+I 6,9 0 0111
+J 8,9 0 0112
+K 10,9 0 0113
+L 9,9 0 0114
+M 14,9 0 0115
+N 11,9 0 0116
+O 10,9 0 0117
+P 9,9 0 0120
+Q 10,9,2 0 0121
+R 10,9 0 0122
+S 8,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 10,9 0 0126
+W 13,9 0 0127
+X 11,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 6,9,2 0 0133
+lB "
+\ 6,9 0 0134
+rs "
+] 6,9,2 0 0135
+rB "
+^ 8,9 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 8,6 0 0141
+b 7,9 0 0142
+c 6,6 0 0143
+d 8,9 0 0144
+e 7,6 0 0145
+f 5,9,3 0 0146
+g 7,8,3 0 0147
+h 8,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 8,9 0 0153
+l 4,9 0 0154
+m 12,6 0 0155
+n 8,6 0 0156
+o 7,6 0 0157
+p 8,6,3 0 0160
+q 8,6,3 0 0161
+r 6,6 0 0162
+s 7,6 0 0163
+t 5,8 0 0164
+u 8,6 0 0165
+v 7,6 0 0166
+w 11,6 0 0167
+x 7,6 0 0170
+y 6,6,3 0 0171
+z 7,6 0 0172
+{ 6,9,2 0 0173
+lC "
+| 8,9 0 0174
+or "
+ba "
+} 6,9,2 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,6,3 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 10,9 0 0245
+¥ "
+bb 8,9 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 4,9 0 0250
+¨ "
+co 10,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 10,9 0 0256
+® "
+a- 5,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 8,6,3 0 0265
+ps 8,9 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 6,6,3 0 0277
+¿ "
+`A 10,12 0 0300
+À "
+'A 10,12 0 0301
+Á "
+^A 10,12 0 0302
+Â "
+~A 10,12 0 0303
+Ã "
+:A 10,12 0 0304
+Ä "
+oA 10,12 0 0305
+Å "
+AE 12,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 6,12 0 0314
+Ì "
+'I 6,12 0 0315
+Í "
+^I 6,12 0 0316
+Î "
+:I 6,12 0 0317
+Ï "
+-D 10,9 0 0320
+Ð "
+~N 11,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 10,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9,2 0 0337
+ß "
+`a 8,9 0 0340
+à "
+'a 8,9 0 0341
+á "
+^a 8,10 0 0342
+â "
+~a 8,9 0 0343
+ã "
+:a 8,9 0 0344
+ä "
+oa 8,10 0 0345
+å "
+ae 11,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,10 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 7,9 0 0360
+ð "
+~n 8,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,6 0 0370
+ø "
+`u 8,9 0 0371
+ù "
+'u 8,9 0 0372
+ú "
+^u 8,10 0 0373
+û "
+:u 8,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 8,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/NI b/gnu/usr.bin/groff/devices/devX75-12/NI
new file mode 100644
index 000000000000..05ee8cdbd82e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 8,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 10,9 0 045
+& 10,9 0 046
+' 3,9 0 047
+( 5,9,2 0 050
+) 5,9,2 0 051
+* 7,9 0 052
++ 8,7 0 053
+, 2,2,1 0 054
+\- 7,4 0 055
+. 2,2 0 056
+/ 8,9,1 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 3,6 0 072
+; 3,6,1 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 5,9 0 077
+@ 11,9 0 0100
+at "
+A 8,9 0 0101
+B 8,9 0 0102
+C 9,9 0 0103
+D 10,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 8,9 0 0114
+M 13,9 0 0115
+N 11,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,2 0 0121
+R 10,9 0 0122
+S 9,9 0 0123
+T 8,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 13,9 0 0127
+X 10,9 0 0130
+Y 8,9 0 0131
+Z 9,9 0 0132
+[ 6,9,2 0 0133
+lB "
+\ 8,9 0 0134
+rs "
+] 6,9,2 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 8,6 0 0141
+b 7,9 0 0142
+c 6,6 0 0143
+d 8,9 0 0144
+e 6,6 0 0145
+f 4,9,3 0 0146
+g 6,7,3 0 0147
+h 8,9 0 0150
+i 4,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 4,9 0 0154
+m 12,6 0 0155
+n 8,6 0 0156
+o 6,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 5,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 8,6 0 0165
+v 7,6 0 0166
+w 10,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 5,9,2 0 0173
+lC "
+| 6,9 0 0174
+or "
+ba "
+} 5,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 9,8 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 6,9 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 10,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 10,9 0 0256
+® "
+a- 5,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 8,6,3 0 0265
+ps 9,9 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 4,9 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 5,7,2 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,12 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 10,9 0 0320
+Ð "
+~N 11,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,12 0 0334
+Ü "
+'Y 8,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 8,9,3 0 0337
+ß "
+`a 8,9 0 0340
+à "
+'a 8,9 0 0341
+á "
+^a 8,9 0 0342
+â "
+~a 8,9 0 0343
+ã "
+:a 8,9 0 0344
+ä "
+oa 8,10 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,9 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 8,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,9 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 8,9 0 0371
+ù "
+'u 8,9 0 0372
+ú "
+^u 8,9 0 0373
+û "
+:u 8,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 8,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/NR b/gnu/usr.bin/groff/devices/devX75-12/NR
new file mode 100644
index 000000000000..a1df4867901a
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 8,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 4,9,2 0 050
+) 4,9,2 0 051
+* 6,9 0 052
++ 8,7 0 053
+, 4,2,1 0 054
+\- 7,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 4,6 0 072
+; 4,6,1 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 5,9 0 077
+@ 10,9 0 0100
+at "
+A 10,9 0 0101
+B 8,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 10,9 0 0107
+H 10,9 0 0110
+I 6,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 8,9 0 0114
+M 12,9 0 0115
+N 10,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 7,9 0 0123
+T 8,9 0 0124
+U 10,9 0 0125
+V 10,9 0 0126
+W 12,9 0 0127
+X 9,9 0 0130
+Y 10,9 0 0131
+Z 7,9 0 0132
+[ 4,9,2 0 0133
+lB "
+\ 6,9 0 0134
+rs "
+] 4,9,2 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 4,9 0 0140
+oq "
+a 7,6 0 0141
+b 6,9 0 0142
+c 6,6 0 0143
+d 7,9 0 0144
+e 6,6 0 0145
+f 4,9 0 0146
+g 7,7,3 0 0147
+h 8,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 7,9 0 0153
+l 4,9 0 0154
+m 12,6 0 0155
+n 8,6 0 0156
+o 6,6 0 0157
+p 7,6,3 0 0160
+q 6,6,3 0 0161
+r 6,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 8,6 0 0165
+v 6,6 0 0166
+w 10,6 0 0167
+x 7,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 4,9,2 0 0173
+lC "
+| 8,9 0 0174
+or "
+ba "
+} 4,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,2 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,9 0 0245
+¥ "
+bb 8,9 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 4,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 5,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 8,6,3 0 0265
+ps 8,9,2 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 5,7,2 0 0277
+¿ "
+`A 10,12 0 0300
+À "
+'A 10,12 0 0301
+Á "
+^A 10,12 0 0302
+Â "
+~A 10,12 0 0303
+Ã "
+:A 10,12 0 0304
+Ä "
+oA 10,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,12 0 0313
+Ë "
+`I 6,12 0 0314
+Ì "
+'I 6,12 0 0315
+Í "
+^I 6,12 0 0316
+Î "
+:I 6,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 10,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 10,12 0 0331
+Ù "
+'U 10,12 0 0332
+Ú "
+^U 10,12 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 10,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 10,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,9 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 8,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 6,7,1 0 0370
+ø "
+`u 8,9 0 0371
+ù "
+'u 8,9 0 0372
+ú "
+^u 8,9 0 0373
+û "
+:u 8,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/S b/gnu/usr.bin/groff/devices/devX75-12/S
new file mode 100644
index 000000000000..e93a2057341a
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+fa 9,9 0 042
+# 7,9 0 043
+sh "
+te 7,9 0 044
+% 10,9 0 045
+& 10,9 0 046
+st 6,6 0 047
+( 5,9,3 0 050
+) 5,9,3 0 051
+** 6,7 0 052
++ 7,6 0 053
+pl "
+, 3,1,2 0 054
+\- 7,4 0 055
+mi "
+. 3,1 0 056
+/ 3,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 6,9 0 077
+=~ 7,6 0 0100
+*A 9,9 0 0101
+*B 8,9 0 0102
+*X 9,9 0 0103
+*D 8,9 0 0104
+*E 8,9 0 0105
+*F 10,9 0 0106
+*G 8,9 0 0107
+*Y 9,9 0 0110
+*I 4,9 0 0111
++h 8,9 0 0112
+*K 9,9 0 0113
+*L 9,9 0 0114
+*M 11,9 0 0115
+*N 9,9 0 0116
+*O 9,9 0 0117
+*P 9,9 0 0120
+*H 9,9 0 0121
+*R 7,9 0 0122
+*S 7,9 0 0123
+*T 8,9 0 0124
+--- 9,9 0 0125
+ts 7,6,3 0 0126
+*W 10,9 0 0127
+*C 8,9 0 0130
+*Q 10,9 0 0131
+*Z 8,9 0 0132
+[ 5,9,3 0 0133
+lB "
+tf 9,6 0 0134
+3d "
+] 5,9,3 0 0135
+rB "
+pp 8,9 0 0136
+_ 6,0,3 0 0137
+rn 6,12 0 0140
+*a 8,6 0 0141
+*b 7,10,3 0 0142
+*x 7,6,3 0 0143
+*d 7,10 0 0144
+*e 6,6 0 0145
+*f 8,8,3 0 0146
+*g 7,6,3 0 0147
+*y 8,6,3 0 0150
+*i 3,6 0 0151
++f 8,6,3 0 0152
+*k 7,6 0 0153
+*l 7,9 0 0154
+*m 8,6,3 0 0155
+µ "
+*n 7,6 0 0156
+*o 7,6 0 0157
+*p 7,6 0 0160
+*h 7,9 0 0161
+*r 7,6,3 0 0162
+*s 8,6 0 0163
+*t 6,6 0 0164
+*u 8,6 0 0165
++p 9,7 0 0166
+*w 9,6 0 0167
+*c 6,11,3 0 0170
+*q 9,6,3 0 0171
+*z 6,10,3 0 0172
+lC 6,9,3 0 0173
+{ "
+ba 3,9,3 0 0174
+or "
+| "
+rC 6,9,3 0 0175
+} "
+ap 7,5 0 0176
+*U 8,9 0 0241
+fm 3,9 0 0242
+<= 7,7 0 0243
+f/ 4,9 0 0244
+if 9,5 0 0245
+Fn 6,9,3 0 0246
+CL 9,6,1 0 0247
+DI 7,6 0 0250
+HE 9,6 0 0251
+SP 9,6,1 0 0252
+<> 13,6 0 0253
+<- 12,6 0 0254
+ua 7,12,4 0 0255
+arrowverttp "
+-> 12,6 0 0256
+da 7,12,3 0 0257
+arrowvertbt "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+sd 5,9 0 0262
+>= 7,7 0 0263
+mu 7,6 0 0264
+× "
+pt 9,5 0 0265
+pd 6,10 0 0266
+bu 6,5 0 0267
+di 7,6 0 0270
+÷ "
+!= 7,7 0 0271
+== 7,6 0 0272
+~= 7,6 0 0273
+~~ "
+--- 11,1 0 0274
+arrowvertex 7,12,4 0 0275
+an 13,4 0 0276
+CR 8,8 0 0277
+Ah 10,9 0 0300
+Im 9,10,1 0 0301
+Re 10,10 0 0302
+wp 10,8,3 0 0303
+c* 10,9 0 0304
+c+ 10,9 0 0305
+es 10,9 0 0306
+ca 10,6 0 0307
+cu 10,6 0 0310
+sp 9,6 0 0311
+ip 9,6,2 0 0312
+--- 9,7,1 0 0313
+sb 9,6 0 0314
+ib 9,6,2 0 0315
+mo 8,6 0 0316
+nm 8,7,1 0 0317
+/_ 10,9 0 0320
+gr 9,9 0 0321
+rg 10,9 0 0322
+co 10,9 0 0323
+tm 11,9 0 0324
+--- 10,10,1 0 0325
+sr 7,12 0 0326
+md 3,4 0 0327
+no 9,4 0 0330
+¬ "
+AN 8,6 0 0331
+OR 8,6 0 0332
+hA 13,6 0 0333
+lA 12,6 0 0334
+uA 8,11,1 0 0335
+rA 12,6 0 0336
+dA 8,12 0 0337
+lz 6,9 0 0340
+la 4,10,1 0 0341
+--- 10,9 0 0342
+--- 10,9 0 0343
+--- 10,9 0 0344
+--- 9,10,1 0 0345
+parenlefttp 5,12,4 0 0346
+parenleftex 5,12,4 0 0347
+parenleftbt 5,12,4 0 0350
+bracketlefttp 5,12,4 0 0351
+lc "
+bracketleftex 5,12,4 0 0352
+bracketleftbt 5,12,3 0 0353
+lf "
+bracelefttp 6,12,4 0 0354
+lt "
+braceleftmid 6,12,4 0 0355
+lk "
+braceleftbt 6,12,3 0 0356
+lb "
+bracerightex 6,12,4 0 0357
+braceleftex "
+bv "
+--- 10,11 0 0360
+ra 4,10,2 0 0361
+is 4,12,3 0 0362
+--- 9,12,4 0 0363
+--- 9,12,4 0 0364
+--- 9,12,3 0 0365
+parenrighttp 5,12,4 0 0366
+parenrightex 5,12,4 0 0367
+parenrightbt 5,12,4 0 0370
+bracketrighttp 5,12,4 0 0371
+rc "
+bracketrightex 5,12,4 0 0372
+bracketrightbt 5,12,3 0 0373
+rf "
+bracerighttp 6,12,4 0 0374
+rt "
+bracerightmid 6,12,4 0 0375
+rk "
+bracerightbt 6,12,3 0 0376
+rb "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/TB b/gnu/usr.bin/groff/devices/devX75-12/TB
new file mode 100644
index 000000000000..348d388104a4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+# 6,9 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 12,9 0 045
+& 10,9 0 046
+' 4,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 4,2,2 0 054
+\- 8,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 8,6 0 076
+? 7,9 0 077
+@ 12,9,2 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 7,9,1 0 0112
+K 10,9 0 0113
+L 8,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 7,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 12,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 8,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 3,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 7,9 0 0136
+a^ "
+ha "
+_ 6,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 7,6 0 0141
+b 6,9 0 0142
+c 6,6 0 0143
+d 6,9 0 0144
+e 7,6 0 0145
+f 4,9 0 0146
+g 6,6,3 0 0147
+h 6,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 3,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 7,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 5,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 9,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 5,9,3 0 0173
+lC "
+| 3,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 6,7,2 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 8,9 0 0245
+¥ "
+bb 3,9,3 0 0246
+¦ "
+sc 6,9,3 0 0247
+§ "
+ad 4,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 4,9 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 6,6,3 0 0265
+ps 8,9,3 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 4,9 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 9,10,1 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 8,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 8,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/TBI b/gnu/usr.bin/groff/devices/devX75-12/TBI
new file mode 100644
index 000000000000..02793a58073a
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,9 0 041
+" 7,9 0 042
+# 7,9 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 12,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 6,9,2 0 050
+) 6,9,2 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 4,2,1 0 054
+\- 8,4 0 055
+. 4,2 0 056
+/ 5,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 5,6 0 072
+; 5,6,1 0 073
+< 9,7 0 074
+= 8,5 0 075
+eq "
+> 9,7 0 076
+? 6,9 0 077
+@ 12,9,1 0 0100
+at "
+A 8,9 0 0101
+B 8,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 6,9,1 0 0112
+K 8,9 0 0113
+L 8,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,3 0 0121
+R 8,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 10,9 0 0125
+V 8,9 0 0126
+W 11,9 0 0127
+X 8,9 0 0130
+Y 7,9 0 0131
+Z 7,9 0 0132
+[ 6,9,2 0 0133
+lB "
+\ 5,9 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 8,9 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 5,9 0 0140
+oq "
+a 7,6 0 0141
+b 6,9 0 0142
+c 5,6 0 0143
+d 6,9 0 0144
+e 6,6 0 0145
+f 3,9,3 0 0146
+g 5,6,3 0 0147
+h 6,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 6,9 0 0153
+l 4,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 5,6 0 0162
+s 5,6 0 0163
+t 3,7 0 0164
+u 7,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6,1 0 0172
+{ 6,9,2 0 0173
+lC "
+| 4,9 0 0174
+or "
+ba "
+} 6,9,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 6,8,2 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 8,7 0 0244
+¤ "
+Ye 6,9 0 0245
+¥ "
+bb 4,9 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 6,6,3 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,12 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 12,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 9,10,1 0 0330
+Ø "
+`U 10,12 0 0331
+Ù "
+'U 10,12 0 0332
+Ú "
+^U 10,12 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 7,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9,3 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 10,6 0 0346
+æ "
+,c 5,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 6,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/TI b/gnu/usr.bin/groff/devices/devX75-12/TI
new file mode 100644
index 000000000000..dd79bd1d5378
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+# 6,9 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 10,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 6,9 0 052
++ 8,6 0 053
+, 3,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 4,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,9 0 077
+@ 12,9,1 0 0100
+at "
+A 8,9 0 0101
+B 8,9 0 0102
+C 7,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 8,9 0 0107
+H 9,9 0 0110
+I 5,9 0 0111
+J 5,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 7,9 0 0117
+P 8,9 0 0120
+Q 7,9,2 0 0121
+R 8,9 0 0122
+S 6,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 7,9 0 0126
+W 10,9 0 0127
+X 8,9 0 0130
+Y 7,9 0 0131
+Z 7,9 0 0132
+[ 5,9,2 0 0133
+lB "
+\ 3,9 0 0134
+rs "
+] 5,9,2 0 0135
+rB "
+^ 5,9 0 0136
+a^ "
+ha "
+_ 6,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 6,6 0 0141
+b 6,9 0 0142
+c 5,6 0 0143
+d 6,9 0 0144
+e 6,6 0 0145
+f 4,9,3 0 0146
+g 5,6,3 0 0147
+h 6,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 4,6 0 0162
+s 5,6 0 0163
+t 4,7 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 9,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 5,6 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,6,3 0 0241
+¡ "
+ct 6,8,2 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 6,9 0 0245
+¥ "
+bb 4,9,3 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 4,9 0 0252
+ª "
+Fo 6,6 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 6,6,3 0 0265
+ps 7,9,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 3,9 0 0271
+¹ "
+Om 4,9 0 0272
+º "
+Fc 6,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 6,6,3 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 7,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 7,12 0 0322
+Ò "
+'O 7,12 0 0323
+Ó "
+^O 7,12 0 0324
+Ô "
+~O 7,12 0 0325
+Õ "
+:O 7,11 0 0326
+Ö "
+mu 8,6 0 0327
+× "
+/O 7,10,1 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 7,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 6,9,3 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,9 0 0356
+î "
+:i 4,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 8,6 0 0367
+÷ "
+/o 6,7,1 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,8,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75-12/TR b/gnu/usr.bin/groff/devices/devX75-12/TR
new file mode 100644
index 000000000000..da7c961a1e93
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75-12/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+# 6,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 9,9 0 045
+& 10,9 0 046
+' 4,9 0 047
+( 5,9,3 0 050
+) 5,9,3 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 3,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 3,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 8,6 0 074
+= 7,5 0 075
+eq "
+> 8,6 0 076
+? 5,9 0 077
+@ 11,9,2 0 0100
+at "
+A 9,9 0 0101
+B 8,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 4,9 0 0111
+J 4,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 7,9 0 0120
+Q 9,9,2 0 0121
+R 8,9 0 0122
+S 7,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 12,9 0 0127
+X 8,9 0 0130
+Y 9,9 0 0131
+Z 8,9 0 0132
+[ 5,9,3 0 0133
+lB "
+\ 3,9 0 0134
+rs "
+] 5,9,3 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 6,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 6,6 0 0141
+b 6,9 0 0142
+c 5,6 0 0143
+d 6,9 0 0144
+e 6,6 0 0145
+f 3,9 0 0146
+g 6,6,3 0 0147
+h 6,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 4,6 0 0162
+s 6,6 0 0163
+t 4,7 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 9,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 6,9,3 0 0173
+lC "
+| 3,9 0 0174
+or "
+ba "
+} 6,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 6,9 0 0245
+¥ "
+bb 3,9 0 0246
+¦ "
+sc 6,9,3 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 6,6,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 5,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 4,12 0 0314
+Ì "
+'I 4,12 0 0315
+Í "
+^I 4,12 0 0316
+Î "
+:I 4,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 9,10 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 7,9 0 0336
+Þ "
+ss 6,9 0 0337
+ß "
+`a 6,9 0 0340
+à "
+'a 6,9 0 0341
+á "
+^a 6,9 0 0342
+â "
+~a 6,9 0 0343
+ã "
+:a 6,8 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,8,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/CB b/gnu/usr.bin/groff/devices/devX75/CB
new file mode 100644
index 000000000000..5583135951a4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,6 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,6 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,1 0 050
+) 6,7,1 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,6 0 077
+@ 6,7,1 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,1 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,1 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,1 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,1 0 0173
+lC "
+| 6,7,2 0 0174
+or "
+ba "
+} 6,7,1 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,7 0 0245
+¥ "
+bb 6,7,2 0 0246
+¦ "
+sc 6,7,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,7 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,7,1 0 0266
+¶ "
+md 6,5 0 0267
+· "
+ac 6,1,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,7 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,4,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,9 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,9 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,9 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,9 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,6,1 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,9 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,8 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,8 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,8,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/CBI b/gnu/usr.bin/groff/devices/devX75/CBI
new file mode 100644
index 000000000000..e6281f44b44a
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,7 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,2 0 050
+) 6,7,2 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,7 0 077
+@ 6,7,1 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,1 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,2 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,2 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,2 0 0173
+lC "
+| 6,7,1 0 0174
+or "
+ba "
+} 6,7,2 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,6 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,6 0 0245
+¥ "
+bb 6,7,1 0 0246
+¦ "
+sc 6,7,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,6 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,7,1 0 0266
+¶ "
+md 6,4 0 0267
+· "
+ac 6,0,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,6 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,8 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,8 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,8 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,8 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,7 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,8 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,7 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/CI b/gnu/usr.bin/groff/devices/devX75/CI
new file mode 100644
index 000000000000..f19be187d1ea
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,7 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,1 0 050
+) 6,7,1 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,6 0 077
+@ 6,7 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,2 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,1 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,1 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,1 0 0173
+lC "
+| 6,7,1 0 0174
+or "
+ba "
+} 6,7,1 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,6 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,6 0 0245
+¥ "
+bb 6,7,2 0 0246
+¦ "
+sc 6,7,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,7 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,7,1 0 0266
+¶ "
+md 6,4 0 0267
+· "
+ac 6,0,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,7 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,4,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,8 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,8 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,8 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,8 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,6 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,8 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,7 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/CR b/gnu/usr.bin/groff/devices/devX75/CR
new file mode 100644
index 000000000000..8bb40b2753ac
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,6 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,2 0 050
+) 6,7,2 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,6 0 077
+@ 6,7,1 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,1 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,2 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,2 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,2 0 0173
+lC "
+| 6,7,2 0 0174
+or "
+ba "
+} 6,7,2 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,7 0 0245
+¥ "
+bb 6,7,2 0 0246
+¦ "
+sc 6,6,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,6 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,6,1 0 0266
+¶ "
+md 6,4 0 0267
+· "
+ac 6,1,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,6 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,4,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,8 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,8 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,8 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,8 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,6 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,8 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,7 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/DESC b/gnu/usr.bin/groff/devices/devX75/DESC
new file mode 100644
index 000000000000..172170c9c0b5
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 75
+X11
+hor 1
+vert 1
+unitwidth 10
+postpro gxditview
diff --git a/gnu/usr.bin/groff/devices/devX75/HB b/gnu/usr.bin/groff/devices/devX75/HB
new file mode 100644
index 000000000000..26894e07f733
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 5,8 0 042
+# 6,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 8,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 4,8,2 0 050
+) 4,8,2 0 051
+* 4,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 7,4 0 055
+. 3,2 0 056
+/ 4,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 5,6 0 074
+= 6,5 0 075
+eq "
+> 5,6 0 076
+? 6,8 0 077
+@ 11,7,2 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 8,8 0 0103
+D 7,8 0 0104
+E 6,8 0 0105
+F 6,8 0 0106
+G 8,8 0 0107
+H 7,8 0 0110
+I 3,8 0 0111
+J 6,8 0 0112
+K 7,8 0 0113
+L 6,8 0 0114
+M 10,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 8,8 0 0126
+W 11,8 0 0127
+X 8,8 0 0130
+Y 9,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 4,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 5,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 6,6 0 0141
+b 6,8 0 0142
+c 5,6 0 0143
+d 6,8 0 0144
+e 6,6 0 0145
+f 4,8 0 0146
+g 6,6,2 0 0147
+h 6,8 0 0150
+i 3,8 0 0151
+j 3,8,2 0 0152
+k 6,8 0 0153
+l 3,8 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,2 0 0160
+q 6,6,2 0 0161
+r 4,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 7,6 0 0170
+y 6,6,2 0 0171
+z 6,6 0 0172
+{ 5,8,2 0 0173
+lC "
+| 3,8,2 0 0174
+or "
+ba "
+} 5,8,2 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 6,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 3,8,2 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 7,4 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 3,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 6,6,2 0 0265
+ps 6,8,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 7,4 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 6,11 0 0310
+È "
+'E 6,11 0 0311
+É "
+^E 6,11 0 0312
+Ê "
+:E 6,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 9,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 6,8 0 0337
+ß "
+`a 6,9 0 0340
+à "
+'a 6,9 0 0341
+á "
+^a 6,9 0 0342
+â "
+~a 6,9 0 0343
+ã "
+:a 6,9 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,9 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,9 0 0374
+ü "
+'y 6,9,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 6,9,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/HBI b/gnu/usr.bin/groff/devices/devX75/HBI
new file mode 100644
index 000000000000..6488003417a4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+# 7,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 5,8,2 0 050
+) 5,8,2 0 051
+* 6,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 7,4 0 055
+. 3,2 0 056
+/ 5,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 7,6 0 076
+? 6,8 0 077
+@ 10,7,2 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 8,8 0 0104
+E 6,8 0 0105
+F 5,8 0 0106
+G 8,8 0 0107
+H 7,8 0 0110
+I 3,8 0 0111
+J 6,8 0 0112
+K 8,8 0 0113
+L 6,8 0 0114
+M 10,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8 0 0121
+R 8,8 0 0122
+S 7,8 0 0123
+T 6,8 0 0124
+U 7,8 0 0125
+V 8,8 0 0126
+W 10,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 4,8 0 0140
+oq "
+a 6,6 0 0141
+b 6,8 0 0142
+c 5,6 0 0143
+d 6,8 0 0144
+e 6,6 0 0145
+f 3,8 0 0146
+g 6,6,2 0 0147
+h 6,8 0 0150
+i 3,8 0 0151
+j 3,8,2 0 0152
+k 6,8 0 0153
+l 3,8 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,2 0 0160
+q 6,6,2 0 0161
+r 4,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 5,6 0 0170
+y 6,6,2 0 0171
+z 5,6 0 0172
+{ 5,8,2 0 0173
+lC "
+| 4,8,2 0 0174
+or "
+ba "
+} 5,8,2 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 7,7 0 0243
+£ "
+Cs 6,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 4,8,1 0 0246
+¦ "
+sc 7,8,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 6,6,2 0 0265
+ps 7,8,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,1,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 7,8,2 0 0307
+Ç "
+`E 6,11 0 0310
+È "
+'E 6,11 0 0311
+É "
+^E 6,11 0 0312
+Ê "
+:E 6,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8 0 0337
+ß "
+`a 6,9 0 0340
+à "
+'a 6,9 0 0341
+á "
+^a 6,9 0 0342
+â "
+~a 6,9 0 0343
+ã "
+:a 6,8 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 8,6 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,9,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 6,8,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/HI b/gnu/usr.bin/groff/devices/devX75/HI
new file mode 100644
index 000000000000..07509511fac5
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 4,8 0 042
+# 7,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 4,8,2 0 050
+) 4,8,2 0 051
+* 4,8 0 052
++ 6,6 0 053
+, 3,1,2 0 054
+\- 7,4 0 055
+. 3,1 0 056
+/ 3,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 6,6 0 074
+= 7,5 0 075
+eq "
+> 6,6 0 076
+? 6,8 0 077
+@ 11,8,2 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 8,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 6,8 0 0106
+G 8,8 0 0107
+H 8,8 0 0110
+I 3,8 0 0111
+J 5,8 0 0112
+K 7,8 0 0113
+L 5,8 0 0114
+M 9,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 5,8 0 0124
+U 8,8 0 0125
+V 7,8 0 0126
+W 10,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 3,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 5,6 0 0141
+b 5,8 0 0142
+c 5,6 0 0143
+d 5,8 0 0144
+e 5,6 0 0145
+f 4,8 0 0146
+g 5,6,2 0 0147
+h 6,8 0 0150
+i 2,8 0 0151
+j 2,8,2 0 0152
+k 5,8 0 0153
+l 2,8 0 0154
+m 8,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 5,6,2 0 0160
+q 5,6,2 0 0161
+r 4,6 0 0162
+s 5,6 0 0163
+t 4,8 0 0164
+u 5,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 6,6 0 0170
+y 5,6,2 0 0171
+z 5,6 0 0172
+{ 4,8,2 0 0173
+lC "
+| 3,8,2 0 0174
+or "
+ba "
+} 4,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 6,7 0 0244
+¤ "
+Ye 6,8 0 0245
+¥ "
+bb 3,8,2 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 3,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 5,6,2 0 0265
+ps 6,8,2 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 3,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 9,8,1 0 0274
+¼ "
+12 9,8,1 0 0275
+½ "
+34 9,8,1 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 6,8 0 0337
+ß "
+`a 5,9 0 0340
+à "
+'a 5,9 0 0341
+á "
+^a 5,9 0 0342
+â "
+~a 5,9 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,9 0 0345
+å "
+ae 8,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 5,9 0 0350
+è "
+'e 5,9 0 0351
+é "
+^e 5,9 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 2,9 0 0354
+ì "
+'i 2,9 0 0355
+í "
+^i 2,9 0 0356
+î "
+:i 2,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 5,9 0 0371
+ù "
+'u 5,9 0 0372
+ú "
+^u 5,9 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,9,2 0 0375
+ý "
+Tp 5,8,2 0 0376
+þ "
+:y 5,8,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/HR b/gnu/usr.bin/groff/devices/devX75/HR
new file mode 100644
index 000000000000..aeac63ed2735
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,8 0 041
+" 4,8 0 042
+# 6,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 4,8,2 0 050
+) 4,8,2 0 051
+* 4,8 0 052
++ 6,6 0 053
+, 3,1,2 0 054
+\- 7,4 0 055
+. 3,1 0 056
+/ 3,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 6,6 0 074
+= 5,5 0 075
+eq "
+> 6,6 0 076
+? 6,8 0 077
+@ 11,8,2 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 8,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 6,8 0 0106
+G 8,8 0 0107
+H 8,8 0 0110
+I 3,8 0 0111
+J 5,8 0 0112
+K 7,8 0 0113
+L 6,8 0 0114
+M 9,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 5,8 0 0124
+U 8,8 0 0125
+V 7,8 0 0126
+W 9,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 3,8,2 0 0133
+lB "
+\ 3,8 0 0134
+rs "
+] 3,8,2 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 5,6 0 0141
+b 6,8 0 0142
+c 5,6 0 0143
+d 6,8 0 0144
+e 5,6 0 0145
+f 4,8 0 0146
+g 6,6,2 0 0147
+h 6,8 0 0150
+i 2,8 0 0151
+j 2,8,1 0 0152
+k 5,8 0 0153
+l 2,8 0 0154
+m 8,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,2 0 0160
+q 6,6,2 0 0161
+r 4,6 0 0162
+s 5,6 0 0163
+t 4,8 0 0164
+u 5,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 6,6 0 0170
+y 5,6,2 0 0171
+z 5,6 0 0172
+{ 3,8,2 0 0173
+lC "
+| 3,8,2 0 0174
+or "
+ba "
+} 3,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 3,6,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 5,7 0 0244
+¤ "
+Ye 6,8 0 0245
+¥ "
+bb 3,8,2 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,8 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 3,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 5,6,2 0 0265
+ps 6,8,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 4,8 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,9,1 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 5,8 0 0337
+ß "
+`a 5,9 0 0340
+à "
+'a 5,9 0 0341
+á "
+^a 5,9 0 0342
+â "
+~a 5,9 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,9 0 0345
+å "
+ae 8,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 5,9 0 0350
+è "
+'e 5,9 0 0351
+é "
+^e 5,9 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 2,9 0 0354
+ì "
+'i 2,9 0 0355
+í "
+^i 2,9 0 0356
+î "
+:i 2,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 5,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 5,9 0 0371
+ù "
+'u 5,9 0 0372
+ú "
+^u 5,9 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,9,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 5,8,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/Makefile b/gnu/usr.bin/groff/devices/devX75/Makefile
new file mode 100644
index 000000000000..e53468a7bb4f
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/Makefile
@@ -0,0 +1,10 @@
+# Makefile for devX75
+
+DEVICE= X75
+FONTFILES= CB CBI CI CR HB HBI HI HR NB NBI NI NR S TB TBI TI TR DESC
+
+NOOBJ= noobj
+
+clean cleandir:
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devX75/NB b/gnu/usr.bin/groff/devices/devX75/NB
new file mode 100644
index 000000000000..d783d02b781d
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,8 0 041
+" 6,8 0 042
+# 8,8 0 043
+sh "
+$ 6,9,1 0 044
+Do "
+% 11,8 0 045
+& 9,8 0 046
+' 3,8 0 047
+( 5,8,2 0 050
+) 5,8,2 0 051
+* 6,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 6,4 0 055
+. 3,2 0 056
+/ 5,8 0 057
+sl "
+0 6,8 0 060
+1 5,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 5,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,5 0 072
+; 3,5,2 0 073
+< 7,6 0 074
+= 6,5 0 075
+eq "
+> 7,6 0 076
+? 6,8 0 077
+@ 10,8 0 0100
+at "
+A 8,8 0 0101
+B 8,8 0 0102
+C 8,8 0 0103
+D 9,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 10,8 0 0110
+I 5,8 0 0111
+J 7,8 0 0112
+K 9,8 0 0113
+L 7,8 0 0114
+M 12,8 0 0115
+N 9,8 0 0116
+O 8,8 0 0117
+P 8,8 0 0120
+Q 8,8,1 0 0121
+R 9,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 9,8 0 0125
+V 9,8 0 0126
+W 12,8 0 0127
+X 9,8 0 0130
+Y 9,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 5,5 0 0141
+b 7,8 0 0142
+c 6,5 0 0143
+d 7,8 0 0144
+e 6,5 0 0145
+f 5,8 0 0146
+g 6,6,2 0 0147
+h 7,8 0 0150
+i 5,8 0 0151
+j 5,8,2 0 0152
+k 6,8 0 0153
+l 5,8 0 0154
+m 11,5 0 0155
+n 7,5 0 0156
+o 7,5 0 0157
+p 7,5,2 0 0160
+q 7,5,2 0 0161
+r 5,5 0 0162
+s 5,5 0 0163
+t 4,7 0 0164
+u 7,5 0 0165
+v 7,5 0 0166
+w 10,5 0 0167
+x 7,5 0 0170
+y 7,5,2 0 0171
+z 6,5 0 0172
+{ 5,8,2 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 5,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 3,6,2 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 8,8 0 0243
+£ "
+Cs 8,6 0 0244
+¤ "
+Ye 9,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 5,8,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 9,8 0 0251
+© "
+Of 4,8 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 9,8 0 0256
+® "
+a- 5,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 4,8 0 0264
+´ "
+µ 7,5,2 0 0265
+ps 8,8 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 11,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,11 0 0313
+Ë "
+`I 5,11 0 0314
+Ì "
+'I 5,11 0 0315
+Í "
+^I 5,11 0 0316
+Î "
+:I 5,11 0 0317
+Ï "
+-D 9,8 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,11 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 9,11 0 0331
+Ù "
+'U 9,11 0 0332
+Ú "
+^U 9,11 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,11 0 0335
+Ý "
+TP 8,8 0 0336
+Þ "
+ss 8,8 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,9 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 9,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 5,8 0 0354
+ì "
+'i 5,8 0 0355
+í "
+^i 5,9 0 0356
+î "
+:i 5,8 0 0357
+ï "
+Sd 7,8 0 0360
+ð "
+~n 7,8 0 0361
+ñ "
+`o 7,8 0 0362
+ò "
+'o 7,8 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,8 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 7,6,1 0 0370
+ø "
+`u 7,8 0 0371
+ù "
+'u 7,8 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,8,2 0 0375
+ý "
+Tp 7,8,2 0 0376
+þ "
+:y 7,8,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/NBI b/gnu/usr.bin/groff/devices/devX75/NBI
new file mode 100644
index 000000000000..bdad1059941e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 5,8 0 041
+" 6,8 0 042
+# 8,7 0 043
+sh "
+$ 6,9,1 0 044
+Do "
+% 11,8 0 045
+& 10,8 0 046
+' 3,8 0 047
+( 4,8,1 0 050
+) 5,8,1 0 051
+* 6,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 7,4 0 055
+. 3,2 0 056
+/ 5,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 4,5 0 072
+; 4,5,2 0 073
+< 7,6 0 074
+= 6,5 0 075
+eq "
+> 7,6 0 076
+? 6,8 0 077
+@ 11,8 0 0100
+at "
+A 8,8 0 0101
+B 8,8 0 0102
+C 7,8 0 0103
+D 9,8 0 0104
+E 8,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 10,8 0 0110
+I 6,8 0 0111
+J 7,8 0 0112
+K 10,8 0 0113
+L 7,8 0 0114
+M 11,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 8,8 0 0120
+Q 8,8,2 0 0121
+R 9,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 8,8 0 0125
+V 8,8 0 0126
+W 11,8 0 0127
+X 8,8 0 0130
+Y 7,8 0 0131
+Z 8,8 0 0132
+[ 5,8,1 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 5,8,1 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 7,5 0 0141
+b 7,8 0 0142
+c 6,5 0 0143
+d 7,8 0 0144
+e 6,5 0 0145
+f 5,8,2 0 0146
+g 6,6,2 0 0147
+h 7,8 0 0150
+i 4,8 0 0151
+j 4,8,2 0 0152
+k 7,8 0 0153
+l 4,8 0 0154
+m 10,5 0 0155
+n 7,5 0 0156
+o 6,5 0 0157
+p 7,5,2 0 0160
+q 7,5,2 0 0161
+r 5,5 0 0162
+s 4,5 0 0163
+t 4,7 0 0164
+u 7,5 0 0165
+v 6,5 0 0166
+w 10,5 0 0167
+x 7,5 0 0170
+y 7,5,2 0 0171
+z 5,5 0 0172
+{ 5,8,1 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 5,8,1 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 9,8 0 0251
+© "
+Of 6,8 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 9,8 0 0256
+® "
+a- 5,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 4,8 0 0264
+´ "
+µ 7,5,2 0 0265
+ps 8,8 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 7,8,2 0 0307
+Ç "
+`E 8,11 0 0310
+È "
+'E 8,11 0 0311
+É "
+^E 8,11 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 6,11 0 0314
+Ì "
+'I 6,11 0 0315
+Í "
+^I 6,11 0 0316
+Î "
+:I 6,11 0 0317
+Ï "
+-D 9,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,11 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 8,8 0 0336
+Þ "
+ss 8,8,2 0 0337
+ß "
+`a 7,8 0 0340
+à "
+'a 7,8 0 0341
+á "
+^a 7,8 0 0342
+â "
+~a 7,8 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 9,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 4,8 0 0354
+ì "
+'i 4,8 0 0355
+í "
+^i 4,8 0 0356
+î "
+:i 4,8 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 7,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 7,8 0 0371
+ù "
+'u 7,8 0 0372
+ú "
+^u 7,8 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,8,2 0 0375
+ý "
+Tp 7,8,2 0 0376
+þ "
+:y 7,8,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/NI b/gnu/usr.bin/groff/devices/devX75/NI
new file mode 100644
index 000000000000..20c2c4246996
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+# 8,7 0 043
+sh "
+$ 5,9,1 0 044
+Do "
+% 9,8 0 045
+& 9,8 0 046
+' 3,8 0 047
+( 5,8,1 0 050
+) 5,8,1 0 051
+* 6,8 0 052
++ 6,5 0 053
+, 2,2,1 0 054
+\- 6,3 0 055
+. 2,2 0 056
+/ 5,8,1 0 057
+sl "
+0 5,8 0 060
+1 5,8 0 061
+2 5,8 0 062
+3 5,8 0 063
+4 5,8 0 064
+5 5,8 0 065
+6 5,8 0 066
+7 5,8 0 067
+8 5,8 0 070
+9 5,8 0 071
+: 3,5 0 072
+; 3,5,1 0 073
+< 7,5 0 074
+= 6,4 0 075
+eq "
+> 7,5 0 076
+? 6,8 0 077
+@ 9,8 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 6,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 9,8 0 0110
+I 5,8 0 0111
+J 5,8 0 0112
+K 8,8 0 0113
+L 7,8 0 0114
+M 12,8 0 0115
+N 9,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 8,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 8,8 0 0126
+W 11,8 0 0127
+X 8,8 0 0130
+Y 8,8 0 0131
+Z 8,8 0 0132
+[ 5,8,1 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 5,8,1 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 6,5 0 0141
+b 6,8 0 0142
+c 5,5 0 0143
+d 6,8 0 0144
+e 5,5 0 0145
+f 4,8,2 0 0146
+g 5,6,2 0 0147
+h 6,8 0 0150
+i 3,8 0 0151
+j 3,8,2 0 0152
+k 6,8 0 0153
+l 3,8 0 0154
+m 9,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 5,5 0 0162
+s 4,5 0 0163
+t 3,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 9,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 5,8,1 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 5,8,1 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 6,8,1 0 0247
+§ "
+ad 4,7 0 0250
+¨ "
+co 9,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 6,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 9,8 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,5 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 8,8 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 4,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 4,8 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 7,8 0 0274
+¼ "
+12 7,8 0 0275
+½ "
+34 7,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 6,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 5,11 0 0314
+Ì "
+'I 5,11 0 0315
+Í "
+^I 5,11 0 0316
+Î "
+:I 5,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8,2 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,2 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,7 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/NR b/gnu/usr.bin/groff/devices/devX75/NR
new file mode 100644
index 000000000000..aa05125e750e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+# 8,8 0 043
+sh "
+$ 5,9,1 0 044
+Do "
+% 9,8 0 045
+& 10,8 0 046
+' 3,8 0 047
+( 4,8,1 0 050
+) 4,8,1 0 051
+* 6,8 0 052
++ 6,5 0 053
+, 3,2,1 0 054
+\- 6,3 0 055
+. 4,2 0 056
+/ 4,8 0 057
+sl "
+0 5,8 0 060
+1 5,8 0 061
+2 5,8 0 062
+3 5,8 0 063
+4 5,8 0 064
+5 5,8 0 065
+6 5,8 0 066
+7 5,8 0 067
+8 5,8 0 070
+9 5,8 0 071
+: 4,5 0 072
+; 4,5,1 0 073
+< 7,5 0 074
+= 6,4 0 075
+eq "
+> 7,5 0 076
+? 5,8 0 077
+@ 9,8 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 9,8 0 0110
+I 4,8 0 0111
+J 5,8 0 0112
+K 8,8 0 0113
+L 7,8 0 0114
+M 10,8 0 0115
+N 9,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 8,8 0 0122
+S 6,8 0 0123
+T 8,8 0 0124
+U 8,8 0 0125
+V 8,8 0 0126
+W 12,8 0 0127
+X 7,8 0 0130
+Y 8,8 0 0131
+Z 6,8 0 0132
+[ 3,8,1 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 3,8,1 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 6,5 0 0141
+b 5,8 0 0142
+c 5,5 0 0143
+d 6,8 0 0144
+e 5,5 0 0145
+f 4,8 0 0146
+g 6,5,2 0 0147
+h 6,8 0 0150
+i 4,7 0 0151
+j 4,7,2 0 0152
+k 7,8 0 0153
+l 4,8 0 0154
+m 10,5 0 0155
+n 7,5 0 0156
+o 5,5 0 0157
+p 5,5,2 0 0160
+q 6,5,2 0 0161
+r 5,5 0 0162
+s 5,5 0 0163
+t 3,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 8,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 5,5 0 0172
+{ 4,8,1 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 4,8,1 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 8,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 5,8,2 0 0247
+§ "
+ad 4,7 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 5,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,5 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 7,8,2 0 0266
+¶ "
+md 4,4 0 0267
+· "
+ac 3,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 7,8 0 0274
+¼ "
+12 7,8 0 0275
+½ "
+34 7,8 0 0276
+¾ "
+r? 5,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 11,8 0 0306
+Æ "
+,C 7,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 4,11 0 0314
+Ì "
+'I 4,11 0 0315
+Í "
+^I 4,11 0 0316
+Î "
+:I 4,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,8 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,2 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,7 0 0353
+ë "
+`i 4,8 0 0354
+ì "
+'i 4,8 0 0355
+í "
+^i 4,8 0 0356
+î "
+:i 4,7 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 7,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,7 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 5,5,1 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 5,8,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/S b/gnu/usr.bin/groff/devices/devX75/S
new file mode 100644
index 000000000000..77e2f5fb3c5d
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,7 0 041
+fa 7,7 0 042
+# 5,7 0 043
+sh "
+te 6,7 0 044
+% 8,7 0 045
+& 7,7 0 046
+st 5,5 0 047
+( 4,7,2 0 050
+) 4,7,2 0 051
+** 5,6 0 052
++ 6,5 0 053
+pl "
+, 2,1,2 0 054
+\- 6,3 0 055
+mi "
+. 2,2 0 056
+/ 3,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 2,5 0 072
+; 2,5,2 0 073
+< 7,5 0 074
+= 6,4 0 075
+eq "
+> 6,5 0 076
+? 5,7 0 077
+=~ 6,6 0 0100
+*A 8,7 0 0101
+*B 6,7 0 0102
+*X 8,7 0 0103
+*D 7,7 0 0104
+*E 6,7 0 0105
+*F 8,7 0 0106
+*G 6,7 0 0107
+*Y 8,7 0 0110
+*I 3,7 0 0111
++h 7,7 0 0112
+*K 7,7 0 0113
+*L 7,7 0 0114
+*M 10,7 0 0115
+*N 8,7 0 0116
+*O 7,7 0 0117
+*P 8,7 0 0120
+*H 7,7 0 0121
+*R 6,7 0 0122
+*S 6,7 0 0123
+*T 6,7 0 0124
+--- 8,7 0 0125
+ts 5,5,2 0 0126
+*W 9,7 0 0127
+*C 7,7 0 0130
+*Q 9,7 0 0131
+*Z 6,7 0 0132
+[ 3,7,2 0 0133
+lB "
+tf 7,5 0 0134
+3d "
+] 3,7,2 0 0135
+rB "
+pp 7,7 0 0136
+_ 5,0,3 0 0137
+rn 5,10 0 0140
+*a 7,5 0 0141
+*b 5,8,2 0 0142
+*x 6,5,2 0 0143
+*d 5,8 0 0144
+*e 5,5 0 0145
+*f 6,7,2 0 0146
+*g 6,5,2 0 0147
+*y 6,5,2 0 0150
+*i 4,5 0 0151
++f 6,5,2 0 0152
+*k 6,5 0 0153
+*l 6,8 0 0154
+*m 6,5,2 0 0155
+µ "
+*n 6,5 0 0156
+*o 5,5 0 0157
+*p 6,5 0 0160
+*h 5,7 0 0161
+*r 5,5,3 0 0162
+*s 6,5 0 0163
+*t 5,5 0 0164
+*u 6,5 0 0165
++p 8,6 0 0166
+*w 8,5 0 0167
+*c 5,8,2 0 0170
+*q 7,5,2 0 0171
+*z 5,8,2 0 0172
+lC 5,7,2 0 0173
+{ "
+ba 2,7,2 0 0174
+or "
+| "
+rC 5,7,2 0 0175
+} "
+ap 6,4 0 0176
+*U 7,7 0 0241
+fm 3,8 0 0242
+<= 6,7 0 0243
+f/ 3,7 0 0244
+if 7,4 0 0245
+Fn 5,7,2 0 0246
+CL 7,5 0 0247
+DI 7,5 0 0250
+HE 7,5 0 0251
+SP 7,5 0 0252
+<> 10,5 0 0253
+<- 10,5 0 0254
+ua 6,10,4 0 0255
+arrowverttp "
+-> 10,5 0 0256
+da 6,10,2 0 0257
+arrowvertbt "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+sd 4,8 0 0262
+>= 6,7 0 0263
+mu 6,5 0 0264
+× "
+pt 7,4 0 0265
+pd 5,8 0 0266
+bu 5,4 0 0267
+di 6,5 0 0270
+÷ "
+!= 6,5 0 0271
+== 6,5 0 0272
+~= 6,5 0 0273
+~~ "
+--- 9,1 0 0274
+arrowvertex 6,10,4 0 0275
+an 10,3 0 0276
+CR 7,6 0 0277
+Ah 8,7 0 0300
+Im 7,8,1 0 0301
+Re 8,8 0 0302
+wp 9,6,2 0 0303
+c* 8,7 0 0304
+c+ 8,7 0 0305
+es 8,8,1 0 0306
+ca 8,5 0 0307
+cu 8,5 0 0310
+sp 7,5 0 0311
+ip 7,5,2 0 0312
+--- 7,6,1 0 0313
+sb 7,5 0 0314
+ib 7,5,2 0 0315
+mo 7,5 0 0316
+nm 7,6,1 0 0317
+/_ 8,7 0 0320
+gr 7,7 0 0321
+rg 8,7,1 0 0322
+co 8,7,1 0 0323
+tm 10,7 0 0324
+--- 9,8,1 0 0325
+sr 6,10 0 0326
+md 3,3 0 0327
+no 7,3 0 0330
+¬ "
+AN 6,5 0 0331
+OR 6,5 0 0332
+hA 11,5 0 0333
+lA 10,5 0 0334
+uA 6,10 0 0335
+rA 10,5 0 0336
+dA 6,10 0 0337
+lz 7,7 0 0340
+la 3,7,2 0 0341
+--- 8,7,1 0 0342
+--- 8,7,1 0 0343
+--- 9,7 0 0344
+--- 7,8,1 0 0345
+parenlefttp 4,10,4 0 0346
+parenleftex 4,10,4 0 0347
+parenleftbt 4,10,4 0 0350
+bracketlefttp 4,10,4 0 0351
+lc "
+bracketleftex 4,10,4 0 0352
+bracketleftbt 4,10,2 0 0353
+lf "
+bracelefttp 5,10,4 0 0354
+lt "
+braceleftmid 5,10,4 0 0355
+lk "
+braceleftbt 5,10,2 0 0356
+lb "
+bracerightex 5,10,4 0 0357
+braceleftex "
+bv "
+--- 8,9 0 0360
+ra 3,7,2 0 0361
+is 3,10,2 0 0362
+--- 7,10,4 0 0363
+--- 7,10,4 0 0364
+--- 7,10,2 0 0365
+parenrighttp 4,10,4 0 0366
+parenrightex 4,10,4 0 0367
+parenrightbt 4,10,4 0 0370
+bracketrighttp 4,10,4 0 0371
+rc "
+bracketrightex 4,10,4 0 0372
+bracketrightbt 4,10,2 0 0373
+rf "
+bracerighttp 5,10,4 0 0374
+rt "
+bracerightmid 5,10,4 0 0375
+rk "
+bracerightbt 5,10,2 0 0376
+rb "
diff --git a/gnu/usr.bin/groff/devices/devX75/TB b/gnu/usr.bin/groff/devices/devX75/TB
new file mode 100644
index 000000000000..090771428fc5
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,7 0 041
+" 5,7 0 042
+# 6,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 9,7 0 045
+& 9,7 0 046
+' 4,7 0 047
+( 4,7,3 0 050
+) 4,7,3 0 051
+* 6,7 0 052
++ 6,5 0 053
+, 4,2,1 0 054
+\- 7,3 0 055
+. 3,2 0 056
+/ 3,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 4,5 0 072
+; 4,5,1 0 073
+< 6,5 0 074
+= 6,4 0 075
+eq "
+> 6,5 0 076
+? 6,7 0 077
+@ 11,7,2 0 0100
+at "
+A 7,7 0 0101
+B 7,7 0 0102
+C 7,7 0 0103
+D 8,7 0 0104
+E 7,7 0 0105
+F 7,7 0 0106
+G 7,7 0 0107
+H 9,7 0 0110
+I 5,7 0 0111
+J 5,7,1 0 0112
+K 8,7 0 0113
+L 7,7 0 0114
+M 10,7 0 0115
+N 8,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 7,7 0 0122
+S 6,7 0 0123
+T 7,7 0 0124
+U 7,7 0 0125
+V 8,7 0 0126
+W 10,7 0 0127
+X 7,7 0 0130
+Y 8,7 0 0131
+Z 7,7 0 0132
+[ 4,7,3 0 0133
+lB "
+\ 3,7 0 0134
+rs "
+] 4,7,3 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 5,0,3 0 0137
+` 4,7 0 0140
+oq "
+a 5,5 0 0141
+b 5,7 0 0142
+c 5,5 0 0143
+d 6,7 0 0144
+e 5,5 0 0145
+f 3,7 0 0146
+g 5,5,3 0 0147
+h 5,7 0 0150
+i 3,8 0 0151
+j 4,8,2 0 0152
+k 5,7 0 0153
+l 3,7 0 0154
+m 8,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 5,5,2 0 0160
+q 5,5,2 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 4,7 0 0164
+u 5,5 0 0165
+v 5,5 0 0166
+w 6,5 0 0167
+x 5,5 0 0170
+y 5,5,2 0 0171
+z 5,5 0 0172
+{ 4,7,3 0 0173
+lC "
+| 3,7,2 0 0174
+or "
+ba "
+} 4,7,3 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,4,3 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,7 0 0245
+¥ "
+bb 3,7,2 0 0246
+¦ "
+sc 5,7,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,7 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 3,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 4,7 0 0264
+´ "
+µ 5,5,3 0 0265
+ps 6,7,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 4,7 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 7,7 0 0274
+¼ "
+12 7,7 0 0275
+½ "
+34 7,7 0 0276
+¾ "
+r? 6,4,3 0 0277
+¿ "
+`A 7,10 0 0300
+À "
+'A 7,10 0 0301
+Á "
+^A 7,10 0 0302
+Â "
+~A 7,10 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,10 0 0305
+Å "
+AE 9,7 0 0306
+Æ "
+,C 7,7,3 0 0307
+Ç "
+`E 7,10 0 0310
+È "
+'E 7,10 0 0311
+É "
+^E 7,10 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 5,10 0 0314
+Ì "
+'I 5,10 0 0315
+Í "
+^I 5,10 0 0316
+Î "
+:I 5,10 0 0317
+Ï "
+-D 8,7 0 0320
+Ð "
+~N 8,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 7,8,1 0 0330
+Ø "
+`U 7,10 0 0331
+Ù "
+'U 7,10 0 0332
+Ú "
+^U 7,10 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,8 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,3 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,8,3 0 0375
+ý "
+Tp 5,7,3 0 0376
+þ "
+:y 5,8,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/TBI b/gnu/usr.bin/groff/devices/devX75/TBI
new file mode 100644
index 000000000000..37d92b0a70c5
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 8,7 0 043
+sh "
+$ 5,7 0 044
+Do "
+% 11,7 0 045
+& 8,7 0 046
+' 4,7 0 047
+( 6,7,2 0 050
+) 6,7,2 0 051
+* 7,8 0 052
++ 7,5 0 053
+, 4,2,1 0 054
+\- 7,3 0 055
+. 4,2 0 056
+/ 5,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 3,5 0 072
+; 5,5,1 0 073
+< 6,5 0 074
+= 7,4 0 075
+eq "
+> 6,5 0 076
+? 5,7 0 077
+@ 11,7,2 0 0100
+at "
+A 6,7 0 0101
+B 7,7 0 0102
+C 7,7 0 0103
+D 7,7 0 0104
+E 7,7 0 0105
+F 7,7 0 0106
+G 7,7 0 0107
+H 8,7 0 0110
+I 4,7 0 0111
+J 5,7,1 0 0112
+K 7,7 0 0113
+L 6,7 0 0114
+M 10,7 0 0115
+N 8,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 7,7 0 0122
+S 6,7 0 0123
+T 6,7 0 0124
+U 8,7 0 0125
+V 7,7 0 0126
+W 9,7 0 0127
+X 7,7 0 0130
+Y 6,7 0 0131
+Z 6,7 0 0132
+[ 5,7,2 0 0133
+lB "
+\ 5,7 0 0134
+rs "
+] 5,7,2 0 0135
+rB "
+^ 7,7 0 0136
+a^ "
+ha "
+_ 5,0,2 0 0137
+` 4,7 0 0140
+oq "
+a 5,5 0 0141
+b 5,7 0 0142
+c 5,5 0 0143
+d 5,7 0 0144
+e 5,5 0 0145
+f 4,7,3 0 0146
+g 4,5,3 0 0147
+h 5,7 0 0150
+i 3,7 0 0151
+j 3,7,3 0 0152
+k 5,7 0 0153
+l 3,7 0 0154
+m 7,5 0 0155
+n 5,5 0 0156
+o 5,5 0 0157
+p 5,5,3 0 0160
+q 5,5,3 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 4,6 0 0164
+u 5,5 0 0165
+v 4,5 0 0166
+w 7,5 0 0167
+x 4,5 0 0170
+y 5,5,2 0 0171
+z 4,5 0 0172
+{ 5,7,2 0 0173
+lC "
+| 3,7 0 0174
+or "
+ba "
+} 5,7,2 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 5,5,3 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 5,7 0 0243
+£ "
+Cs 7,6 0 0244
+¤ "
+Ye 5,7 0 0245
+¥ "
+bb 3,7 0 0246
+¦ "
+sc 5,7,2 0 0247
+§ "
+ad 5,7 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 5,7 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 3,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 4,7 0 0264
+´ "
+µ 5,5,3 0 0265
+ps 8,7,3 0 0266
+¶ "
+md 4,4 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 5,7 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 7,7 0 0274
+¼ "
+12 7,7 0 0275
+½ "
+34 7,7 0 0276
+¾ "
+r? 5,5,3 0 0277
+¿ "
+`A 6,10 0 0300
+À "
+'A 6,10 0 0301
+Á "
+^A 6,10 0 0302
+Â "
+~A 6,10 0 0303
+Ã "
+:A 6,10 0 0304
+Ä "
+oA 6,10 0 0305
+Å "
+AE 9,7 0 0306
+Æ "
+,C 7,7,3 0 0307
+Ç "
+`E 7,10 0 0310
+È "
+'E 7,10 0 0311
+É "
+^E 7,10 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 4,10 0 0314
+Ì "
+'I 4,10 0 0315
+Í "
+^I 4,10 0 0316
+Î "
+:I 4,10 0 0317
+Ï "
+-D 7,7 0 0320
+Ð "
+~N 8,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,5 0 0327
+× "
+/O 7,8,1 0 0330
+Ø "
+`U 8,10 0 0331
+Ù "
+'U 8,10 0 0332
+Ú "
+^U 8,10 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 6,10 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 6,7,3 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,8 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,3 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 5,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,8 0 0366
+ö "
+di 7,5 0 0367
+÷ "
+/o 5,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,8,2 0 0375
+ý "
+Tp 5,7,3 0 0376
+þ "
+:y 5,8,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/TI b/gnu/usr.bin/groff/devices/devX75/TI
new file mode 100644
index 000000000000..daa858e2eef0
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,7 0 041
+" 4,8 0 042
+# 5,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 9,7 0 045
+& 8,7 0 046
+' 3,8 0 047
+( 3,7,2 0 050
+) 4,7,2 0 051
+* 5,7 0 052
++ 7,5 0 053
+, 3,1,2 0 054
+\- 7,3 0 055
+. 3,1 0 056
+/ 4,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 3,5 0 072
+; 3,5,2 0 073
+< 5,5 0 074
+= 7,4 0 075
+eq "
+> 5,5 0 076
+? 5,7 0 077
+@ 10,7,2 0 0100
+at "
+A 7,7 0 0101
+B 6,7 0 0102
+C 7,7 0 0103
+D 7,7 0 0104
+E 6,7 0 0105
+F 6,7 0 0106
+G 8,7 0 0107
+H 7,7 0 0110
+I 3,7 0 0111
+J 4,7 0 0112
+K 7,7 0 0113
+L 6,7 0 0114
+M 10,7 0 0115
+N 7,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 6,7 0 0122
+S 5,7 0 0123
+T 6,7 0 0124
+U 7,7 0 0125
+V 6,7 0 0126
+W 9,7 0 0127
+X 6,7 0 0130
+Y 6,7 0 0131
+Z 6,7 0 0132
+[ 4,7,2 0 0133
+lB "
+\ 5,7 0 0134
+rs "
+] 4,7,2 0 0135
+rB "
+^ 5,7 0 0136
+a^ "
+ha "
+_ 5,0,3 0 0137
+` 3,8 0 0140
+oq "
+a 5,5 0 0141
+b 5,7 0 0142
+c 5,5 0 0143
+d 5,7 0 0144
+e 5,5 0 0145
+f 3,7,3 0 0146
+g 4,5,3 0 0147
+h 5,7 0 0150
+i 3,7 0 0151
+j 3,7,3 0 0152
+k 5,7 0 0153
+l 3,7 0 0154
+m 7,5 0 0155
+n 5,5 0 0156
+o 5,5 0 0157
+p 5,5,3 0 0160
+q 5,5,3 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 3,6 0 0164
+u 5,5 0 0165
+v 5,5 0 0166
+w 7,5 0 0167
+x 4,5 0 0170
+y 5,5,3 0 0171
+z 4,5 0 0172
+{ 4,7,2 0 0173
+lC "
+| 3,7,2 0 0174
+or "
+ba "
+} 4,7,2 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,5,2 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 5,7 0 0243
+£ "
+Cs 5,7 0 0244
+¤ "
+Ye 7,7 0 0245
+¥ "
+bb 3,7,2 0 0246
+¦ "
+sc 5,7,2 0 0247
+§ "
+ad 3,7 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,7 0 0252
+ª "
+Fo 5,5 0 0253
+« "
+no 7,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 3,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 5,5,3 0 0265
+ps 6,7,3 0 0266
+¶ "
+md 3,3 0 0267
+· "
+ac 3,0,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 3,7 0 0272
+º "
+Fc 5,5 0 0273
+» "
+14 7,7 0 0274
+¼ "
+12 7,7 0 0275
+½ "
+34 7,7 0 0276
+¾ "
+r? 5,5,2 0 0277
+¿ "
+`A 7,10 0 0300
+À "
+'A 7,10 0 0301
+Á "
+^A 7,10 0 0302
+Â "
+~A 7,10 0 0303
+Ã "
+:A 7,9 0 0304
+Ä "
+oA 7,10 0 0305
+Å "
+AE 8,7 0 0306
+Æ "
+,C 7,7,2 0 0307
+Ç "
+`E 6,10 0 0310
+È "
+'E 6,10 0 0311
+É "
+^E 6,10 0 0312
+Ê "
+:E 6,9 0 0313
+Ë "
+`I 3,10 0 0314
+Ì "
+'I 3,10 0 0315
+Í "
+^I 3,10 0 0316
+Î "
+:I 3,9 0 0317
+Ï "
+-D 7,7 0 0320
+Ð "
+~N 7,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,9 0 0326
+Ö "
+mu 7,5 0 0327
+× "
+/O 7,8,1 0 0330
+Ø "
+`U 7,10 0 0331
+Ù "
+'U 7,10 0 0332
+Ú "
+^U 7,10 0 0333
+Û "
+:U 7,9 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 6,7,2 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,8 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,7 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 7,5 0 0346
+æ "
+,c 5,5,2 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,7 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,7 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 5,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,7 0 0366
+ö "
+di 7,5 0 0367
+÷ "
+/o 5,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,7 0 0374
+ü "
+'y 5,8,3 0 0375
+ý "
+Tp 5,7,3 0 0376
+þ "
+:y 5,7,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devX75/TR b/gnu/usr.bin/groff/devices/devX75/TR
new file mode 100644
index 000000000000..c1ac847b408b
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devX75/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,7 0 041
+" 4,7 0 042
+# 5,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 8,7 0 045
+& 8,7 0 046
+' 3,7 0 047
+( 4,7,2 0 050
+) 4,7,2 0 051
+* 5,7 0 052
++ 6,5 0 053
+, 3,1,2 0 054
+\- 7,3 0 055
+. 3,1 0 056
+/ 3,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 3,5 0 072
+; 3,5,2 0 073
+< 5,5 0 074
+= 6,4 0 075
+eq "
+> 5,5 0 076
+? 4,7 0 077
+@ 9,7,2 0 0100
+at "
+A 8,7 0 0101
+B 6,7 0 0102
+C 7,7 0 0103
+D 7,7 0 0104
+E 6,7 0 0105
+F 6,7 0 0106
+G 7,7 0 0107
+H 8,7 0 0110
+I 4,7 0 0111
+J 4,7 0 0112
+K 7,7 0 0113
+L 6,7 0 0114
+M 10,7 0 0115
+N 8,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 7,7 0 0122
+S 5,7 0 0123
+T 6,7 0 0124
+U 8,7 0 0125
+V 8,7 0 0126
+W 10,7 0 0127
+X 8,7 0 0130
+Y 8,7 0 0131
+Z 6,7 0 0132
+[ 3,7,2 0 0133
+lB "
+\ 3,7 0 0134
+rs "
+] 3,7,2 0 0135
+rB "
+^ 5,7 0 0136
+a^ "
+ha "
+_ 5,0,3 0 0137
+` 3,7 0 0140
+oq "
+a 4,5 0 0141
+b 5,7 0 0142
+c 4,5 0 0143
+d 5,7 0 0144
+e 4,5 0 0145
+f 4,7 0 0146
+g 5,5,2 0 0147
+h 5,7 0 0150
+i 3,7 0 0151
+j 3,7,2 0 0152
+k 5,7 0 0153
+l 4,7 0 0154
+m 8,5 0 0155
+n 5,5 0 0156
+o 5,5 0 0157
+p 5,5,2 0 0160
+q 5,5,2 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 4,6 0 0164
+u 5,5 0 0165
+v 5,5 0 0166
+w 8,5 0 0167
+x 6,5 0 0170
+y 5,5,2 0 0171
+z 5,5 0 0172
+{ 4,7,2 0 0173
+lC "
+| 2,7,2 0 0174
+or "
+ba "
+} 4,7,2 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 3,5,2 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 5,7 0 0243
+£ "
+Cs 5,7 0 0244
+¤ "
+Ye 5,7 0 0245
+¥ "
+bb 2,7 0 0246
+¦ "
+sc 5,8,1 0 0247
+§ "
+ad 5,7 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,7 0 0252
+ª "
+Fo 5,5 0 0253
+« "
+no 7,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,7 0 0264
+´ "
+µ 5,5,2 0 0265
+ps 6,7,2 0 0266
+¶ "
+md 2,3 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 4,7 0 0272
+º "
+Fc 5,5 0 0273
+» "
+14 8,7 0 0274
+¼ "
+12 8,7 0 0275
+½ "
+34 8,7 0 0276
+¾ "
+r? 4,5,2 0 0277
+¿ "
+`A 8,10 0 0300
+À "
+'A 8,10 0 0301
+Á "
+^A 8,10 0 0302
+Â "
+~A 8,10 0 0303
+Ã "
+:A 8,9 0 0304
+Ä "
+oA 8,10 0 0305
+Å "
+AE 9,7 0 0306
+Æ "
+,C 7,7,3 0 0307
+Ç "
+`E 6,10 0 0310
+È "
+'E 6,10 0 0311
+É "
+^E 6,10 0 0312
+Ê "
+:E 6,9 0 0313
+Ë "
+`I 4,10 0 0314
+Ì "
+'I 4,10 0 0315
+Í "
+^I 4,10 0 0316
+Î "
+:I 4,9 0 0317
+Ï "
+-D 7,7 0 0320
+Ð "
+~N 8,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,9 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 8,8,1 0 0330
+Ø "
+`U 8,10 0 0331
+Ù "
+'U 8,10 0 0332
+Ú "
+^U 8,10 0 0333
+Û "
+:U 8,9 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 5,7 0 0337
+ß "
+`a 4,8 0 0340
+à "
+'a 4,8 0 0341
+á "
+^a 4,8 0 0342
+â "
+~a 4,8 0 0343
+ã "
+:a 4,7 0 0344
+ä "
+oa 4,8 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 4,5,3 0 0347
+ç "
+`e 4,8 0 0350
+è "
+'e 4,8 0 0351
+é "
+^e 4,8 0 0352
+ê "
+:e 4,7 0 0353
+ë "
+`i 4,8 0 0354
+ì "
+'i 4,8 0 0355
+í "
+^i 4,8 0 0356
+î "
+:i 4,7 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 5,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,7 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 5,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,7 0 0374
+ü "
+'y 5,8,2 0 0375
+ý "
+Tp 5,7,2 0 0376
+þ "
+:y 5,7,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devices/devascii/DESC.proto b/gnu/usr.bin/groff/devices/devascii/DESC.proto
new file mode 100644
index 000000000000..88399ab16d91
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devascii/DESC.proto
@@ -0,0 +1,8 @@
+res 240
+hor 24
+vert 40
+unitwidth 10
+sizes 10 0
+fonts 4 R I B BI
+tcommand
+postpro grotty
diff --git a/gnu/usr.bin/groff/devices/devascii/Makefile b/gnu/usr.bin/groff/devices/devascii/Makefile
new file mode 100644
index 000000000000..47057d87d4f7
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devascii/Makefile
@@ -0,0 +1,6 @@
+# Makefile for devascii
+
+DEVICE= ascii
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devascii/R.proto b/gnu/usr.bin/groff/devices/devascii/R.proto
new file mode 100644
index 000000000000..9a8909e85b79
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devascii/R.proto
@@ -0,0 +1,184 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0041
+r! "
+TP "
+Tp "
+" 24 0 0042
+lq "
+rq "
+# 24 0 0043
+sh "
+sc "
+$ 24 0 0044
+Do "
+% 24 0 0045
+& 24 0 0046
+' 24 0 0047
+aa "
+fm "
+aq "
+ac "
+( 24 0 0050
+) 24 0 0051
+* 24 0 0052
+** "
+ho "
++ 24 0 0053
+pl "
+dg "
+dd "
+ad "
+ah "
+-D "
+Sd "
+, 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 "
+ss "
+> 24 0 0076
+ra "
+fc "
+? 24 0 0077
+r? "
+@ 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 "
+ua "
+de "
+_ 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 "
+a- "
+ao "
+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
+da "
+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 "
diff --git a/gnu/usr.bin/groff/devices/devdvi/B b/gnu/usr.bin/groff/devices/devdvi/B
new file mode 100644
index 000000000000..240731a75e5e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/B
@@ -0,0 +1,347 @@
+name B
+internalname cmbx10
+spacewidth 401952
+ligatures ff fi fl ffi ffl 0
+checksum 452076118
+designsize 10485760
+kernpairs
+ff ' 114323
+ff ? 114323
+ff ! 114323
+ff ) 114323
+ff rB 114323
+ff ] 114323
+' ' -100488
+' ? 133984
+' ! 133984
+A t -33496
+A C -33496
+A O -33496
+A G -33496
+A U -33496
+A Q -33496
+A T -100488
+A Y -100488
+A V -133984
+A W -133984
+D X -33496
+D W -33496
+D A -33496
+D V -33496
+D Y -33496
+F o -100488
+F e -100488
+F u -100488
+F r -100488
+F a -100488
+F A -133984
+F O -33496
+F C -33496
+F G -33496
+F Q -33496
+I I 33496
+K O -33496
+K C -33496
+K G -33496
+K Q -33496
+L T -100488
+L Y -100488
+L V -133984
+L W -133984
+O X -33496
+O W -33496
+O A -33496
+O V -33496
+O Y -33496
+P A -100488
+P o -33496
+P e -33496
+P a -33496
+P . -100488
+P , -100488
+R t -33496
+R C -33496
+R O -33496
+R G -33496
+R U -33496
+R Q -33496
+R T -100488
+R Y -100488
+R V -133984
+R W -133984
+T y -33496
+T e -100488
+T o -100488
+T r -100488
+T a -100488
+T A -100488
+T u -100488
+V o -100488
+V e -100488
+V u -100488
+V r -100488
+V a -100488
+V A -133984
+V O -33496
+V C -33496
+V G -33496
+V Q -33496
+W o -100488
+W e -100488
+W u -100488
+W r -100488
+W a -100488
+W A -133984
+W O -33496
+W C -33496
+W G -33496
+W Q -33496
+X O -33496
+X C -33496
+X G -33496
+X Q -33496
+Y e -100488
+Y o -100488
+Y r -100488
+Y a -100488
+Y A -100488
+Y u -100488
+oq oq -100488
+oq ` -100488
+` oq -100488
+` ` -100488
+a v -33496
+a j 66992
+a y -33496
+a w -33496
+b e 33496
+b o 33496
+b x -33496
+b d 33496
+b c 33496
+b q 33496
+b v -33496
+b j 66992
+b y -33496
+b w -33496
+c h -33496
+c k -33496
+f ' 114323
+f ? 114323
+f ! 114323
+f ) 114323
+f rB 114323
+f ] 114323
+g j 33496
+h t -33496
+h u -33496
+h b -33496
+h y -33496
+h v -33496
+h w -33496
+k a -66992
+k e -33496
+k a -33496
+k o -33496
+k c -33496
+m t -33496
+m u -33496
+m b -33496
+m y -33496
+m v -33496
+m w -33496
+n t -33496
+n u -33496
+n b -33496
+n y -33496
+n v -33496
+n w -33496
+o e 33496
+o o 33496
+o x -33496
+o d 33496
+o c 33496
+o q 33496
+o v -33496
+o j 66992
+o y -33496
+o w -33496
+p e 33496
+p o 33496
+p x -33496
+p d 33496
+p c 33496
+p q 33496
+p v -33496
+p j 66992
+p y -33496
+p w -33496
+t y -33496
+t w -33496
+u w -33496
+v a -66992
+v e -33496
+v a -33496
+v o -33496
+v c -33496
+w e -33496
+w a -33496
+w o -33496
+w c -33496
+y o -33496
+y e -33496
+y a -33496
+y . -100488
+y , -100488
+charset
+*G 725261,719440,0,0,0,-167480 2 0000
+*D 1004880,719440 2 0001
+*H 937888,719440,0,0,-33496,-33496 2 0002
+*L 844682,719440 2 0003
+*C 803904,719440 2 0004
+*P 943714,719440 2 0005
+*S 870896,719440 2 0006
+*U 937888,719440,0,0,-33496,-167480 2 0007
+*F 870896,719440,0,0,-33496 2 0010
+*Q 937888,719440,0,0,-33496,-83741 2 0011
+*W 870896,719440 2 0012
+ff 703416,728178,0,114323 2 0013
+fi 669920,728178 2 0014
+fl 669920,728178 2 0015
+Fi 1004880,728178 2 0016
+Fl 1004880,728178 2 0017
+.i 334960,466034 0 0020
+.j 368456,466034,203890 1 0021
+ga 602928,728178 2 0022
+char180 602928,728178 2 0023
+aa "
+ah 602928,662642 2 0024
+ab 602928,728178 2 0025
+char175 602928,625066 2 0026
+a- "
+ao 911674,728178 2 0027
+char184 535936,0,178403 1 0030
+ac "
+char223 626230,728178 2 0031
+ss "
+char230 870896,466034 0 0032
+ae "
+oe 937888,466034 0 0033
+char248 602928,567979,101946 3 0034
+/o "
+char198 1092261,719440 2 0035
+AE "
+OE 1226245,719440 2 0036
+char216 937888,770413,50973 3 0037
+/O "
+--- 334960,466034 0 0040
+! 367000,728178 2 0041
+rq 632056,728178 2 0042
+sh 1004880,728178,203888 3 0043
+# "
+Do 602928,786432,58254 3 0044
+$ "
+% 1004880,786432,58254 3 0045
+& 937888,728178 2 0046
+' 334960,728178 2 0047
+( 468944,786432,262144 3 0050
+) 468944,786432,262144 3 0051
+* 602928,786432 2 0052
++ 937888,664096,139808 3 0053
+, 334960,163112,203890 1 0054
+char173 401952,466034 0 0055
+hy "
+- "
+. 334960,163112 0 0056
+sl 602928,786432,262144 3 0057
+/ "
+0 602928,675749 2 0060
+1 602928,675749 2 0061
+2 602928,675749 2 0062
+3 602928,675749 2 0063
+4 602928,675749 2 0064
+5 602928,675749 2 0065
+6 602928,675749 2 0066
+7 602928,675749 2 0067
+8 602928,675749 2 0070
+9 602928,675749 2 0071
+: 334960,466034 0 0072
+; 334960,466034,203890 1 0073
+char161 367000,524288,203890 3 0074
+r! "
+= 937888,410110,-114178 0 0075
+char191 569432,524288,203890 3 0076
+r? "
+? 569432,728178 2 0077
+at 937888,728178 2 0100
+@ "
+A 911674,719440 2 0101
+B 857789,719440 2 0102
+C 870896,719440,0,0,-33496 2 0103
+D 924781,719440,0,0,0,-33496 2 0104
+E 792253,719440 2 0105
+F 758757,719440,0,0,0,-167480 2 0106
+G 948083,719440,0,0,-33496 2 0107
+H 943714,719440 2 0110
+I 457294,719440 2 0111
+J 623317,719440,0,0,0,-33496 2 0112
+K 945170,719440 2 0113
+L 725261,719440,0,0,0,66992 2 0114
+M 1144690,719440 2 0115
+N 943714,719440 2 0116
+O 905848,719440,0,0,-33496,-33496 2 0117
+P 824293,719440,0,0,0,-167480 2 0120
+Q 905848,719440,203890,0,-33496 3 0121
+R 904392,719440 2 0122
+S 669920,719440 2 0123
+T 838856,719440,0,0,0,-167480 2 0124
+U 927694,719440,0,0,-20389 2 0125
+V 911674,719440,0,16749,50245,-251219 2 0126
+W 1246634,719440,0,16749,50245,-150731 2 0127
+X 911674,719440 2 0130
+Y 911674,719440,0,30146,33496,-237822 2 0131
+Z 736912,719440 2 0132
+lB 334960,786432,262144 3 0133
+[ "
+lq 632056,728178 2 0134
+rB 334960,786432,262144 3 0135
+] "
+ha 602928,728178 2 0136
+^ "
+a^ "
+a. 334960,728178 2 0137
+oq 334960,728178 2 0140
+` "
+a 586179,466034 0 0141
+b 669920,728178 2 0142
+c 535936,466034 0 0143
+d 669920,728178 2 0144
+e 552685,466034 0 0145
+f 368456,728178,0,114323 2 0146
+g 602928,466034,203890,16749 1 0147
+h 669920,728178 2 0150
+i 334960,728178 2 0151
+j 368456,728178,203890 3 0152
+k 636424,728178 2 0153
+l 334960,728178 2 0154
+m 1004880,466034 0 0155
+n 669920,466034 0 0156
+o 602928,466034 0 0157
+p 669920,466034,203890 1 0160
+q 636424,466034,203890 1 0161
+r 496616,466034 0 0162
+s 475643,466034 0 0163
+t 468944,665763 2 0164
+u 669920,466034 0 0165
+v 636424,466034,0,16749 0 0166
+w 870896,466034,0,16749 0 0167
+x 636424,466034 0 0170
+y 636424,466034,203890,16749 1 0171
+z 535936,466034 0 0172
+en 602928,466034,0,33496 0 0173
+em 1205856,466034,0,33496 0 0174
+a" 602928,728178 2 0175
+~ 602928,728178 2 0176
+a~ "
+char168 602928,728178 2 0177
+ad "
diff --git a/gnu/usr.bin/groff/devices/devdvi/BI b/gnu/usr.bin/groff/devices/devdvi/BI
new file mode 100644
index 000000000000..16d0193c44ab
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/BI
@@ -0,0 +1,352 @@
+name BI
+internalname cmbxti10
+spacewidth 434573
+slant 14.036243
+ligatures ff fi fl ffi ffl 0
+checksum 1175274390
+designsize 10485760
+kernpairs
+ff ' 111848
+ff ? 111848
+ff ! 111848
+ff ) 111848
+ff rB 111848
+ff ] 111848
+' ' -92624
+' ? 123498
+' ! 123498
+A n -30875
+A l -30875
+A r -30875
+A u -30875
+A m -30875
+A t -30875
+A i -30875
+A C -30875
+A O -30875
+A G -30875
+A h -30875
+A b -30875
+A U -30875
+A k -30875
+A v -30875
+A w -30875
+A Q -30875
+A T -92624
+A Y -92624
+A V -123498
+A W -123498
+A e -61749
+A a -61749
+A o -61749
+A d -61749
+A c -61749
+A g -61749
+A q -61749
+D X -30875
+D W -30875
+D A -30875
+D V -30875
+D Y -30875
+F o -92624
+F e -92624
+F u -92624
+F r -92624
+F a -92624
+F A -123498
+F O -30875
+F C -30875
+F G -30875
+F Q -30875
+K O -30875
+K C -30875
+K G -30875
+K Q -30875
+L T -92624
+L Y -92624
+L V -123498
+L W -123498
+L e -61749
+L a -61749
+L o -61749
+L d -61749
+L c -61749
+L g -61749
+L q -61749
+O X -30875
+O W -30875
+O A -30875
+O V -30875
+O Y -30875
+P A -92624
+R n -30875
+R l -30875
+R r -30875
+R u -30875
+R m -30875
+R t -30875
+R i -30875
+R C -30875
+R O -30875
+R G -30875
+R h -30875
+R b -30875
+R U -30875
+R k -30875
+R v -30875
+R w -30875
+R Q -30875
+R T -92624
+R Y -92624
+R V -123498
+R W -123498
+R e -61749
+R a -61749
+R o -61749
+R d -61749
+R c -61749
+R g -61749
+R q -61749
+T y -92624
+T e -92624
+T o -92624
+T r -92624
+T a -92624
+T u -92624
+T A -92624
+V o -92624
+V e -92624
+V u -92624
+V r -92624
+V a -92624
+V A -123498
+V O -30875
+V C -30875
+V G -30875
+V Q -30875
+W A -92624
+X O -30875
+X C -30875
+X G -30875
+X Q -30875
+Y e -92624
+Y o -92624
+Y r -92624
+Y a -92624
+Y u -92624
+Y A -92624
+oq oq -92624
+oq ` -92624
+` oq -92624
+` ` -92624
+b e -61749
+b a -61749
+b o -61749
+b d -61749
+b c -61749
+b g -61749
+b q -61749
+c e -61749
+c a -61749
+c o -61749
+c d -61749
+c c -61749
+c g -61749
+c q -61749
+d l 61749
+e e -61749
+e a -61749
+e o -61749
+e d -61749
+e c -61749
+e g -61749
+e q -61749
+Fn ' 111848
+f ' 111848
+Fn ? 111848
+f ? 111848
+Fn ! 111848
+f ! 111848
+Fn ) 111848
+f ) 111848
+Fn rB 111848
+Fn ] 111848
+f rB 111848
+f ] 111848
+l l 61749
+n ' -123498
+o e -61749
+o a -61749
+o o -61749
+o d -61749
+o c -61749
+o g -61749
+o q -61749
+p e -61749
+p a -61749
+p o -61749
+p d -61749
+p c -61749
+p g -61749
+p q -61749
+r e -61749
+r a -61749
+r o -61749
+r d -61749
+r c -61749
+r g -61749
+r q -61749
+w l 61749
+charset
+*G 731666,719440,0,135298,0,-19075 2 0000
+*D 990312,719440 2 0001
+*H 928563,719440,0,95027,-84834,64152 2 0002
+*L 845843,719440 2 0003
+*C 805066,719440,0,158248,0,79125 2 0004
+*P 939632,719440,0,180443,0,90222 2 0005
+*S 866814,719440,0,119859,0,59930 2 0006
+*U 928563,719440,0,113013,-174763,-41360 2 0007
+*F 866814,719440,0,59054,-120805,59054 2 0010
+*Q 928563,719440,0,113013,-174763,-5243 2 0011
+*W 866814,719440,0,104021,0,52011 2 0012
+ff 792256,728178,203890,228357 3 0013
+fi 707205,728178,203890,113890 3 0014
+fl 738078,728178,203890,113890 3 0015
+Fi 1095466,728178,203890,113890 3 0016
+Fl 1110902,728178,203890,113890 3 0017
+.i 372824,466034,0,98840 0 0020
+.j 403699,466034,203890,48354 1 0021
+ga 619819,728178 2 0022
+char180 619819,728178,0,89421 2 0023
+aa "
+ah 619819,662642,0,86728 2 0024
+ab 619819,728178,0,108354 2 0025
+char175 619819,623318,0,109518 2 0026
+a- "
+ao 994973,728178 2 0027
+char184 558070,0,178403 1 0030
+ac "
+char223 697302,728178,203890,102090 3 0031
+ss "
+char230 866814,466034,0,89131 0 0032
+ae "
+oe 866814,466034,0,89131 0 0033
+char248 619819,567979,101946,99179 3 0034
+/o "
+char198 1072450,719440,0,119859 2 0035
+AE "
+OE 1195947,719440,0,119859 2 0036
+char216 928563,770413,50973,95027 3 0037
+/O "
+--- 311075,466034 0 0040
+! 404864,728178,0,119714 2 0041
+rq 650696,728178,0,83248 2 0042
+sh 990312,728178,203888,71653 3 0043
+# "
+char163 910723,728178 2 0044
+Po "
+% 990312,786432,58254,134859 3 0045
+& 928563,728178,0,89421 2 0046
+' 372824,728178,0,135734 2 0047
+( 496322,786432,262144,165733 3 0050
+) 496322,786432,262144,34661 3 0051
+* 619819,786432,0,150296 2 0052
++ 928563,632637,108349,34661 3 0053
+, 372824,154374,203890 1 0054
+char173 434573,466034,0,27379 0 0055
+hy "
+- "
+. 372824,154374 0 0056
+sl 619819,786432,262144,165733 3 0057
+/ "
+0 619819,675749,0,138062 2 0060
+1 619819,675749,0,138062 2 0061
+2 619819,675749,0,138062 2 0062
+3 619819,675749,0,138062 2 0063
+4 619819,675749,203890,138062 3 0064
+5 619819,675749,0,138062 2 0065
+6 619819,675749,0,138062 2 0066
+7 619819,675749,203890,138062 3 0067
+8 619819,675749,0,138062 2 0070
+9 619819,675749,0,138062 2 0071
+: 372824,466034,0,70198 0 0072
+; 372824,466034,203890,70198 1 0073
+char161 404864,524288,203890,68741 3 0074
+r! "
+= 928563,410110,-114178,71653 0 0075
+char191 619819,524288,203890 3 0076
+r? "
+? 619819,728178,0,120296 2 0077
+at 928563,728178,0,96555 2 0100
+@ "
+A 907592,719440 2 0101
+B 856330,719440,0,104021,0,52011 2 0102
+C 866814,719440,0,148986,-84834,74493 2 0103
+D 918078,719440,0,95027,0,64152 2 0104
+E 793414,719440,0,119859,0,59930 2 0105
+F 762541,719440,0,135298,0,-19075 2 0106
+G 938758,719440,0,77042,-84834,77042 2 0107
+H 939632,719440,0,180443,0,90222 2 0110
+I 494576,719440,0,164424,0,82213 2 0111
+J 640208,719440,0,152045,0,45147 2 0112
+K 938467,719440,0,148986,0,74493 2 0113
+L 731666,719440,0,0,0,61749 2 0114
+M 1124878,719440,0,180443,0,59347 2 0115
+N 939632,719440,0,180443,0,59347 2 0116
+O 896523,719440,0,95027,-84834,64152 2 0117
+P 825454,719440,0,104021,0,-50352 2 0120
+Q 896523,719440,203890,95027,-84834,95027 3 0121
+R 901186,719440,0,26835,0,20126 2 0122
+S 681568,719440,0,118112,0,59056 2 0123
+T 834774,719440,0,135298,-134896,-19075 2 0124
+U 923613,719440,0,180443,-136096,59347 2 0125
+V 907592,719440,0,195298,-133549,-51698 2 0126
+W 1216336,719440,0,195298,-133549,40925 2 0127
+X 907592,719440,0,164424,0,82213 2 0130
+Y 907592,719440,0,207648,-148986,-39347 2 0131
+Z 743317,719440,0,148986,0,74493 2 0132
+lB 373408,786432,262144,196608 3 0133
+[ "
+lq 650696,728178,0,175869 2 0134
+rB 373408,786432,262144,104568 3 0135
+] "
+ha 619819,728178,0,70344 2 0136
+^ "
+a^ "
+a. 372824,728178,0,135734 2 0137
+oq 372824,728178,0,135734 2 0140
+` "
+a 619819,466034,0,98840,-34078,98840 0 0141
+b 558070,728178,0,82430,-34078,82430 2 0142
+c 558070,466034,0,54760,-34078,54760 0 0143
+d 619819,728178,0,113890,-34078,113890 2 0144
+e 558070,466034,0,89131,-34078,89131 0 0145
+Fn 419432,728178,203890,228357,112722,116509 3 0146
+f "
+g 558070,466034,203890,110102,-35829,71266 1 0147
+h 619819,728178,0,98840,0,98840 2 0150
+i 372824,726931,0,119403,-17669,119403 2 0151
+j 372824,726931,203890,175326,50973,110102 3 0152
+k 558070,728178,0,116509,0,98840 2 0153
+l 311075,728178,0,113890,-30875,129714 2 0154
+m 990312,466034,0,98840,-17669,98840 0 0155
+n 681568,466034,0,98840,-17669,98840 0 0156
+o 619819,466034,0,82430,-34078,82430 0 0157
+p 619819,466034,203890,82430,-17182,82430 1 0160
+q 558070,466034,203890,110102,-34078,71266 1 0161
+r 526034,466034,0,116509,-17669,85634 0 0162
+s 510595,466034,0,85634,0,85634 0 0163
+t 403699,665763,0,101072,-39323,101072 2 0164
+u 650694,466034,0,98840,-17669,98840 0 0165
+v 558070,466034,0,116509,-17669,77672 0 0166
+w 805066,466034,0,116509,-17669,87382 0 0167
+x 587782,466034,0,131946,0,131946 0 0170
+y 588946,466034,203890,110102,-17669,71266 1 0171
+z 514382,466034,0,145637,0,98840 0 0172
+en 619819,466034,0,102880 0 0173
+em 1239638,466034,0,102880 0 0174
+a" 619819,728178,0,120296 2 0175
+~ 619819,728178,0,120296 2 0176
+a~ "
+char168 619819,728178,0,120298 2 0177
+ad "
diff --git a/gnu/usr.bin/groff/devices/devdvi/CW b/gnu/usr.bin/groff/devices/devdvi/CW
new file mode 100644
index 000000000000..fd94235ce8b4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/CW
@@ -0,0 +1,158 @@
+name CW
+special
+internalname cmtt10
+spacewidth 550498
+checksum -538297224
+designsize 10485760
+charset
+*G 550498,640797 2 0000
+*D 550498,640797 2 0001
+*H 550498,640797 2 0002
+*L 550498,640797 2 0003
+*C 550498,640797 2 0004
+*P 550498,640797 2 0005
+*S 550498,640797 2 0006
+*U 550498,640797 2 0007
+*F 550498,640797 2 0010
+*Q 550498,640797 2 0011
+*W 550498,640797 2 0012
+ff 550498,640797 2 0013
+fi 550498,640797 2 0014
+fl 550498,640797 2 0015
+Fi 550498,407779,233018 1 0016
+Fl 550498,407779,233018 1 0017
+.i 550498,451470 0 0020
+.j 550498,451470,233018 1 0021
+ga 550498,640797 2 0022
+char180 550498,640797 2 0023
+aa "
+ah 550498,593466 2 0024
+ab 550498,640797 2 0025
+char175 550498,593027 2 0026
+a- "
+ao 550498,640797 2 0027
+char184 550498,0,203891 1 0030
+ac "
+char223 550498,640797 2 0031
+ss "
+char230 550498,451470 0 0032
+ae "
+oe 550498,451470 0 0033
+char248 550498,567979,116509 3 0034
+/o "
+char198 550498,640797 2 0035
+AE "
+OE 550498,640797 2 0036
+char216 550498,699051,58254 3 0037
+/O "
+--- 550498,230104,116509 1 0040
+! 550498,640797 2 0041
+" 550498,640797 2 0042
+sh 550498,640797 2 0043
+# "
+Do 550498,728178,87381 3 0044
+$ "
+% 550498,728178,87381 3 0045
+& 550498,640797 2 0046
+' 550498,640797 2 0047
+( 550498,728178,87379 3 0050
+) 550498,728178,87379 3 0051
+* 550498,546134 2 0052
++ 550498,556326,-84470 2 0053
+, 550498,131072,145635 1 0054
+\- 550498,556326,-84470 2 0055
+- "
+. 550498,131072 0 0056
+sl 550498,728178,87379 3 0057
+/ "
+0 550498,640797 2 0060
+1 550498,640797 2 0061
+2 550498,640797 2 0062
+3 550498,640797 2 0063
+4 550498,640797 2 0064
+5 550498,640797 2 0065
+6 550498,640797 2 0066
+7 550498,640797 2 0067
+8 550498,640797 2 0070
+9 550498,640797 2 0071
+: 550498,451470 0 0072
+; 550498,451470,145635 1 0073
+< 550498,582542,-58254 2 0074
+= 550498,435813,-204984 0 0075
+> 550498,582542,-58254 2 0076
+? 550498,640797 2 0077
+at 550498,640797 2 0100
+@ "
+A 550498,640797 2 0101
+B 550498,640797 2 0102
+C 550498,640797 2 0103
+D 550498,640797 2 0104
+E 550498,640797 2 0105
+F 550498,640797 2 0106
+G 550498,640797 2 0107
+H 550498,640797 2 0110
+I 550498,640797 2 0111
+J 550498,640797 2 0112
+K 550498,640797 2 0113
+L 550498,640797 2 0114
+M 550498,640797 2 0115
+N 550498,640797 2 0116
+O 550498,640797 2 0117
+P 550498,640797 2 0120
+Q 550498,640797,145635 3 0121
+R 550498,640797 2 0122
+S 550498,640797 2 0123
+T 550498,640797 2 0124
+U 550498,640797 2 0125
+V 550498,640797 2 0126
+W 550498,640797 2 0127
+X 550498,640797 2 0130
+Y 550498,640797 2 0131
+Z 550498,640797 2 0132
+lB 550498,728178,87379 3 0133
+[ "
+rs 550498,728178,87379 3 0134
+\ "
+rB 550498,728178,87379 3 0135
+] "
+ha 550498,640797 2 0136
+^ "
+a^ "
+_ 550498,0,99757 1 0137
+oq 550498,640797 2 0140
+` "
+a 550498,451470 0 0141
+b 550498,640797 2 0142
+c 550498,451470 0 0143
+d 550498,640797 2 0144
+e 550498,451470 0 0145
+f 550498,640797 2 0146
+g 550498,451470,233018 1 0147
+h 550498,640797 2 0150
+i 550498,640797 2 0151
+j 550498,640797,233018 3 0152
+k 550498,640797 2 0153
+l 550498,640797 2 0154
+m 550498,451470 0 0155
+n 550498,451470 0 0156
+o 550498,451470 0 0157
+p 550498,451470,233018 1 0160
+q 550498,451470,233018 1 0161
+r 550498,451470 0 0162
+s 550498,451470 0 0163
+t 550498,580466 2 0164
+u 550498,451470 0 0165
+v 550498,451470 0 0166
+w 550498,451470 0 0167
+x 550498,451470 0 0170
+y 550498,451470,233018 1 0171
+z 550498,451470 0 0172
+{ 550498,728178,87379 3 0173
+lC "
+| 550498,728178,87379 3 0174
+ba "
+} 550498,728178,87379 3 0175
+rC "
+~ 550498,640797 2 0176
+a~ "
+--- 550498,640797 2 0177
diff --git a/gnu/usr.bin/groff/devices/devdvi/DESC b/gnu/usr.bin/groff/devices/devdvi/DESC
new file mode 100644
index 000000000000..c1a0e97aa831
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/DESC
@@ -0,0 +1,11 @@
+sizescale 100
+unitwidth 131072
+res 57816
+hor 1
+vert 1
+sizes 500 600 700 800 900 1000 1100 1200 1400 1440 1600 1728 1800
+2000 2074 2200 2400 2488 2800 3600 0
+fonts 13 R I B BI 0 0 0 0 0 MI S EX CW
+tcommand
+postpro grodvi
+print lpr -d
diff --git a/gnu/usr.bin/groff/devices/devdvi/EX b/gnu/usr.bin/groff/devices/devdvi/EX
new file mode 100644
index 000000000000..6e83d02bd6ef
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/EX
@@ -0,0 +1,144 @@
+name EX
+special
+internalname cmex10
+checksum -89033454
+designsize 10485760
+charset
+parenleft0 480600,41942,1216362 1 0000
+parenright0 480600,41942,1216362 1 0001
+bracketleft0 436909,41942,1216362 1 0002
+bracketright0 436909,41942,1216362 1 0003
+floorleft0 495163,41942,1216362 1 0004
+floorright0 495163,41942,1216362 1 0005
+ceilingleft0 495163,41942,1216362 1 0006
+ceilingright0 495163,41942,1216362 1 0007
+braceleft0 611672,41942,1216362 1 0010
+braceright0 611672,41942,1216362 1 0011
+angleleft0 495163,41942,1216362 1 0012
+angleright0 495163,41942,1216362 1 0013
+barex 349526,0,629152 1 0014
+bardblex 582544,0,629152 1 0015
+slash0 605845,41942,1216362 1 0016
+backslash0 605845,41942,1216362 1 0017
+parenleft1 626235,41942,1845514 1 0020
+parenright1 626235,41942,1845514 1 0021
+parenleft2 771872,41942,2474666 1 0022
+parenright2 771872,41942,2474666 1 0023
+bracketleft2 553418,41942,2474666 1 0024
+bracketright2 553418,41942,2474666 1 0025
+floorleft2 611672,41942,2474666 1 0026
+floorright2 611672,41942,2474666 1 0027
+ceilingleft2 611672,41942,2474666 1 0030
+ceilingright2 611672,41942,2474666 1 0031
+braceleft2 786434,41942,2474666 1 0032
+braceright2 786434,41942,2474666 1 0033
+angleleft2 786434,41942,2474666 1 0034
+angleright2 786434,41942,2474666 1 0035
+slash2 1095182,41942,2474666 1 0036
+backslash2 1095182,41942,2474666 1 0037
+parenleft3 830126,41942,3103818 1 0040
+parenright3 830126,41942,3103818 1 0041
+bracketleft3 611672,41942,3103818 1 0042
+bracketright3 611672,41942,3103818 1 0043
+floorleft3 669926,41942,3103818 1 0044
+floorright3 669926,41942,3103818 1 0045
+ceilingleft3 669926,41942,3103818 1 0046
+ceilingright3 669926,41942,3103818 1 0047
+braceleft3 844691,41942,3103818 1 0050
+braceright3 844691,41942,3103818 1 0051
+angleleft3 844691,41942,3103818 1 0052
+angleright3 844691,41942,3103818 1 0053
+slash3 1339851,41942,3103818 1 0054
+backslash3 1339851,41942,3103818 1 0055
+slash1 850515,41942,1845514 1 0056
+backslash1 850515,41942,1845514 1 0057
+parenlefttp 917507,41942,1845514 1 0060
+parenrighttp 917507,41942,1845514 1 0061
+bracketlefttp 699053,41942,1845514 1 0062
+bracketrighttp 699053,41942,1845514 1 0063
+bracketleftbt 699053,41942,1845514 1 0064
+bracketrightbt 699053,41942,1845514 1 0065
+bracketleftex 699053,0,629152 1 0066
+bracketrightex 699053,0,629152 1 0067
+lt 932070,0,943728 1 0070
+bracelefttp "
+rt 932070,0,943728 1 0071
+bracerighttp "
+lb 932070,0,943728 1 0072
+braceleftbt "
+rb 932070,0,943728 1 0073
+bracerightbt "
+lk 932070,0,1887456 1 0074
+braceleftmid "
+rk 932070,0,1887456 1 0075
+bracerightmid "
+braceleftex 932070,0,314576 1 0076
+bracerightex "
+braceex "
+arrowvertex 699053,0,629152 1 0077
+parenleftbt 917507,41942,1845514 1 0100
+parenrightbt 917507,41942,1845514 1 0101
+parenleftex 917507,0,629152 1 0102
+parenrightex 917507,0,629152 1 0103
+angleleft1 640798,41942,1845514 1 0104
+angleright1 640798,41942,1845514 1 0105
+--- 873816,0,1048590 1 0106
+--- 1165088,104859,1572877 1 0107
+--- 495162,0,1165096,203891 1 0110
+ointegral 582544,0,2330194,466035 1 0111
+ois "
+--- 1165088,0,1048590 1 0112
+bigcircledot 1584520,104859,1572877 1 0113
+--- 1165088,0,1048590 1 0114
+bigcircleplus 1584520,104859,1572877 1 0115
+--- 1165088,0,1048590 1 0116
+bigcirclemultiply 1584520,104859,1572877 1 0117
+--- 1106834,0,1048590 1 0120
+--- 990325,0,1048590 1 0121
+--- 495162,0,1165096,203891 1 0122
+--- 873816,0,1048590 1 0123
+--- 873816,0,1048590 1 0124
+--- 873816,0,1048590 1 0125
+--- 873816,0,1048590 1 0126
+--- 873816,0,1048590 1 0127
+sum 1514614,104859,1572877 1 0130
+product 1339851,104859,1572877 1 0131
+integral 582544,0,2330194,466035 1 0132
+is "
+bigunion 1165088,104859,1572877 1 0133
+bigintersection 1165088,104859,1572877 1 0134
+bigunionplus 1165088,104859,1572877 1 0135
+biglogicaland 1165088,104859,1572877 1 0136
+biglogicalor 1165088,104859,1572877 1 0137
+--- 990325,0,1048590 1 0140
+coproduct 1339851,104859,1572877 1 0141
+--- 582544,757306 2 0142
+--- 1048579,786432 2 0143
+--- 1514614,786432 2 0144
+--- 582544,757306 2 0145
+--- 1048579,786432 2 0146
+--- 1514614,786432 2 0147
+bracketleft1 495163,41942,1845514 1 0150
+bracketright1 495163,41942,1845514 1 0151
+floorleft1 553418,41942,1845514 1 0152
+floorright1 553418,41942,1845514 1 0153
+ceilingleft1 553418,41942,1845514 1 0154
+ceilingright1 553418,41942,1845514 1 0155
+braceleft1 699053,41942,1845514 1 0156
+braceright1 699053,41942,1845514 1 0157
+sr0 1048579,41942,1216362 1 0160
+sr1 1048579,41942,1845514 1 0161
+sr2 1048579,41942,2474666 1 0162
+sr3 1048579,41942,3103818 1 0163
+--- 1106834,0,1887456 1 0164
+--- 1106834,0,629152 1 0165
+--- 1106834,41942,587210 1 0166
+arrowvertdblex 815562,0,629152 1 0167
+arrowverttp 699053,0,629152 1 0170
+arrowvertbt 699053,0,629152 1 0171
+--- 471864,125827 0 0172
+--- 471864,125827 0 0173
+--- 471864,125827 0 0174
+--- 471864,125827 0 0175
+arrowvertdbltp 815562,0,629152 1 0176
+arrowvertdblbt 815562,0,629152 1 0177
diff --git a/gnu/usr.bin/groff/devices/devdvi/H b/gnu/usr.bin/groff/devices/devdvi/H
new file mode 100644
index 000000000000..96ae0f5fe0b1
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/H
@@ -0,0 +1,302 @@
+name H
+internalname cmss10
+spacewidth 349526
+ligatures ff fi fl ffi ffl 0
+checksum 1831058770
+designsize 10485760
+kernpairs
+ff ' 72818
+ff ? 72818
+ff ! 72818
+ff ) 72818
+ff rB 72818
+ff ] 72818
+' ? 116509
+' ! 116509
+A t -29128
+A C -29128
+A O -29128
+A G -29128
+A U -29128
+A Q -29128
+A T -87382
+A Y -87382
+A V -116509
+A W -116509
+D X -29128
+D W -29128
+D A -29128
+D V -29128
+D Y -29128
+F o -29128
+F e -29128
+F u -29128
+F r -29128
+F a -29128
+F A -87382
+F O -29128
+F C -29128
+F G -29128
+F Q -29128
+I I 29128
+K O -29128
+K C -29128
+K G -29128
+K Q -29128
+L T -87382
+L Y -87382
+L V -116509
+L W -116509
+O X -29128
+O W -29128
+O A -29128
+O V -29128
+O Y -29128
+P A -87382
+P o -29128
+P e -29128
+P a -29128
+P . -87382
+P , -87382
+T y -87382
+T e -87382
+T o -87382
+T r -87382
+T a -87382
+T A -87382
+T u -87382
+V o -29128
+V e -29128
+V u -29128
+V r -29128
+V a -29128
+V A -87382
+V O -29128
+V C -29128
+V G -29128
+V Q -29128
+W o -29128
+W e -29128
+W u -29128
+W r -29128
+W a -29128
+W A -87382
+W O -29128
+W C -29128
+W G -29128
+W Q -29128
+X O -29128
+X C -29128
+X G -29128
+X Q -29128
+Y e -87382
+Y o -87382
+Y r -87382
+Y a -87382
+Y A -87382
+Y u -87382
+a r -29128
+a y -29128
+a w -29128
+b e 29128
+b o 29128
+b x -29128
+b d 29128
+b c 29128
+b q 29128
+b r -29128
+b y -29128
+b w -29128
+f ' 72818
+f ? 72818
+f ! 72818
+f ) 72818
+f rB 72818
+f ] 72818
+g j 29128
+k e -29128
+k a -29128
+k o -29128
+k c -29128
+o e 29128
+o o 29128
+o x -29128
+o d 29128
+o c 29128
+o q 29128
+o r -29128
+o y -29128
+o w -29128
+p e 29128
+p o 29128
+p x -29128
+p d 29128
+p c 29128
+p q 29128
+p r -29128
+p y -29128
+p w -29128
+t y -29128
+t w -29128
+u w -29128
+w e -29128
+w a -29128
+w o -29128
+w c -29128
+y o -29128
+y e -29128
+y a -29128
+y . -87382
+y , -87382
+charset
+*G 567981,728178,0,0,0,-145637 2 0000
+*D 873816,728178 2 0001
+*H 815562,728178,0,0,-29128,-29128 2 0002
+*L 640800,728178 2 0003
+*C 699053,728178 2 0004
+*P 742746,728178 2 0005
+*S 757307,728178 2 0006
+*U 815562,728178,0,0,-29128,-145637 2 0007
+*F 757307,728178,0,0,-29128 2 0010
+*Q 815562,728178,0,0,-29128,-72818 2 0011
+*W 757307,728178 2 0012
+ff 611672,728178,0,72818 2 0013
+fi 562155,728178 2 0014
+fl 562155,728178 2 0015
+Fi 853427,728178 2 0016
+Fl 853427,728178 2 0017
+.i 250494,466034 0 0020
+.j 279622,466034,203890 1 0021
+ga 524290,728178 2 0022
+char180 524290,728178 2 0023
+aa "
+ah 524290,662642 2 0024
+ab 524290,728178 2 0025
+char175 524290,638464 2 0026
+a- "
+ao 699054,728178 2 0027
+char184 466035,0,178403 1 0030
+ac "
+char223 503902,728178 2 0031
+ss "
+char230 757307,466034 0 0032
+ae "
+oe 815562,466034 0 0033
+char248 524290,567979,101946 3 0034
+/o "
+char198 902944,728178 2 0035
+AE "
+OE 1019453,728178 2 0036
+char216 815562,779150,50973 3 0037
+/O "
+--- 250494,466034 0 0040
+! 334963,728178 2 0041
+rq 524290,728178 2 0042
+sh 873816,728178,203888 3 0043
+# "
+Do 524290,786432,58254 3 0044
+$ "
+% 873816,786432,58254 3 0045
+& 795173,728178 2 0046
+' 291272,728178 2 0047
+( 407781,786432,262144 3 0050
+) 407781,786432,262144 3 0051
+* 524290,786432 2 0052
++ 815562,611670,87382 3 0053
+, 291272,87381,131072 1 0054
+char173 349526,466034 0 0055
+hy "
+- "
+. 291272,87381 0 0056
+sl 524290,786432,262144 3 0057
+/ "
+0 524290,687400 2 0060
+1 524290,687400 2 0061
+2 524290,687400 2 0062
+3 524290,687400 2 0063
+4 524290,687400 2 0064
+5 524290,687400 2 0065
+6 524290,687400 2 0066
+7 524290,687400 2 0067
+8 524290,687400 2 0070
+9 524290,687400 2 0071
+: 291272,466034 0 0072
+; 291272,466034,131072 1 0073
+char161 334963,524288,203890 3 0074
+r! "
+= 815562,387973,-136315 0 0075
+char191 495163,524288,203890 3 0076
+r? "
+? 495163,728178 2 0077
+at 699053,728178 2 0100
+@ "
+A 699054,728178 2 0101
+B 699054,728178 2 0102
+C 669926,728178,0,0,-29128 2 0103
+D 757309,728178,0,0,0,-29128 2 0104
+E 626235,728178 2 0105
+F 597109,728178,0,0,0,-145637 2 0106
+G 699053,728178,0,0,-29128 2 0107
+H 742746,728178 2 0110
+I 291274,728178 2 0111
+J 495163,728178,0,0,0,-29128 2 0112
+K 728182,728178 2 0113
+L 567981,728178,0,0,0,58254 2 0114
+M 917509,728178 2 0115
+N 742746,728178 2 0116
+O 771870,728178,0,0,-29128,-29128 2 0117
+P 669926,728178,0,0,0,-145637 2 0120
+Q 771870,728178,131072,0,-29128 3 0121
+R 677208,728178 2 0122
+S 582544,728178 2 0123
+T 713616,728178,0,0,0,-145637 2 0124
+U 720901,728178,0,0,29126 2 0125
+V 699054,728178,0,14563,43691,-218454 2 0126
+W 990326,728178,0,14563,43691,-131074 2 0127
+X 699054,728178 2 0130
+Y 699054,728178,0,26214,29128,-206803 2 0131
+Z 640798,728178 2 0132
+lB 302923,786432,262144 3 0133
+[ "
+lq 524290,728178 2 0134
+rB 302923,786432,262144 3 0135
+] "
+ha 524290,728178 2 0136
+^ "
+a^ "
+a. 291272,712366 2 0137
+oq 291272,728178 2 0140
+` "
+a 503901,466034 0 0141
+b 541766,728178 2 0142
+c 466035,466034 0 0143
+d 541766,728178 2 0144
+e 466035,466034 0 0145
+f 320400,728178,0,72818 2 0146
+g 524290,466034,203890,14563 1 0147
+h 541766,728178 2 0150
+i 250494,712366 2 0151
+j 279622,712366,203890 3 0152
+k 512640,728178 2 0153
+l 250494,728178 2 0154
+m 833038,466034 0 0155
+n 541766,466034 0 0156
+o 524290,466034 0 0157
+p 541766,466034,203890 1 0160
+q 541766,466034,203890 1 0161
+r 358266,466034,0,14563 0 0162
+s 401955,466034 0 0163
+t 378653,599189 2 0164
+u 541766,466034 0 0165
+v 483512,466034,0,14563 0 0166
+w 716530,466034,0,14563 0 0167
+x 483512,466034 0 0170
+y 483512,466034,203890,14563 1 0171
+z 455840,466034 0 0172
+en 524290,466034,0,29128 0 0173
+em 1048579,466034,0,29128 0 0174
+a" 524290,728178 2 0175
+~ 524290,709454 2 0176
+a~ "
+char168 524290,712366 2 0177
+ad "
diff --git a/gnu/usr.bin/groff/devices/devdvi/HB b/gnu/usr.bin/groff/devices/devdvi/HB
new file mode 100644
index 000000000000..aaff8968112c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/HB
@@ -0,0 +1,302 @@
+name HB
+internalname cmssbx10
+spacewidth 384480
+ligatures ff fi fl ffi ffl 0
+checksum -244629176
+designsize 10485760
+kernpairs
+ff ' 80101
+ff ? 80101
+ff ! 80101
+ff ) 80101
+ff rB 80101
+ff ] 80101
+' ? 128160
+' ! 128160
+A t -32040
+A C -32040
+A O -32040
+A G -32040
+A U -32040
+A Q -32040
+A T -96120
+A Y -96120
+A V -128160
+A W -128160
+D X -32040
+D W -32040
+D A -32040
+D V -32040
+D Y -32040
+F o -32040
+F e -32040
+F u -32040
+F r -32040
+F a -32040
+F A -96120
+F O -32040
+F C -32040
+F G -32040
+F Q -32040
+I I 32040
+K O -32040
+K C -32040
+K G -32040
+K Q -32040
+L T -96120
+L Y -96120
+L V -128160
+L W -128160
+O X -32040
+O W -32040
+O A -32040
+O V -32040
+O Y -32040
+P A -96120
+P o -32040
+P e -32040
+P a -32040
+P . -96120
+P , -96120
+T y -96120
+T e -96120
+T o -96120
+T r -96120
+T a -96120
+T A -96120
+T u -96120
+V o -32040
+V e -32040
+V u -32040
+V r -32040
+V a -32040
+V A -96120
+V O -32040
+V C -32040
+V G -32040
+V Q -32040
+W o -32040
+W e -32040
+W u -32040
+W r -32040
+W a -32040
+W A -96120
+W O -32040
+W C -32040
+W G -32040
+W Q -32040
+X O -32040
+X C -32040
+X G -32040
+X Q -32040
+Y e -96120
+Y o -96120
+Y r -96120
+Y a -96120
+Y A -96120
+Y u -96120
+a r -32040
+a y -32040
+a w -32040
+b e 32040
+b o 32040
+b x -32040
+b d 32040
+b c 32040
+b q 32040
+b r -32040
+b y -32040
+b w -32040
+f ' 80101
+f ? 80101
+f ! 80101
+f ) 80101
+f rB 80101
+f ] 80101
+g j 32040
+k e -32040
+k a -32040
+k o -32040
+k c -32040
+o e 32040
+o o 32040
+o x -32040
+o d 32040
+o c 32040
+o q 32040
+o r -32040
+o y -32040
+o w -32040
+p e 32040
+p o 32040
+p x -32040
+p d 32040
+p c 32040
+p q 32040
+p r -32040
+p y -32040
+p w -32040
+t y -32040
+t w -32040
+u w -32040
+w e -32040
+w a -32040
+w o -32040
+w c -32040
+y o -32040
+y e -32040
+y a -32040
+y . -96120
+y , -96120
+charset
+*G 608760,728178,0,0,0,-160200 2 0000
+*D 961200,728178 2 0001
+*H 897120,728178,0,0,-32040,-32040 2 0002
+*L 704880,728178 2 0003
+*C 768960,728178 2 0004
+*P 833040,728178 2 0005
+*S 833040,728178 2 0006
+*U 897120,728178,0,0,-32040,-160200 2 0007
+*F 833040,728178,0,0,-32040 2 0010
+*Q 897120,728178,0,0,-32040,-80101 2 0011
+*W 833040,728178 2 0012
+ff 672840,728178,0,80101 2 0013
+fi 614586,728178 2 0014
+fl 614586,728178 2 0015
+Fi 934986,728178 2 0016
+Fl 934986,728178 2 0017
+.i 267971,480597 0 0020
+.j 300011,480597,203890 1 0021
+ga 576720,728178 2 0022
+char180 576720,728178 2 0023
+aa "
+ah 576720,666283 2 0024
+ab 576720,728178 2 0025
+char175 576720,668757 2 0026
+a- "
+ao 768960,728178 2 0027
+char184 512640,0,178403 1 0030
+ac "
+char223 592739,728178 2 0031
+ss "
+char230 833040,480597 0 0032
+ae "
+oe 897120,480597 0 0033
+char248 576720,582542,101946 3 0034
+/o "
+char198 993240,728178 2 0035
+AE "
+OE 1121400,728178 2 0036
+char216 897120,779150,50973 3 0037
+/O "
+--- 267971,480597 0 0040
+! 384480,728178 2 0041
+rq 585458,728178 2 0042
+sh 961200,728178,203888 3 0043
+# "
+Do 576720,786432,58254 3 0044
+$ "
+% 1079109,786432,58254 3 0045
+& 870906,728178 2 0046
+' 320400,728178 2 0047
+( 448560,786432,262144 3 0050
+) 448560,786432,262144 3 0051
+* 576720,786432 2 0052
++ 897120,646624,122336 3 0053
+, 320400,136898,110683 1 0054
+char173 384480,480597 0 0055
+hy "
+- "
+. 320400,136898 0 0056
+sl 576720,786432,262144 3 0057
+/ "
+0 576720,728178 2 0060
+1 576720,728178 2 0061
+2 576720,728178 2 0062
+3 576720,728178 2 0063
+4 576720,728178 2 0064
+5 576720,728178 2 0065
+6 576720,728178 2 0066
+7 576720,728178 2 0067
+8 576720,728178 2 0070
+9 576720,728178 2 0071
+: 320400,480597 0 0072
+; 320400,480597,110683 1 0073
+char161 384480,524288,203890 3 0074
+r! "
+= 897120,425984,-98304 0 0075
+char191 544680,524288,203890 3 0076
+r? "
+? 544680,728178 2 0077
+at 768960,728178 2 0100
+@ "
+A 768960,728178 2 0101
+B 768960,728178 2 0102
+C 736920,728178,0,0,-32040 2 0103
+D 833040,728178,0,0,0,-32040 2 0104
+E 672840,728178 2 0105
+F 640800,728178,0,0,0,-160200 2 0106
+G 768960,728178,0,0,-32040 2 0107
+H 833040,728178 2 0110
+I 346614,728178 2 0111
+J 544680,728178,0,0,0,-32040 2 0112
+K 801000,728178 2 0113
+L 608760,728178,0,0,0,64080 2 0114
+M 1025280,728178 2 0115
+N 833040,728178 2 0116
+O 833040,728178,0,0,-32040,-32040 2 0117
+P 736920,728178,0,0,0,-160200 2 0120
+Q 833040,728178,110683,0,-32040 3 0121
+R 736920,728178 2 0122
+S 640800,728178 2 0123
+T 768960,728178,0,0,0,-160200 2 0124
+U 801000,728178,0,0,32040 2 0125
+V 768960,728178,0,16021,48061,-240299 2 0126
+W 1089360,728178,0,16021,48061,-144179 2 0127
+X 768960,728178 2 0130
+Y 768960,728178,0,28835,32040,-227485 2 0131
+Z 704880,728178 2 0132
+lB 359722,786432,262144 3 0133
+[ "
+lq 585458,728178 2 0134
+rB 359722,786432,262144 3 0135
+] "
+ha 576720,728178 2 0136
+^ "
+a^ "
+a. 320400,728178 2 0137
+oq 320400,728178 2 0140
+` "
+a 550506,480597 0 0141
+b 588371,728178 2 0142
+c 512640,480597 0 0143
+d 588371,728178 2 0144
+e 535942,480597 0 0145
+f 352440,728178,0,80101 2 0146
+g 576720,480597,203890,16021 1 0147
+h 588371,728178 2 0150
+i 267971,728178 2 0151
+j 300011,728178,203890 3 0152
+k 556331,728178 2 0153
+l 267971,728178 2 0154
+m 908771,480597 0 0155
+n 588371,480597 0 0156
+o 576720,480597 0 0157
+p 588371,480597,203890 1 0160
+q 588371,480597,203890 1 0161
+r 390306,480597,0,16021 0 0162
+s 442152,480597 0 0163
+t 423802,617914 2 0164
+u 588371,480597 0 0165
+v 524291,480597,0,16021 0 0166
+w 780611,480597,0,16021 0 0167
+x 524291,480597 0 0170
+y 524291,480597,203890,16021 1 0171
+z 499533,480597 0 0172
+en 576720,480597,0,32040 0 0173
+em 1153440,480597,0,32040 0 0174
+a" 576720,728178 2 0175
+~ 576720,728178 2 0176
+a~ "
+char168 576720,728178 2 0177
+ad "
diff --git a/gnu/usr.bin/groff/devices/devdvi/HI b/gnu/usr.bin/groff/devices/devdvi/HI
new file mode 100644
index 000000000000..dcfcced1a557
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/HI
@@ -0,0 +1,303 @@
+name HI
+internalname cmssi10
+spacewidth 349526
+slant 11.999911
+ligatures ff fi fl ffi ffl 0
+checksum -984248855
+designsize 10485760
+kernpairs
+ff ' 72818
+ff ? 72818
+ff ! 72818
+ff ) 72818
+ff rB 72818
+ff ] 72818
+' ? 116509
+' ! 116509
+A t -29128
+A C -29128
+A O -29128
+A G -29128
+A U -29128
+A Q -29128
+A T -87382
+A Y -87382
+A V -116509
+A W -116509
+D X -29128
+D W -29128
+D A -29128
+D V -29128
+D Y -29128
+F o -29128
+F e -29128
+F u -29128
+F r -29128
+F a -29128
+F A -87382
+F O -29128
+F C -29128
+F G -29128
+F Q -29128
+I I 29128
+K O -29128
+K C -29128
+K G -29128
+K Q -29128
+L T -87382
+L Y -87382
+L V -116509
+L W -116509
+O X -29128
+O W -29128
+O A -29128
+O V -29128
+O Y -29128
+P A -87382
+P o -29128
+P e -29128
+P a -29128
+P . -87382
+P , -87382
+T y -87382
+T e -87382
+T o -87382
+T r -87382
+T a -87382
+T A -87382
+T u -87382
+V o -29128
+V e -29128
+V u -29128
+V r -29128
+V a -29128
+V A -87382
+V O -29128
+V C -29128
+V G -29128
+V Q -29128
+W o -29128
+W e -29128
+W u -29128
+W r -29128
+W a -29128
+W A -87382
+W O -29128
+W C -29128
+W G -29128
+W Q -29128
+X O -29128
+X C -29128
+X G -29128
+X Q -29128
+Y e -87382
+Y o -87382
+Y r -87382
+Y a -87382
+Y A -87382
+Y u -87382
+a r -29128
+a y -29128
+a w -29128
+b e 29128
+b o 29128
+b x -29128
+b d 29128
+b c 29128
+b q 29128
+b r -29128
+b y -29128
+b w -29128
+f ' 72818
+f ? 72818
+f ! 72818
+f ) 72818
+f rB 72818
+f ] 72818
+g j 29128
+k e -29128
+k a -29128
+k o -29128
+k c -29128
+o e 29128
+o o 29128
+o x -29128
+o d 29128
+o c 29128
+o q 29128
+o r -29128
+o y -29128
+o w -29128
+p e 29128
+p o 29128
+p x -29128
+p d 29128
+p c 29128
+p q 29128
+p r -29128
+p y -29128
+p w -29128
+t y -29128
+t w -29128
+u w -29128
+w e -29128
+w a -29128
+w o -29128
+w c -29128
+y o -29128
+y e -29128
+y a -29128
+y . -87382
+y , -87382
+charset
+*G 567981,728178,0,140214,0,-5422 2 0000
+*D 873816,728178 2 0001
+*H 815562,728178,0,79216,-75562,50088 2 0002
+*L 640800,728178 2 0003
+*C 699053,728178,0,134389,0,67195 2 0004
+*P 742746,728178,0,84870,0,42435 2 0005
+*S 757307,728178,0,125650,0,62826 2 0006
+*U 815562,728178,0,94694,-152950,-50942 2 0007
+*F 757307,728178,0,48261,-106517,48261 2 0010
+*Q 815562,728178,0,94694,-152950,-10907 2 0011
+*W 757307,728178,0,86955,0,43478 2 0012
+ff 611672,728178,0,227595 2 0013
+fi 562155,728178,0,102349 2 0014
+fl 562155,728178,0,99435 2 0015
+Fi 853427,728178,0,102349 2 0016
+Fl 853427,728178,0,99435 2 0017
+.i 250494,466034,0,43715 0 0020
+.j 279622,466034,203890,43715 1 0021
+ga 524290,728178 2 0022
+char180 524290,728178,0,96523 2 0023
+aa "
+ah 524290,662642,0,88419 2 0024
+ab 524290,728178,0,99435 2 0025
+char175 524290,638464,0,92018 2 0026
+a- "
+ao 773347,728178 2 0027
+char184 466035,0,178403 1 0030
+ac "
+char223 503902,728178,0,96523 2 0031
+ss "
+char230 757307,466034,0,71070 0 0032
+ae "
+oe 815562,466034,0,71070 0 0033
+char248 524290,567979,101946,50821 3 0034
+/o "
+char198 902944,728178,0,125650 2 0035
+AE "
+OE 1019453,728178,0,125650 2 0036
+char216 815562,779150,50973,79216 3 0037
+/O "
+--- 250494,466034 0 0040
+! 334963,728178,0,60114 2 0041
+rq 524290,728178,0,3315 2 0042
+sh 873816,728178,203888,53338 3 0043
+# "
+Do 524290,786432,58254,116982 3 0044
+$ "
+% 873816,786432,58254,32782 3 0045
+& 795173,728178,0,32064 2 0046
+' 291272,728178,0,81960 2 0047
+( 407781,786432,262144,138032 3 0050
+) 407781,786432,262144,26592 3 0051
+* 524290,786432,0,123469 2 0052
++ 815562,611670,87382,26592 3 0053
+, 291272,87381,131072 1 0054
+char173 349526,466034,0,20402 0 0055
+hy "
+- "
+. 291272,87381 0 0056
+sl 524290,786432,262144,138032 3 0057
+/ "
+0 524290,687400,0,116982 2 0060
+1 524290,687400,0,116982 2 0061
+2 524290,687400,0,116982 2 0062
+3 524290,687400,0,116982 2 0063
+4 524290,687400,0,116982 2 0064
+5 524290,687400,0,116982 2 0065
+6 524290,687400,0,116982 2 0066
+7 524290,687400,0,116982 2 0067
+8 524290,687400,0,116982 2 0070
+9 524290,687400,0,116982 2 0071
+: 291272,466034,0,26240 0 0072
+; 291272,466034,131072,26240 1 0073
+char161 334963,524288,203890,16776 3 0074
+r! "
+= 815562,387973,-136315,53338 0 0075
+char191 495163,524288,203890 3 0076
+r? "
+? 495163,728178,0,123822 2 0077
+at 699053,728178,0,79216 2 0100
+@ "
+A 699054,728178 2 0101
+B 699054,728178,0,86955,0,43478 2 0102
+C 669926,728178,0,125650,-75562,62826 2 0103
+D 757309,728178,0,79216,0,50088 2 0104
+E 626235,728178,0,125650,0,62826 2 0105
+F 597109,728178,0,140214,0,-5422 2 0106
+G 699053,728178,0,125650,-75562,62826 2 0107
+H 742746,728178,0,84870,0,42435 2 0110
+I 291274,728178,0,140214,0,70107 2 0111
+J 495163,728178,0,84870,0,13307 2 0112
+K 728182,728178,0,125650,0,62826 2 0113
+L 567981,728178,0,0,0,58254 2 0114
+M 917509,728178,0,84870,0,13307 2 0115
+N 742746,728178,0,84870,0,13307 2 0116
+O 771870,728178,0,79216,-75562,50088 2 0117
+P 669926,728178,0,86955,0,-58682 2 0120
+Q 771870,728178,131072,79216,-75562,79216 3 0121
+R 677208,728178,0,86955,0,65216 2 0122
+S 582544,728178,0,96523,0,48262 2 0123
+T 713616,728178,0,140214,-116083,-5422 2 0124
+U 720901,728178,0,84870,-75562,13307 2 0125
+V 699054,728178,0,169341,-111086,-63677 2 0126
+W 990326,728178,0,169341,-111086,23704 2 0127
+X 699054,728178,0,140214,0,70107 2 0130
+Y 699054,728178,0,180992,-125650,-52026 2 0131
+Z 640798,728178,0,125650,0,62826 2 0132
+lB 302923,786432,262144,167160 3 0133
+[ "
+lq 524290,728178,0,148952 2 0134
+rB 302923,786432,262144,91429 3 0135
+] "
+ha 524290,728178,0,83776 2 0136
+^ "
+a^ "
+a. 291272,712366,0,81512 2 0137
+oq 291272,728178,0,81960 2 0140
+` "
+a 503901,466034,0,10283 0 0141
+b 541766,728178,0,32053 2 0142
+c 466035,466034,0,87406 0 0143
+d 541766,728178,0,99435 2 0144
+e 466035,466034,0,71070 0 0145
+f 320400,728178,0,227595 2 0146
+g 524290,466034,203890,113621 1 0147
+h 541766,728178,0,18642 2 0150
+i 250494,712366,0,101901 2 0151
+j 279622,712366,203890,96075 3 0152
+k 512640,728178,0,87406 2 0153
+l 250494,728178,0,99435 2 0154
+m 833038,466034,0,18642 0 0155
+n 541766,466034,0,18642 0 0156
+o 524290,466034,0,69341 0 0157
+p 541766,466034,203890,40790 1 0160
+q 541766,466034,203890,43715 1 0161
+r 358266,466034,0,113621 0 0162
+s 401955,466034,0,81581 0 0163
+t 378653,599189,0,75757 2 0164
+u 541766,466034,0,43715 0 0165
+v 483512,466034,0,113621 0 0166
+w 716530,466034,0,113621 0 0167
+x 483512,466034,0,96144 0 0170
+y 483512,466034,203890,113621 1 0171
+z 455840,466034,0,91776 0 0172
+en 524290,466034,0,90349 0 0173
+em 1048579,466034,0,90349 0 0174
+a" 524290,728178,0,96523 2 0175
+~ 524290,709454,0,92544 2 0176
+a~ "
+char168 524290,712366,0,66949 2 0177
+ad "
diff --git a/gnu/usr.bin/groff/devices/devdvi/I b/gnu/usr.bin/groff/devices/devdvi/I
new file mode 100644
index 000000000000..a46501669f44
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/I
@@ -0,0 +1,353 @@
+name I
+special
+internalname cmti10
+spacewidth 375155
+slant 14.036243
+ligatures ff fi fl ffi ffl 0
+checksum -50321606
+designsize 10485760
+kernpairs
+ff ' 109373
+ff ? 109373
+ff ! 109373
+ff ) 109373
+ff rB 109373
+ff ] 109373
+' ' -80390
+' ? 107187
+' ! 107187
+A n -26797
+A l -26797
+A r -26797
+A u -26797
+A m -26797
+A t -26797
+A i -26797
+A C -26797
+A O -26797
+A G -26797
+A h -26797
+A b -26797
+A U -26797
+A k -26797
+A v -26797
+A w -26797
+A Q -26797
+A T -80390
+A Y -80390
+A V -107187
+A W -107187
+A e -53594
+A a -53594
+A o -53594
+A d -53594
+A c -53594
+A g -53594
+A q -53594
+D X -26797
+D W -26797
+D A -26797
+D V -26797
+D Y -26797
+F o -80390
+F e -80390
+F u -80390
+F r -80390
+F a -80390
+F A -107187
+F O -26797
+F C -26797
+F G -26797
+F Q -26797
+K O -26797
+K C -26797
+K G -26797
+K Q -26797
+L T -80390
+L Y -80390
+L V -107187
+L W -107187
+L e -53594
+L a -53594
+L o -53594
+L d -53594
+L c -53594
+L g -53594
+L q -53594
+O X -26797
+O W -26797
+O A -26797
+O V -26797
+O Y -26797
+P A -80390
+R n -26797
+R l -26797
+R r -26797
+R u -26797
+R m -26797
+R t -26797
+R i -26797
+R C -26797
+R O -26797
+R G -26797
+R h -26797
+R b -26797
+R U -26797
+R k -26797
+R v -26797
+R w -26797
+R Q -26797
+R T -80390
+R Y -80390
+R V -107187
+R W -107187
+R e -53594
+R a -53594
+R o -53594
+R d -53594
+R c -53594
+R g -53594
+R q -53594
+T y -80390
+T e -80390
+T o -80390
+T r -80390
+T a -80390
+T u -80390
+T A -80390
+V o -80390
+V e -80390
+V u -80390
+V r -80390
+V a -80390
+V A -107187
+V O -26797
+V C -26797
+V G -26797
+V Q -26797
+W A -80390
+X O -26797
+X C -26797
+X G -26797
+X Q -26797
+Y e -80390
+Y o -80390
+Y r -80390
+Y a -80390
+Y u -80390
+Y A -80390
+oq oq -80390
+oq ` -80390
+` oq -80390
+` ` -80390
+b e -53594
+b a -53594
+b o -53594
+b d -53594
+b c -53594
+b g -53594
+b q -53594
+c e -53594
+c a -53594
+c o -53594
+c d -53594
+c c -53594
+c g -53594
+c q -53594
+d l 53594
+e e -53594
+e a -53594
+e o -53594
+e d -53594
+e c -53594
+e g -53594
+e q -53594
+Fn ' 109373
+f ' 109373
+Fn ? 109373
+f ? 109373
+Fn ! 109373
+f ! 109373
+Fn ) 109373
+f ) 109373
+Fn rB 109373
+Fn ] 109373
+f rB 109373
+f ] 109373
+l l 53594
+n ' -107187
+o e -53594
+o a -53594
+o o -53594
+o d -53594
+o c -53594
+o g -53594
+o q -53594
+p e -53594
+p a -53594
+p o -53594
+p d -53594
+p c -53594
+p g -53594
+p q -53594
+r e -53594
+r a -53594
+r o -53594
+r d -53594
+r c -53594
+r g -53594
+r q -53594
+w l 53594
+charset
+*G 657686,716526,0,139518,0,5534 2 0000
+*D 857498,716526 2 0001
+*H 803904,716526,0,98595,-80538,71798 2 0002
+*L 725843,716526 2 0003
+*C 696717,716526,0,160373,0,80187 2 0004
+*P 779437,716526,0,171851,0,85926 2 0005
+*S 750310,716526,0,126120,0,63061 2 0006
+*U 803904,716526,0,116509,-170102,-17475 2 0007
+*F 750310,716526,0,62770,-116363,62770 2 0010
+*Q 803904,716526,0,116509,-170102,4659 2 0011
+*W 750310,716526,0,107552,0,53776 2 0012
+ff 643123,728178,203890,222240 3 0013
+fi 589530,728178,203890,108354 3 0014
+fl 616326,728178,203890,108354 3 0015
+Fi 924490,728178,203890,108354 3 0016
+Fl 937888,728178,203890,108354 3 0017
+.i 321562,451470,0,80440 0 0020
+.j 348358,451470,203890,39176 1 0021
+ga 535936,728178 2 0022
+char180 535936,728178,0,101654 2 0023
+aa "
+ah 535936,659002,0,86982 2 0024
+ab 535936,728178,0,113306 2 0025
+char175 535936,588949,0,108354 2 0026
+a- "
+ao 871672,728178 2 0027
+char184 482342,0,178403 1 0030
+ac "
+char223 562733,728178,203890,110245 3 0031
+ss "
+char230 750310,451470,0,78789 0 0032
+ae "
+oe 750310,451470,0,78789 0 0033
+char248 535936,553416,101946,96411 3 0034
+/o "
+char198 925654,716526,0,126120 2 0035
+AE "
+OE 1032842,716526,0,126120 2 0036
+char216 803904,767499,50973,98595 3 0037
+/O "
+--- 267968,451470 0 0040
+! 321562,728178,0,130200 2 0041
+rq 539432,728178,0,72994 2 0042
+sh 857498,728178,203888,69378 3 0043
+# "
+char163 806453,728178 2 0044
+Po "
+% 857498,786432,58254,143014 3 0045
+& 803904,728178,0,101654 2 0046
+' 321562,728178,0,130200 2 0047
+( 428749,786432,262144,169811 3 0050
+) 428749,786432,262144,38739 3 0051
+* 535936,786432,0,156413 2 0052
++ 803904,588949,59418,38739 3 0053
+, 321562,110683,203890 1 0054
+char173 375155,451470,0,29637 0 0055
+hy "
+- "
+. 321562,110683 0 0056
+sl 535936,786432,262144,169811 3 0057
+/ "
+0 535936,675749,0,142141 2 0060
+1 535936,675749,0,142141 2 0061
+2 535936,675749,0,142141 2 0062
+3 535936,675749,0,142141 2 0063
+4 535936,675749,203890,142141 3 0064
+5 535936,675749,0,142141 2 0065
+6 535936,675749,0,142141 2 0066
+7 535936,675749,203890,142141 3 0067
+8 535936,675749,0,142141 2 0070
+9 535936,675749,0,142141 2 0071
+: 321562,451470,0,61022 0 0072
+; 321562,451470,203890,61022 1 0073
+char161 321562,524288,203890,79227 3 0074
+r! "
+= 803904,384696,-139592,69378 0 0075
+char191 535936,524288,203890 3 0076
+r? "
+? 535936,728178,0,128451 2 0077
+at 803904,728178,0,100634 2 0100
+@ "
+A 779437,716526 2 0101
+B 738077,716526,0,107552,0,53776 2 0102
+C 750310,716526,0,152334,-80538,76168 2 0103
+D 791670,716526,0,98595,0,71798 2 0104
+E 711280,716526,0,126120,0,63061 2 0105
+F 684483,716526,0,139518,0,5534 2 0106
+G 811186,716526,0,91459,-80538,91459 2 0107
+H 779437,716526,0,171851,0,85926 2 0110
+I 404282,716526,0,165733,0,82867 2 0111
+J 550499,716526,0,147093,0,46750 2 0112
+K 806234,716526,0,152334,0,76168 2 0113
+L 657686,716526,0,0,0,53594 2 0114
+M 940218,716526,0,171851,0,59130 2 0115
+N 779437,716526,0,171851,0,59130 2 0116
+O 803904,716526,0,98595,-80538,71798 2 0117
+P 711280,716526,0,107552,0,-26432 2 0120
+Q 803904,716526,203890,98595,-80538,98595 3 0121
+R 764874,716526,0,40560,0,30421 2 0122
+S 589530,716526,0,125538,0,62770 2 0123
+T 750310,716526,0,139518,-134349,5534 2 0124
+U 779437,716526,0,171851,-121898,59130 2 0125
+V 779437,716526,0,192530,-138936,-21845 2 0126
+W 1047405,716526,0,192530,-138936,58546 2 0127
+X 779437,716526,0,165733,0,82867 2 0130
+Y 779437,716526,0,203248,-152334,-11126 2 0131
+Z 643123,716526,0,152334,0,76168 2 0132
+lB 321562,786432,262144,196608 3 0133
+[ "
+lq 539432,728178,0,176685 2 0134
+rB 321562,786432,262144,110392 3 0135
+] "
+ha 535936,728178,0,69688 2 0136
+^ "
+a^ "
+a. 321562,700301,0,123230 2 0137
+oq 321562,728178,0,130200 2 0140
+` "
+a 535936,451470,0,80440,-46677,80440 0 0141
+b 482342,728178,0,66190,-46677,66190 2 0142
+c 482342,451470,0,59274,-46677,59274 0 0143
+d 535936,728178,0,108354,-46677,108354 2 0144
+e 482342,451470,0,78789,-46677,78789 0 0145
+Fn 321562,728178,203890,222240,104566,112867 3 0146
+f "
+g 482342,451470,203890,92770,-21045,55147 1 0147
+h 535936,728178,0,80440,0,80440 2 0150
+i 321562,687194,0,106846,-32427,106846 2 0151
+j 321562,687194,203890,151701,50973,92770 3 0152
+k 482342,728178,0,112867,0,80440 2 0153
+l 267968,728178,0,108354,-26797,107237 2 0154
+m 857498,451470,0,80440,-32427,80440 0 0155
+n 589530,451470,0,80440,-32427,80440 0 0156
+o 535936,451470,0,66190,-46677,66190 0 0157
+p 535936,451470,203890,66190,-22718,66190 1 0160
+q 482342,451470,203890,92770,-46677,55147 1 0161
+r 442147,451470,0,112867,-32427,86070 0 0162
+s 428749,451470,0,86070,0,86070 0 0163
+t 348358,644958,0,99469,-45875,99469 2 0164
+u 562733,451470,0,80440,-32427,80440 0 0165
+v 482342,451470,0,112867,-32427,75245 0 0166
+w 696717,451470,0,112867,-32427,84651 0 0167
+x 486421,451470,0,126266,0,126266 0 0170
+y 509139,451470,203890,92770,-32427,55147 1 0171
+z 428749,451470,0,128888,0,80440 0 0172
+en 535936,451470,0,96552 0 0173
+em 1071872,451470,0,96552 0 0174
+a" 535936,728178,0,128451 2 0175
+~ 535936,700301,0,121482 2 0176
+a~ "
+char168 535936,700301,0,109832 2 0177
+ad "
diff --git a/gnu/usr.bin/groff/devices/devdvi/MI b/gnu/usr.bin/groff/devices/devdvi/MI
new file mode 100644
index 000000000000..2b2e3491ba3c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/MI
@@ -0,0 +1,136 @@
+name MI
+special
+internalname cmmi10
+slant 14.036243
+checksum 195060286
+designsize 10485760
+charset
+--- 645166,716526,0,145637 2 0000
+--- 873816,716526 2 0001
+--- 799829,716526,0,29128 2 0002
+--- 728179,716526 2 0003
+--- 778424,716526,0,79371 2 0004
+--- 871630,716526,0,85195 2 0005
+--- 817746,716526,0,60438 2 0006
+--- 611669,716526,0,145637 2 0007
+--- 699051,716526 2 0010
+--- 641962,716526,0,115344 2 0011
+--- 809918,716526,0,52610 2 0012
+*a 670776,451470,0,3882 0 0013
+*b 593102,728178,203890,55342 3 0014
+*g 542880,451470,203890,58254 1 0015
+*d 466034,728178,0,39685 2 0016
+*e 425621,451470 0 0017
+*z 458754,728178,203890,77368 3 0020
+*y 520651,451470,203890,37622 1 0021
+*h 492248,728178,0,29128 2 0022
+*i 371130,451470 0 0023
+*k 604147,451470 0 0024
+*l 611672,728178 2 0025
+char181 631819,451470,203890 1 0026
+*m "
+*n 517979,451470,0,66750 0 0027
+*c 458754,728178,203890,48242 3 0030
+*p 597717,451470,0,37622 0 0031
+*r 542130,451470,203890 1 0032
+*s 599171,451470,0,37622 0 0033
+*t 458390,451470,0,118694 0 0034
+*u 566525,451470,0,37622 0 0035
+*f 624778,728178,203890 3 0036
+*x 656086,451470,203890 1 0037
+*q 683034,728178,203890,37622 3 0040
+*w 652691,451470,0,37622 0 0041
+--- 488970,451470 0 0042
++h 620170,728178 2 0043
++p 868357,451470,0,29128 0 0044
+--- 542130,451470,203890 1 0045
+ts 380474,451470,101946,83739 1 0046
++f 685944,451470,203890 1 0047
+--- 1048579,384696,-139592 0 0050
+--- 1048579,384696,-139592 0 0051
+--- 1048579,384696,-139592 0 0052
+--- 1048579,384696,-139592 0 0053
+--- 291272,486275,-38013 2 0054
+--- 291272,486275,-38013 2 0055
+--- 524290,487880,-36408 2 0056
+--- 524290,487880,-36408 2 0057
+--- 524290,451470 0 0060
+--- 524290,451470 0 0061
+--- 524290,451470 0 0062
+--- 524290,451470,203890 1 0063
+--- 524290,451470,203890 1 0064
+--- 524290,451470,203890 1 0065
+--- 524290,675749 2 0066
+--- 524290,451470,203890 1 0067
+--- 524290,675749 2 0070
+--- 524290,451470,203890 1 0071
+--- 291272,110683 0 0072
+--- 291272,110683,203890 1 0073
+< 815562,565285,40997 3 0074
+--- 524290,786432,262144 3 0075
+> 815562,565285,40997 3 0076
+--- 524290,487880,-36408 2 0077
+pd 556693,728178,0,58254 2 0100
+--- 786434,716526 2 0101
+--- 795355,716526,0,52610 2 0102
+--- 749440,716526,0,75002 2 0103
+--- 868134,716526,0,29128 2 0104
+--- 774054,716526,0,60438 2 0105
+--- 674294,716526,0,145637 2 0106
+--- 824442,716526 2 0107
+--- 871630,716526,0,85195 2 0110
+--- 460938,716526,0,82283 2 0111
+--- 581450,716526,0,100853 2 0112
+--- 890563,716526,0,75002 2 0113
+--- 713616,716526 2 0114
+--- 1017266,716526,0,114323 2 0115
+--- 842502,716526,0,114323 2 0116
+--- 799829,716526,0,29128 2 0117
+--- 673200,716526,0,145637 2 0120
+--- 828957,716526,203890 3 0121
+--- 796173,716526,0,8101 2 0122
+--- 642982,716526,0,60438 2 0123
+--- 612763,716526,0,145637 2 0124
+--- 715944,716526,0,114323 2 0125
+--- 611670,716526,0,233018 2 0126
+--- 990323,716526,0,145637 2 0127
+--- 868718,716526,0,82283 2 0130
+--- 608758,716526,0,233018 2 0131
+--- 715800,716526,0,75002 2 0132
+--- 407781,786432 2 0133
+--- 407781,728178,203890 3 0134
+--- 407781,728178,203890 3 0135
+--- 1048579,375013,-149275 0 0136
+--- 1048579,375013,-149275 0 0137
+--- 436910,728178 2 0140
+--- 554267,451470 0 0141
+--- 450014,728178 2 0142
+--- 453778,451470 0 0143
+--- 545771,728178 2 0144
+--- 488245,451470 0 0145
+--- 513368,728178,203890,112869 3 0146
+--- 500138,451470,203890,37622 1 0147
+--- 604147,728178 2 0150
+--- 361248,691562 2 0151
+--- 431811,691562,203890,60024 3 0152
+--- 545893,728178,0,33010 2 0153
+--- 312874,728178,0,20634 2 0154
+--- 920664,451470 0 0155
+--- 629392,451470 0 0156
+*o 508269,451470 0 0157
+--- 527566,451470,203890 1 0160
+--- 468099,451470,203890,37622 1 0161
+--- 473075,451470,0,29128 0 0162
+--- 491520,451470 0 0163
+--- 378654,644958 2 0164
+--- 600266,451470 0 0165
+--- 508270,451470,0,37622 0 0166
+--- 750694,451470,0,28216 0 0167
+--- 599291,451470 0 0170
+--- 514098,451470,203890,37622 1 0171
+--- 487640,451470,0,46117 0 0172
+--- 338120,451470 0 0173
+--- 402685,451470,203890 1 0174
+wp 667376,451470,203890 1 0175
+--- 524290,749149,0,161291 2 0176
+--- 291272,728178,0,418866 2 0177
diff --git a/gnu/usr.bin/groff/devices/devdvi/Makefile b/gnu/usr.bin/groff/devices/devdvi/Makefile
new file mode 100644
index 000000000000..7bc924615427
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/Makefile
@@ -0,0 +1,12 @@
+DEVICE= dvi
+FONTFILES= R I B BI CW MI S EX H HI HB SA SB DESC $(DEVGENFILES)
+DEVGENFILES= 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
+
+NOOBJ= noobj
+
+clean cleandir:
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devdvi/R b/gnu/usr.bin/groff/devices/devdvi/R
new file mode 100644
index 000000000000..3e49b938e791
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/R
@@ -0,0 +1,430 @@
+name R
+special
+internalname cmr10
+spacewidth 349526
+ligatures ff fi fl ffi ffl 0
+checksum 1274110073
+designsize 10485760
+kernpairs
+ff ' 81557
+ff ? 81557
+ff ! 81557
+ff ) 81557
+ff rB 81557
+ff ] 81557
+' ' -87382
+' ? 116509
+' ! 116509
+*A t -29128
+A t -29128
+*A C -29128
+A C -29128
+*A *O -29128
+*A O -29128
+A *O -29128
+A O -29128
+*A G -29128
+A G -29128
+*A U -29128
+A U -29128
+*A Q -29128
+A Q -29128
+*A *T -87382
+*A T -87382
+A *T -87382
+A T -87382
+*A Y -87382
+A Y -87382
+*A V -116509
+A V -116509
+*A W -116509
+A W -116509
+D *X -29128
+D X -29128
+D W -29128
+D *A -29128
+D A -29128
+D V -29128
+D Y -29128
+F o -87382
+F e -87382
+F u -87382
+F r -87382
+F a -87382
+F *A -116509
+F A -116509
+F *O -29128
+F O -29128
+F C -29128
+F G -29128
+F Q -29128
+*I *I 29128
+*I I 29128
+I *I 29128
+I I 29128
+*K *O -29128
+*K O -29128
+K *O -29128
+K O -29128
+*K C -29128
+K C -29128
+*K G -29128
+K G -29128
+*K Q -29128
+K Q -29128
+L *T -87382
+L T -87382
+L Y -87382
+L V -116509
+L W -116509
+*O *X -29128
+*O X -29128
+O *X -29128
+O X -29128
+*O W -29128
+O W -29128
+*O *A -29128
+*O A -29128
+O *A -29128
+O A -29128
+*O V -29128
+O V -29128
+*O Y -29128
+O Y -29128
+*R *A -87382
+*R A -87382
+P *A -87382
+P A -87382
+*R o -29128
+P o -29128
+*R e -29128
+P e -29128
+*R a -29128
+P a -29128
+*R . -87382
+P . -87382
+*R , -87382
+P , -87382
+R t -29128
+R C -29128
+R *O -29128
+R O -29128
+R G -29128
+R U -29128
+R Q -29128
+R *T -87382
+R T -87382
+R Y -87382
+R V -116509
+R W -116509
+*T y -29128
+T y -29128
+*T e -87382
+T e -87382
+*T o -87382
+T o -87382
+*T r -87382
+T r -87382
+*T a -87382
+T a -87382
+*T *A -87382
+*T A -87382
+T *A -87382
+T A -87382
+*T u -87382
+T u -87382
+V o -87382
+V e -87382
+V u -87382
+V r -87382
+V a -87382
+V *A -116509
+V A -116509
+V *O -29128
+V O -29128
+V C -29128
+V G -29128
+V Q -29128
+W o -87382
+W e -87382
+W u -87382
+W r -87382
+W a -87382
+W *A -116509
+W A -116509
+W *O -29128
+W O -29128
+W C -29128
+W G -29128
+W Q -29128
+*X *O -29128
+*X O -29128
+X *O -29128
+X O -29128
+*X C -29128
+X C -29128
+*X G -29128
+X G -29128
+*X Q -29128
+X Q -29128
+Y e -87382
+Y o -87382
+Y r -87382
+Y a -87382
+Y *A -87382
+Y A -87382
+Y u -87382
+oq oq -87382
+oq ` -87382
+` oq -87382
+` ` -87382
+a v -29128
+a j 58254
+a y -29128
+a w -29128
+b e 29128
+b o 29128
+b x -29128
+b d 29128
+b c 29128
+b q 29128
+b v -29128
+b j 58254
+b y -29128
+b w -29128
+c h -29128
+c k -29128
+f ' 81557
+f ? 81557
+f ! 81557
+f ) 81557
+f rB 81557
+f ] 81557
+g j 29128
+h t -29128
+h u -29128
+h b -29128
+h y -29128
+h v -29128
+h w -29128
+k a -58254
+k e -29128
+k a -29128
+k o -29128
+k c -29128
+m t -29128
+m u -29128
+m b -29128
+m y -29128
+m v -29128
+m w -29128
+n t -29128
+n u -29128
+n b -29128
+n y -29128
+n v -29128
+n w -29128
+o e 29128
+o o 29128
+o x -29128
+o d 29128
+o c 29128
+o q 29128
+o v -29128
+o j 58254
+o y -29128
+o w -29128
+p e 29128
+p o 29128
+p x -29128
+p d 29128
+p c 29128
+p q 29128
+p v -29128
+p j 58254
+p y -29128
+p w -29128
+t y -29128
+t w -29128
+u w -29128
+v a -58254
+v e -29128
+v a -29128
+v o -29128
+v c -29128
+w e -29128
+w a -29128
+w o -29128
+w c -29128
+y o -29128
+y e -29128
+y a -29128
+y . -87382
+y , -87382
+charset
+*G 655362,716526,0,0,0,-145637 2 0000
+*D 873816,716526 2 0001
+*H 815562,716526,0,0,-29128,-29128 2 0002
+*L 728179,716526 2 0003
+*C 699053,716526 2 0004
+*P 786434,716526 2 0005
+*S 757307,716526 2 0006
+*U 815562,716526,0,0,-29128,-145637 2 0007
+*F 757307,716526,0,0,-29128 2 0010
+*Q 815562,716526,0,0,-29128,-72818 2 0011
+*W 757307,716526 2 0012
+ff 611672,728178,0,81557 2 0013
+fi 582544,728178 2 0014
+fl 582544,728178 2 0015
+Fi 873816,728178 2 0016
+Fl 873816,728178 2 0017
+.i 291272,451470 0 0020
+.j 320400,451470,203890 1 0021
+ga 524290,728178 2 0022
+char180 524290,728178 2 0023
+aa "
+ah 524290,659002 2 0024
+ab 524290,728178 2 0025
+char175 524290,595357 2 0026
+a- "
+ao 786434,728178 2 0027
+char184 466035,0,178403 1 0030
+ac "
+char223 524291,728178 2 0031
+ss "
+char230 757307,451470 0 0032
+ae "
+oe 815562,451470 0 0033
+char248 524290,553416,101946 3 0034
+/o "
+char198 946634,716526 2 0035
+AE "
+OE 1063142,716526 2 0036
+char216 815562,767499,50973 3 0037
+/O "
+--- 291272,451470 0 0040
+! 291272,728178 2 0041
+rq 524290,728178 2 0042
+sh 873816,728178,203888 3 0043
+# "
+Do 524290,786432,58254 3 0044
+$ "
+% 873816,786432,58254 3 0045
+& 815562,728178 2 0046
+' 291272,728178 2 0047
+( 407781,786432,262144 3 0050
+) 407781,786432,262144 3 0051
+* 524290,786432 2 0052
+pl 815562,611670,87382 3 0053
++ "
+, 291272,110683,203890 1 0054
+char173 349526,451470 0 0055
+hy "
+- "
+. 291272,110683 0 0056
+sl 524290,786432,262144 3 0057
+/ "
+0 524290,675749 2 0060
+1 524290,675749 2 0061
+2 524290,675749 2 0062
+3 524290,675749 2 0063
+4 524290,675749 2 0064
+5 524290,675749 2 0065
+6 524290,675749 2 0066
+7 524290,675749 2 0067
+8 524290,675749 2 0070
+9 524290,675749 2 0071
+: 291272,451470 0 0072
+; 291272,451470,203890 1 0073
+char161 291272,524288,203890 3 0074
+r! "
+eq 815562,384696,-139592 0 0075
+= "
+char191 495163,524288,203890 3 0076
+r? "
+? 495163,728178 2 0077
+at 815562,728178 2 0100
+@ "
+*A 786434,716526 2 0101
+A "
+*B 742744,716526 2 0102
+B "
+C 757307,716526,0,0,-29128 2 0103
+D 800998,716526,0,0,0,-29128 2 0104
+*E 713616,716526 2 0105
+E "
+F 684490,716526,0,0,0,-145637 2 0106
+G 822843,716526,0,0,-29128 2 0107
+*Y 786434,716526 2 0110
+H "
+*I 378653,716526 2 0111
+I "
+J 538853,716526,0,0,0,-29128 2 0112
+*K 815562,716526 2 0113
+K "
+L 655362,716526,0,0,0,58254 2 0114
+*M 961197,716526 2 0115
+M "
+*N 786434,716526 2 0116
+N "
+*O 815562,716526,0,0,-29128,-29128 2 0117
+O "
+*R 713616,716526,0,0,0,-145637 2 0120
+P "
+Q 815562,716526,203890,0,-29128 3 0121
+R 771870,716526 2 0122
+S 582544,716526 2 0123
+*T 757307,716526,0,0,0,-145637 2 0124
+T "
+U 786434,716526,0,0,-14563 2 0125
+V 786434,716526,0,14563,43691,-218454 2 0126
+W 1077706,716526,0,14563,43691,-131074 2 0127
+*X 786434,716526 2 0130
+X "
+Y 786434,716526,0,26214,29128,-206803 2 0131
+*Z 640798,716526 2 0132
+Z "
+lB 291272,786432,262144 3 0133
+[ "
+lq 524290,728178 2 0134
+rB 291272,786432,262144 3 0135
+] "
+ha 524290,728178 2 0136
+^ "
+a^ "
+a. 291272,700301 2 0137
+oq 291272,728178 2 0140
+` "
+a 524290,451470 0 0141
+b 582544,728178 2 0142
+c 466035,451470 0 0143
+d 582544,728178 2 0144
+e 466035,451470 0 0145
+f 320400,728178,0,81557 2 0146
+g 524290,451470,203890,14563 1 0147
+h 582544,728178 2 0150
+i 291272,700301 2 0151
+j 320400,700301,203890 3 0152
+k 553418,728178 2 0153
+l 291272,728178 2 0154
+m 873816,451470 0 0155
+n 582544,451470 0 0156
+o 524290,451470 0 0157
+p 582544,451470,203890 1 0160
+q 553416,451470,203890 1 0161
+r 410694,451470 0 0162
+s 413606,451470 0 0163
+t 407781,644958 2 0164
+u 582544,451470 0 0165
+v 553418,451470,0,14563 0 0166
+w 757307,451470,0,14563 0 0167
+x 553418,451470 0 0170
+y 553418,451470,203890,14563 1 0171
+z 466035,451470 0 0172
+en 524290,451470,0,29128 0 0173
+em 1048579,451470,0,29128 0 0174
+a" 524290,728178 2 0175
+~ 524290,700301 2 0176
+a~ "
+char168 524290,700301 2 0177
+ad "
diff --git a/gnu/usr.bin/groff/devices/devdvi/S b/gnu/usr.bin/groff/devices/devdvi/S
new file mode 100644
index 000000000000..11b79ff9c6db
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/S
@@ -0,0 +1,152 @@
+name S
+special
+internalname cmsy10
+slant 14.036243
+checksum 555887770
+designsize 10485760
+charset
+mi 815562,611670,87382 3 0000
+\- "
+md 291272,466035,-58253 2 0001
+char215 815562,611670,87382 3 0002
+mu "
+** 524290,487880,-36408 2 0003
+char247 815562,611670,87382 3 0004
+di "
+--- 524290,466035,-58253 2 0005
+char177 815562,611670,87382 3 0006
++- "
+-+ 815562,611670,87382 3 0007
+c+ 815562,611670,87382 3 0010
+--- 815562,611670,87382 3 0011
+c* 815562,611670,87382 3 0012
+--- 815562,611670,87382 3 0013
+--- 815562,611670,87382 3 0014
+ci 1048579,728178,203890 3 0015
+--- 524290,466035,-58253 2 0016
+bu 524290,466035,-58253 2 0017
+--- 815562,486275,-38013 2 0020
+== 815562,486275,-38013 2 0021
+ib 815562,666864,142576 3 0022
+ip 815562,666864,142576 3 0023
+<= 815562,666864,142576 3 0024
+>= 815562,666864,142576 3 0025
+--- 815562,666864,142576 3 0026
+--- 815562,666864,142576 3 0027
+ti 815562,384696,-139592 0 0030
+ap "
+~~ 815562,506590,-17698 2 0031
+sb 815562,565285,40997 3 0032
+sp 815562,565285,40997 3 0033
+<< 1048579,565285,40997 3 0034
+>> 1048579,565285,40997 3 0035
+--- 815562,565285,40997 3 0036
+--- 815562,565285,40997 3 0037
+<- 1048579,384696,-139592 0 0040
+-> 1048579,384696,-139592 0 0041
+ua 524290,728178,203888 3 0042
+da 524290,728178,203888 3 0043
+<> 1048579,384696,-139592 0 0044
+--- 1048579,728178,203888 3 0045
+--- 1048579,728178,203888 3 0046
+~= 815562,486275,-38013 2 0047
+lh 1048579,384696,-139592 0 0050
+lA "
+rh 1048579,384696,-139592 0 0051
+rA "
+uA 640798,728178,203888 3 0052
+dA 640798,728178,203888 3 0053
+hA 1048579,384696,-139592 0 0054
+--- 1048579,728178,203888 3 0055
+--- 1048579,728178,203888 3 0056
+pt 815562,451470 0 0057
+prime 288358,582544 2 0060
+if 1048579,451470 0 0061
+mo 699053,565285,40997 3 0062
+st 699053,565285,40997 3 0063
+--- 932070,728178,203890 3 0064
+--- 932070,728178,203890 3 0065
+slashnot 0,728178,203888 3 0066
+--- 0,384696,-139592 0 0067
+fa 582544,728178 2 0070
+te 582544,728178 2 0071
+char172 699053,451470 0 0072
+no "
+es 524290,786432,58254 3 0073
+Re 757307,728178 2 0074
+Im 757307,728178 2 0075
+--- 815562,728178 2 0076
+pp 815562,728178 2 0077
+Ah 640798,728178 2 0100
+A 837258,716526 2 0101
+B 688715,716526,0,31890 2 0102
+C 552106,716526,0,61170 2 0103
+D 808864,716526,0,29128 2 0104
+E 553419,716526,0,93786 2 0105
+F 753662,716526,0,104130 2 0106
+G 623762,716526,101946,62184 3 0107
+H 885541,716526,0,10123 2 0110
+I 570966,716526,0,77408 2 0111
+J 710704,716526,101946,193694 3 0112
+K 798963,716526,0,15147 2 0113
+L 723229,716526 2 0114
+M 1259235,716526 2 0115
+N 860347,716526,0,154518 2 0116
+O 834786,716526,0,29128 2 0117
+P 729347,716526,0,86216 2 0120
+Q 856341,716526,101946 3 0121
+R 888672,716526 2 0122
+S 634974,716526,0,78638 2 0123
+T 571101,716526,0,266514 2 0124
+U 656232,716526,0,104130 2 0125
+V 642549,716526,0,86216 2 0126
+W 1035766,716526,0,86216 2 0127
+X 747946,716526,0,153541 2 0130
+Y 700802,716526,101946,86216 3 0131
+Z 759930,716526,0,83302 2 0132
+cu 699053,582544 2 0133
+ca 699053,582544 2 0134
+--- 699053,582544 2 0135
+AN 699053,582544 2 0136
+OR 699053,582544 2 0137
+--- 640798,728178 2 0140
+--- 640798,728178 2 0141
+lf 466035,786432,262144 3 0142
+rf 466035,786432,262144 3 0143
+lc 466035,786432,262144 3 0144
+rc 466035,786432,262144 3 0145
+{ 524290,786432,262144 3 0146
+lC "
+} 524290,786432,262144 3 0147
+rC "
+la 407781,786432,262144 3 0150
+ra 407781,786432,262144 3 0151
+bar 291272,786432,262144 3 0152
+or "
+bv "
+| "
+ba "
+bardbl 524290,786432,262144 3 0153
+va 524290,786432,262144 3 0154
+vA 640798,786432,262144 3 0155
+rs 524290,786432,262144 3 0156
+\ "
+--- 291272,728178,203888 3 0157
+sr 873816,41942,1006634 1 0160
+--- 786434,716526 2 0161
+gr 873816,716526 2 0162
+--- 436909,728178,203890,116509 3 0163
+--- 699053,582544 2 0164
+--- 699053,582544 2 0165
+--- 815562,666864,142576 3 0166
+--- 815562,666864,142576 3 0167
+char167 466037,728178,203890 3 0170
+sc "
+dg 466035,728178,203890 3 0171
+dd 466035,728178,203890 3 0172
+char182 640798,728178,203890 3 0173
+ps "
+CL 815562,728178,135926 3 0174
+DI 815562,728178,135926 3 0175
+HE 815562,728178,135926 3 0176
+SP 815562,728178,135926 3 0177
diff --git a/gnu/usr.bin/groff/devices/devdvi/SA b/gnu/usr.bin/groff/devices/devdvi/SA
new file mode 100644
index 000000000000..f2b258f16fd4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/SA
@@ -0,0 +1,143 @@
+name SA
+special
+internalname msam10
+checksum -1749815603
+designsize 10485760
+charset
+boxdot 815562,709446 2 0000
+boxplus 815562,709446 2 0001
+boxtimes 815562,709446 2 0002
+square 815562,709446 2 0003
+blacksquare 815562,709446 2 0004
+centerdot 291272,576570 2 0005
+lz 699053,728178,116509 3 0006
+lozenge "
+blacklozenge 699053,728178,116509 3 0007
+circlearrowright 815562,610248,85960 3 0010
+circlearrowleft 815562,610248,85960 3 0011
+rightleftharpoons 1048579,547770,14197 3 0012
+leftrightharpoons 1048579,547770,14197 3 0013
+boxminus 815562,709446 2 0014
+Vdash 757307,728178 2 0015
+Vvdash 932070,728178 2 0016
+vDash 640798,728178 2 0017
+twoheadrightarrow 1048579,547770,14197 3 0020
+twoheadleftarrow 1048579,547770,14197 3 0021
+leftleftarrows 1048579,709446,189584 3 0022
+rightrightarrows 1048579,709446,189584 3 0023
+upuparrows 873816,728178,203888 3 0024
+downdownarrows 873816,728178,203888 3 0025
+upharpoonright 436909,728178,203888 3 0026
+downharpoonright 436909,728178,203888 3 0027
+upharpoonleft 436909,728178,203888 3 0030
+downharpoonleft 436909,728178,203888 3 0031
+rightarrowtail 1165088,547770,14197 3 0032
+leftarrowtail 1165088,547770,14197 3 0033
+leftrightarrows 1048579,709446,189584 3 0034
+rightleftarrows 1048579,709446,189584 3 0035
+Lsh 524290,728178 2 0036
+Rsh 524290,728178 2 0037
+rightsquigarrow 1048579,396238,-139592 0 0040
+leftrightsquigarrow 1456360,396238,-139592 0 0041
+looparrowleft 1048579,576570 2 0042
+looparrowright 1048579,576570 2 0043
+circeq 815562,765021,240733 3 0044
+succsim 815562,765021,240733 3 0045
+gtrsim 815562,765021,240733 3 0046
+gtrapprox 815562,792549,268261 3 0047
+multimap 1165088,576570 2 0050
+3d 699053,728178 2 0051
+tf "
+therefore "
+because 699053,728178 2 0052
+doteqdot 815562,610248,85960 3 0053
+triangleq 815562,961197,85960 3 0054
+precsim 815562,765021,240733 3 0055
+lesssim 815562,765021,240733 3 0056
+lessapprox 815562,792549,268261 3 0057
+eqslantless 815562,667592,143304 3 0060
+eqslantgtr 815562,667592,143304 3 0061
+curlyeqprec 815562,667592,143304 3 0062
+curlyeqsucc 815562,667592,143304 3 0063
+preccurlyeq 815562,667592,143304 3 0064
+leqq 815562,792549,268261 3 0065
+leqslant 815562,667592,143304 3 0066
+lessgtr 815562,709446,189584 3 0067
+backprime 288358,576570 2 0070
+--- 524290,486557,-37731 2 0071
+risingdotseq 815562,610248,85960 3 0072
+fallingdotseq 815562,610248,85960 3 0073
+succcurlyeq 815562,667592,143304 3 0074
+geqq 815562,792549,268261 3 0075
+geqslant 815562,667592,143304 3 0076
+gtrless 815562,709446,189584 3 0077
+sqsubset 815562,576570,36882 3 0100
+sqsupset 815562,576570,36882 3 0101
+vartriangleright 815562,576570,36882 3 0102
+vartriangleleft 815562,576570,36882 3 0103
+trianglerighteq 815562,667592,143304 3 0104
+trianglelefteq 815562,667592,143304 3 0105
+bigstar 990323,728178,203888 3 0106
+between 524290,792549,268261 3 0107
+blacktriangledown 757307,576570 2 0110
+blacktriangleright 815562,576570,36882 3 0111
+blacktriangleleft 815562,576570,36882 3 0112
+--- 524290,486557,-37731 2 0113
+--- 524290,486557,-37731 2 0114
+vartriangle 757307,576570 2 0115
+blacktriangle 757307,576570 2 0116
+triangledown 757307,576570 2 0117
+eqcirc 815562,728178 2 0120
+lesseqgtr 815562,928714,404426 3 0121
+gtreqless 815562,928714,404426 3 0122
+lesseqqgtr 815562,1030294,506006 3 0123
+gtreqqless 815562,1030294,506006 3 0124
+char165 786434,709446,0,26214 2 0125
+Ye "
+yen "
+Rrightarrow 1048579,667592,143304 3 0126
+Lleftarrow 1048579,667592,143304 3 0127
+OK 873816,728178 2 0130
+checkmark "
+veebar 640798,728178,203888 3 0131
+barwedge 640798,728178,203888 3 0132
+doublebarwedge 640798,792549,203888 3 0133
+/_ 757307,728178 2 0134
+angle "
+measuredangle 757307,728178 2 0135
+sphericalangle 757307,547770,36882 3 0136
+varpropto 815562,728178 2 0137
+smallsmile 815562,728178,203888 3 0140
+smallfrown 815562,728178,203888 3 0141
+Subset 815562,576570,36882 3 0142
+Supset 815562,576570,36882 3 0143
+Cup 699053,576570 2 0144
+Cap 699053,576570 2 0145
+curlywedge 797355,576570 2 0146
+curlyvee 797355,576570 2 0147
+leftthreetimes 815562,728178 2 0150
+rightthreetimes 815562,728178 2 0151
+subseteqq 815562,792549,268261 3 0152
+supseteqq 815562,792549,268261 3 0153
+bumpeq 815562,576570,63568 3 0154
+Bumpeq 815562,576570,63568 3 0155
+lll 1398106,576570,36882 3 0156
+ggg 1398106,576570,36882 3 0157
+ulcorner 524290,728178 2 0160
+urcorner 524290,728178 2 0161
+rg 992648,709446,159430 3 0162
+char174 "
+circledR "
+circledS 946045,709446,159430 3 0163
+pitchfork 699053,728178 2 0164
+dotplus 815562,728178,85960 3 0165
+backsim 815562,396238,-139592 0 0166
+backsimeq 815562,486557,-37731 2 0167
+llcorner 524290,396238 0 0170
+lrcorner 524290,396238 0 0171
+maltese 873816,728178 2 0172
+complement 524290,865080 2 0173
+intercal 582544,451470,203888 1 0174
+circledcirc 815562,610248,85960 3 0175
+circledast 815562,610248,85960 3 0176
+circleddash 815562,610248,85960 3 0177
diff --git a/gnu/usr.bin/groff/devices/devdvi/SB b/gnu/usr.bin/groff/devices/devdvi/SB
new file mode 100644
index 000000000000..a4be59db29c6
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/SB
@@ -0,0 +1,132 @@
+name SB
+special
+internalname msbm10
+spacewidth 314576
+slant 87.709390
+checksum -2001332536
+designsize 10485760
+charset
+lvertneqq 815562,794042,263635 3 0000
+gvertneqq 815562,794042,263635 3 0001
+nleq 815562,832390,317448 3 0002
+ngeq 815562,832390,317448 3 0003
+nless 815562,740048,215760 3 0004
+ngtr 815562,740048,215760 3 0005
+nprec 815562,740048,215760 3 0006
+nsucc 815562,740048,215760 3 0007
+lneqq 815562,794042,263635 3 0010
+gneqq 815562,794042,263635 3 0011
+nleqslant 815562,832390,317448 3 0012
+ngeqslant 815562,832390,317448 3 0013
+lneq 815562,666864,142576 3 0014
+gneq 815562,666864,142576 3 0015
+npreceq 815562,832390,317448 3 0016
+nsucceq 815562,832390,317448 3 0017
+precnsim 815562,777110,243501 3 0020
+succnsim 815562,777110,243501 3 0021
+lnsim 815562,777110,243501 3 0022
+gnsim 815562,777110,243501 3 0023
+nleqq 815562,964179,439891 3 0024
+ngeqq 815562,964179,439891 3 0025
+precneqq 815562,794042,263635 3 0026
+succneqq 815562,794042,263635 3 0027
+precnapprox 815562,794042,274379 3 0030
+succnapprox 815562,794042,274379 3 0031
+lnapprox 815562,794042,274379 3 0032
+gnapprox 815562,794042,274379 3 0033
+nsim 815562,384696,-139592 0 0034
+ncong 815562,832390,317448 3 0035
+diagup 932070,722352,203888 3 0036
+diagdown 932070,777110,203888 3 0037
+varsubsetneq 815562,666864,142576 3 0040
+varsupsetneq 815562,666864,142576 3 0041
+nsubseteqq 815562,794042,263635 3 0042
+nsupseteqq 815562,794042,263635 3 0043
+subsetneqq 815562,832390,298650 3 0044
+supsetneqq 815562,832390,298650 3 0045
+varsubsetneqq 815562,794042,263635 3 0046
+varsupsetneqq 815562,794042,263635 3 0047
+subsetneq 815562,666864,142576 3 0050
+supsetneq 815562,666864,142576 3 0051
+nsubseteq 815562,832390,317448 3 0052
+nsupseteq 815562,832390,317448 3 0053
+nparallel 524290,777110,263635 3 0054
+nmid 291272,777110,263635 3 0055
+nshortmid 233018,609920,85632 3 0056
+nshortparallel 407781,609920,85632 3 0057
+nvdash 640798,722352 2 0060
+nVdash 757307,722352 2 0061
+nvDash 640798,722352 2 0062
+nVDash 757307,722352 2 0063
+ntrianglerighteq 815562,832390,317448 3 0064
+ntrianglelefteq 815562,832390,317448 3 0065
+ntriangleleft 815562,740048,215760 3 0066
+ntriangleright 815562,740048,215760 3 0067
+nleftarrow 1048579,384696,-139592 0 0070
+nrightarrow 1048579,384696,-139592 0 0071
+nLeftarrow 1048579,384696,-139592 0 0072
+nRightarrow 1048579,384696,-139592 0 0073
+nLeftrightarrow 1048579,384696,-139592 0 0074
+nleftrightarrow 1048579,384696,-139592 0 0075
+divideontimes 815562,609920,85632 3 0076
+varnothing 815562,609920,85632 3 0077
+nexists 582544,722352 2 0100
+BbbA 757307,722352 2 0101
+BbbB 699053,722352 2 0102
+BbbC 757307,722352 2 0103
+BbbD 757307,722352 2 0104
+BbbE 699053,722352 2 0105
+BbbF 640798,722352 2 0106
+BbbG 815562,722352 2 0107
+BbbH 815562,722352 2 0110
+BbbI 407781,722352 2 0111
+BbbJ 524290,722352,174763 3 0112
+BbbK 815562,722352 2 0113
+BbbL 699053,722352 2 0114
+BbbM 990325,722352 2 0115
+BbbN 757307,722352 2 0116
+BbbO 815562,722352,174763 3 0117
+BbbP 640798,722352 2 0120
+BbbQ 815562,722352,174763 3 0121
+BbbR 757307,722352 2 0122
+BbbS 582544,722352 2 0123
+BbbT 699053,722352 2 0124
+BbbU 757307,722352 2 0125
+BbbV 757307,722352 2 0126
+BbbW 1048579,722352 2 0127
+BbbX 757307,722352 2 0130
+BbbY 757307,722352 2 0131
+BbbZ 699053,722352 2 0132
+--- 1980650,865080 2 0133
+--- 2446685,865080 2 0134
+--- 1980650,865080 2 0135
+--- 2446685,943717 2 0136
+Finv 582544,722352 2 0140
+Game 669925,722352 2 0141
+mho 757307,722352 2 0146
+eth 582544,722352 2 0147
+eqsim 815562,486275,-38013 2 0150
+beth 699053,722352 2 0151
+gimel 466035,722352 2 0152
+daleth 699053,722352 2 0153
+lessdot 815562,565285,40997 3 0154
+gtrdot 815562,565285,40997 3 0155
+ltimes 815562,609920,85632 3 0156
+rtimes 815562,609920,85632 3 0157
+shortmid 233018,609920,85632 3 0160
+shortparallel 407781,609920,85632 3 0161
+smallsetminus 815562,609920,85632 3 0162
+thicksim 815562,384696,-139592 0 0163
+thickapprox 815562,506590,-17698 2 0164
+approxeq 815562,609920,85632 3 0165
+succapprox 815562,794042,274379 3 0166
+precapprox 815562,794042,274379 3 0167
+curvearrowleft 1048579,451470 0 0170
+curvearrowright 1048579,451470 0 0171
+digamma 815562,609920,85632 3 0172
+varkappa 699053,451470,0,42235 0 0173
+Bbbk 582544,722352 2 0174
+hslash 566525,722352 2 0175
+-h 566525,722352 2 0176
+hbar "
+backepsilon 450016,451470 0 0177
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/CompileFonts b/gnu/usr.bin/groff/devices/devdvi/generate/CompileFonts
new file mode 100644
index 000000000000..8859f8ea8630
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/CompileFonts
@@ -0,0 +1,15 @@
+#! /bin/sh
+# Compile fonts in the sizes needed by groff.
+sizes="5 6 7 8 9 10 11 12 14 16 18 20 22 24 28 36"
+fonts="cmr10 cmti10 cmbx10 cmbxti10 cmtt10 cmex10 cmmi10 cmsy10 cmss10 cmssbx10 cmssi10"
+mode=cx
+dpi=300
+
+for f in $fonts; do
+ for s in $sizes; do
+ virmf "&cm \\mode=$mode; mag=$s/10; batchmode; input $f" >/dev/null
+ mag=`expr $s \* $dpi / 10`
+ gftopk $f.${mag}gf >/dev/null
+ rm $f.${mag}gf
+ done
+done
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/Makefile b/gnu/usr.bin/groff/devices/devdvi/generate/Makefile
new file mode 100644
index 000000000000..f133ab6202ed
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/Makefile
@@ -0,0 +1,93 @@
+#Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff is free software; you can redistribute 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.
+#
+#groff is distributed in the hope that it will be useful, but WITHOUT ANY
+#WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+#for more details.
+#
+#You should have received a copy of the GNU General Public License along
+#with groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# This is set up so you can do:
+# make -f generate/Makefile
+# in the parent directory of the directory containing this file.
+
+srcdir=.
+tfmdir=/usr/local/lib/groff-tfm
+gfdir=/usr/local/lib/groff-gf
+
+TFMTODIT=tfmtodit
+FONTS=R I B BI CW MI S EX H HI HB SA SB
+SPECIALFLAG=-s
+
+all: $(FONTS)
+
+# R is special because it contains \(pl \(eq
+
+R: $(srcdir)/texr.map
+ $(TFMTODIT) $(SPECIALFLAG) -g $(gfdir)/cmr10.300gf \
+ $(tfmdir)/cmr10.tfm $(srcdir)/texr.map $@
+
+# I is special because it contains \(Po
+
+I: $(srcdir)/texi.map
+ $(TFMTODIT) $(SPECIALFLAG) -g $(gfdir)/cmti10.300gf \
+ $(tfmdir)/cmti10.tfm $(srcdir)/texi.map $@
+
+B: $(srcdir)/texb.map
+ $(TFMTODIT) -g $(gfdir)/cmbx10.300gf \
+ $(tfmdir)/cmbx10.tfm $(srcdir)/texb.map $@
+
+BI: $(srcdir)/texi.map
+ $(TFMTODIT) -g $(gfdir)/cmbxti10.300gf \
+ $(tfmdir)/cmbxti10.tfm $(srcdir)/texi.map $@
+
+# CW is special because it contains "
+
+CW: $(srcdir)/textt.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/cmtt10.tfm $(srcdir)/textt.map $@
+
+MI: $(srcdir)/texmi.map
+ $(TFMTODIT) $(SPECIALFLAG) -k 0177 $(tfmdir)/cmmi10.tfm $(srcdir)/texmi.map $@
+
+S: $(srcdir)/texsy.map
+ $(TFMTODIT) $(SPECIALFLAG) -k 060 $(tfmdir)/cmsy10.tfm $(srcdir)/texsy.map $@
+
+EX: $(srcdir)/texex.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/cmex10.tfm $(srcdir)/texex.map $@
+
+H: $(srcdir)/texr.map
+ $(TFMTODIT) -g $(gfdir)/cmss10.300gf $(tfmdir)/cmss10.tfm $(srcdir)/texb.map $@
+
+HB: $(srcdir)/texr.map
+ $(TFMTODIT) -g $(gfdir)/cmssbx10.300gf \
+ $(tfmdir)/cmssbx10.tfm $(srcdir)/texb.map $@
+
+HI: $(srcdir)/texr.map
+ $(TFMTODIT) -g $(gfdir)/cmssi10.300gf \
+ $(tfmdir)/cmssi10.tfm $(srcdir)/texb.map $@
+
+SA: $(srcdir)/msam.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/msam10.tfm $(srcdir)/msam.map $@
+
+SB: $(srcdir)/msbm.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/msbm10.tfm $(srcdir)/msbm.map $@
+
+clean:
+
+realclean:
+ -rm -f $(FONTS)
+
+extraclean: realclean
+ -rm -f core *~ \#*
+
+.PHONY: clean realclean extraclean all
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/msam.map b/gnu/usr.bin/groff/devices/devdvi/generate/msam.map
new file mode 100644
index 000000000000..90006c957688
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/msam.map
@@ -0,0 +1,127 @@
+# Map for the AMSFonts 2.0 msam font using TeX names.
+# Contributed by Zdzislaw Meglicki (Zdzislaw.Meglicki@arp.anu.edu.au).
+0 boxdot
+1 boxplus
+2 boxtimes
+3 square
+4 blacksquare
+5 centerdot
+6 lozenge lz
+7 blacklozenge
+8 circlearrowright
+9 circlearrowleft
+10 rightleftharpoons
+11 leftrightharpoons
+12 boxminus
+13 Vdash
+14 Vvdash
+15 vDash
+16 twoheadrightarrow
+17 twoheadleftarrow
+18 leftleftarrows
+19 rightrightarrows
+20 upuparrows
+21 downdownarrows
+22 upharpoonright
+23 downharpoonright
+24 upharpoonleft
+25 downharpoonleft
+26 rightarrowtail
+27 leftarrowtail
+28 leftrightarrows
+29 rightleftarrows
+30 Lsh
+31 Rsh
+32 rightsquigarrow
+33 leftrightsquigarrow
+34 looparrowleft
+35 looparrowright
+36 circeq
+37 succsim
+38 gtrsim
+39 gtrapprox
+40 multimap
+41 therefore tf 3d
+42 because
+43 doteqdot
+44 triangleq
+45 precsim
+46 lesssim
+47 lessapprox
+48 eqslantless
+49 eqslantgtr
+50 curlyeqprec
+51 curlyeqsucc
+52 preccurlyeq
+53 leqq
+54 leqslant
+55 lessgtr
+56 backprime
+58 risingdotseq
+59 fallingdotseq
+60 succcurlyeq
+61 geqq
+62 geqslant
+63 gtrless
+64 sqsubset
+65 sqsupset
+66 vartriangleright
+67 vartriangleleft
+68 trianglerighteq
+69 trianglelefteq
+70 bigstar
+71 between
+72 blacktriangledown
+73 blacktriangleright
+74 blacktriangleleft
+77 vartriangle
+78 blacktriangle
+79 triangledown
+80 eqcirc
+81 lesseqgtr
+82 gtreqless
+83 lesseqqgtr
+84 gtreqqless
+85 yen Ye char165
+86 Rrightarrow
+87 Lleftarrow
+88 checkmark OK
+89 veebar
+90 barwedge
+91 doublebarwedge
+92 angle /_
+93 measuredangle
+94 sphericalangle
+95 varpropto
+96 smallsmile
+97 smallfrown
+98 Subset
+99 Supset
+100 Cup
+101 Cap
+102 curlywedge
+103 curlyvee
+104 leftthreetimes
+105 rightthreetimes
+106 subseteqq
+107 supseteqq
+108 bumpeq
+109 Bumpeq
+110 lll
+111 ggg
+112 ulcorner
+113 urcorner
+114 circledR char174 rg
+115 circledS
+116 pitchfork
+117 dotplus
+118 backsim
+119 backsimeq
+120 llcorner
+121 lrcorner
+122 maltese
+123 complement
+124 intercal
+125 circledcirc
+126 circledast
+127 circleddash
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/msbm.map b/gnu/usr.bin/groff/devices/devdvi/generate/msbm.map
new file mode 100644
index 000000000000..07ee095d41e4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/msbm.map
@@ -0,0 +1,121 @@
+# Map for the AMSFonts 2.0 msbm font using TeX names.
+# Contributed by Zdzislaw Meglicki (Zdzislaw.Meglicki@arp.anu.edu.au).
+0 lvertneqq
+1 gvertneqq
+2 nleq
+3 ngeq
+4 nless
+5 ngtr
+6 nprec
+7 nsucc
+8 lneqq
+9 gneqq
+10 nleqslant
+11 ngeqslant
+12 lneq
+13 gneq
+14 npreceq
+15 nsucceq
+16 precnsim
+17 succnsim
+18 lnsim
+19 gnsim
+20 nleqq
+21 ngeqq
+22 precneqq
+23 succneqq
+24 precnapprox
+25 succnapprox
+26 lnapprox
+27 gnapprox
+28 nsim
+29 ncong
+30 diagup
+31 diagdown
+32 varsubsetneq
+33 varsupsetneq
+34 nsubseteqq
+35 nsupseteqq
+36 subsetneqq
+37 supsetneqq
+38 varsubsetneqq
+39 varsupsetneqq
+40 subsetneq
+41 supsetneq
+42 nsubseteq
+43 nsupseteq
+44 nparallel
+45 nmid
+46 nshortmid
+47 nshortparallel
+48 nvdash
+49 nVdash
+50 nvDash
+51 nVDash
+52 ntrianglerighteq
+53 ntrianglelefteq
+54 ntriangleleft
+55 ntriangleright
+56 nleftarrow
+57 nrightarrow
+58 nLeftarrow
+59 nRightarrow
+60 nLeftrightarrow
+61 nleftrightarrow
+62 divideontimes
+63 varnothing
+64 nexists
+65 BbbA
+66 BbbB
+67 BbbC
+68 BbbD
+69 BbbE
+70 BbbF
+71 BbbG
+72 BbbH
+73 BbbI
+74 BbbJ
+75 BbbK
+76 BbbL
+77 BbbM
+78 BbbN
+79 BbbO
+80 BbbP
+81 BbbQ
+82 BbbR
+83 BbbS
+84 BbbT
+85 BbbU
+86 BbbV
+87 BbbW
+88 BbbX
+89 BbbY
+90 BbbZ
+96 Finv
+97 Game
+102 mho
+103 eth
+104 eqsim
+105 beth
+106 gimel
+107 daleth
+108 lessdot
+109 gtrdot
+110 ltimes
+111 rtimes
+112 shortmid
+113 shortparallel
+114 smallsetminus
+115 thicksim
+116 thickapprox
+117 approxeq
+118 succapprox
+119 precapprox
+120 curvearrowleft
+121 curvearrowright
+122 digamma
+123 varkappa
+124 Bbbk
+125 hslash
+126 hbar -h
+127 backepsilon
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/texb.map b/gnu/usr.bin/groff/devices/devdvi/generate/texb.map
new file mode 100644
index 000000000000..67008339e9f7
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/texb.map
@@ -0,0 +1,127 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 rq
+35 # sh
+36 $ Do
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 +
+44 ,
+45 - hy char173
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 r! char161
+61 =
+62 r? char191
+63 ?
+64 @ at
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 [ lB
+92 lq
+93 ] rB
+94 a^ ^ ha
+95 a.
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 en
+124 em
+125 a"
+126 a~ ~
+127 ad char168
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/texex.map b/gnu/usr.bin/groff/devices/devdvi/generate/texex.map
new file mode 100644
index 000000000000..a5b26901da29
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/texex.map
@@ -0,0 +1,100 @@
+0 parenleft0
+1 parenright0
+2 bracketleft0
+3 bracketright0
+4 floorleft0
+5 floorright0
+6 ceilingleft0
+7 ceilingright0
+8 braceleft0
+9 braceright0
+10 angleleft0
+11 angleright0
+12 barex
+13 bardblex
+14 slash0
+15 backslash0
+16 parenleft1
+17 parenright1
+18 parenleft2
+19 parenright2
+20 bracketleft2
+21 bracketright2
+22 floorleft2
+23 floorright2
+24 ceilingleft2
+25 ceilingright2
+26 braceleft2
+27 braceright2
+28 angleleft2
+29 angleright2
+30 slash2
+31 backslash2
+32 parenleft3
+33 parenright3
+34 bracketleft3
+35 bracketright3
+36 floorleft3
+37 floorright3
+38 ceilingleft3
+39 ceilingright3
+40 braceleft3
+41 braceright3
+42 angleleft3
+43 angleright3
+44 slash3
+45 backslash3
+46 slash1
+47 backslash1
+48 parenlefttp
+49 parenrighttp
+50 bracketlefttp
+51 bracketrighttp
+52 bracketleftbt
+53 bracketrightbt
+54 bracketleftex
+55 bracketrightex
+56 bracelefttp lt
+57 bracerighttp rt
+58 braceleftbt lb
+59 bracerightbt rb
+60 braceleftmid lk
+61 bracerightmid rk
+62 braceex bracerightex braceleftex
+63 arrowvertex
+64 parenleftbt
+65 parenrightbt
+66 parenleftex
+67 parenrightex
+68 angleleft1
+69 angleright1
+73 ois ointegral
+75 bigcircledot
+77 bigcircleplus
+79 bigcirclemultiply
+88 sum
+89 product
+90 is integral
+91 bigunion
+92 bigintersection
+93 bigunionplus
+94 biglogicaland
+95 biglogicalor
+97 coproduct
+104 bracketleft1
+105 bracketright1
+106 floorleft1
+107 floorright1
+108 ceilingleft1
+109 ceilingright1
+110 braceleft1
+111 braceright1
+112 sr0
+113 sr1
+114 sr2
+115 sr3
+119 arrowvertdblex
+120 arrowverttp
+121 arrowvertbt
+126 arrowvertdbltp
+127 arrowvertdblbt
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/texi.map b/gnu/usr.bin/groff/devices/devdvi/generate/texi.map
new file mode 100644
index 000000000000..835c6421f611
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/texi.map
@@ -0,0 +1,127 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 rq
+35 # sh
+36 Po char163
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 +
+44 ,
+45 - hy char173
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 r! char161
+61 =
+62 r? char191
+63 ?
+64 @ at
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 [ lB
+92 lq
+93 ] rB
+94 a^ ^ ha
+95 a.
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f Fn
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 en
+124 em
+125 a"
+126 a~ ~
+127 ad char168
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/texmi.map b/gnu/usr.bin/groff/devices/devdvi/generate/texmi.map
new file mode 100644
index 000000000000..6d01dc4cf90c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/texmi.map
@@ -0,0 +1,32 @@
+11 *a
+12 *b
+13 *g
+14 *d
+15 *e
+16 *z
+17 *y
+18 *h
+19 *i
+20 *k
+21 *l
+22 *m char181
+23 *n
+24 *c
+25 *p
+26 *r
+27 *s
+28 *t
+29 *u
+30 *f
+31 *x
+32 *q
+33 *w
+35 +h
+36 +p
+38 ts
+39 +f
+60 <
+62 >
+64 pd
+111 *o
+125 wp
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/texr.map b/gnu/usr.bin/groff/devices/devdvi/generate/texr.map
new file mode 100644
index 000000000000..bebf67b80c31
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/texr.map
@@ -0,0 +1,127 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 rq
+35 # sh
+36 $ Do
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 + pl
+44 ,
+45 - hy char173
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 r! char161
+61 = eq
+62 r? char191
+63 ?
+64 @ at
+65 A *A
+66 B *B
+67 C
+68 D
+69 E *E
+70 F
+71 G
+72 H *Y
+73 I *I
+74 J
+75 K *K
+76 L
+77 M *M
+78 N *N
+79 O *O
+80 P *R
+81 Q
+82 R
+83 S
+84 T *T
+85 U
+86 V
+87 W
+88 X *X
+89 Y
+90 Z *Z
+91 [ lB
+92 lq
+93 ] rB
+94 a^ ^ ha
+95 a.
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 en
+124 em
+125 a"
+126 a~ ~
+127 ad char168
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/texsy.map b/gnu/usr.bin/groff/devices/devdvi/generate/texsy.map
new file mode 100644
index 000000000000..2c970bc2a47e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/texsy.map
@@ -0,0 +1,100 @@
+0 \- mi
+1 md
+2 mu char215
+3 **
+4 di char247
+6 +- char177
+7 -+
+8 c+
+10 c*
+13 ci
+15 bu
+17 ==
+18 ib
+19 ip
+20 <=
+21 >=
+24 ap ti
+25 ~~
+26 sb
+27 sp
+28 <<
+29 >>
+32 <-
+33 ->
+34 ua
+35 da
+36 <>
+39 ~=
+40 lA lh
+41 rA rh
+42 uA
+43 dA
+44 hA
+47 pt
+48 prime
+49 if
+50 mo
+51 st
+54 slashnot
+56 fa
+57 te
+58 no char172
+59 es
+60 Re
+61 Im
+63 pp
+64 Ah
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 cu
+92 ca
+94 AN
+95 OR
+98 lf
+99 rf
+100 lc
+101 rc
+102 lC {
+103 rC }
+104 la
+105 ra
+106 ba | bv or bar
+107 bardbl
+108 va
+109 vA
+110 \ rs
+112 sr
+114 gr
+120 sc char167
+121 dg
+122 dd
+123 ps char182
+124 CL
+125 DI
+126 HE
+127 SP
diff --git a/gnu/usr.bin/groff/devices/devdvi/generate/textt.map b/gnu/usr.bin/groff/devices/devdvi/generate/textt.map
new file mode 100644
index 000000000000..1461d0abe9ec
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devdvi/generate/textt.map
@@ -0,0 +1,126 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 "
+35 # sh
+36 $ Do
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 +
+44 ,
+45 - \-
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 <
+61 =
+62 >
+63 ?
+64 @ at
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 [ lB
+92 \ rs
+93 ] rB
+94 a^ ^ ha
+95 _
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 lC {
+124 ba |
+125 rC }
+126 a~ ~
diff --git a/gnu/usr.bin/groff/devices/devlatin1/DESC.proto b/gnu/usr.bin/groff/devices/devlatin1/DESC.proto
new file mode 100644
index 000000000000..88399ab16d91
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devlatin1/DESC.proto
@@ -0,0 +1,8 @@
+res 240
+hor 24
+vert 40
+unitwidth 10
+sizes 10 0
+fonts 4 R I B BI
+tcommand
+postpro grotty
diff --git a/gnu/usr.bin/groff/devices/devlatin1/Makefile b/gnu/usr.bin/groff/devices/devlatin1/Makefile
new file mode 100644
index 000000000000..040504cd60b3
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devlatin1/Makefile
@@ -0,0 +1,6 @@
+# Makefile for devascii
+
+DEVICE= latin1
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devlatin1/R.proto b/gnu/usr.bin/groff/devices/devlatin1/R.proto
new file mode 100644
index 000000000000..29a88754ba3e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devlatin1/R.proto
@@ -0,0 +1,353 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0041
+" 24 0 0042
+lq "
+rq "
+# 24 0 0043
+sh "
+$ 24 0 0044
+Do "
+% 24 0 0045
+& 24 0 0046
+' 24 0 0047
+fm "
+aq "
+( 24 0 0050
+) 24 0 0051
+* 24 0 0052
+** "
++ 24 0 0053
+pl "
+, 24 0 0054
+\- 24 0 0055
+mi "
+- "
+hy "
+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
+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 "
+r! 24 0 0241
+char161 "
+ct 24 0 0242
+char162 "
+Po 24 0 0243
+char163 "
+Cs 24 0 0244
+char164 "
+Ye 24 0 0245
+char165 "
+bb 24 0 0246
+char166 "
+sc 24 0 0247
+char167 "
+ad 24 0 0250
+char168 "
+co 24 0 0251
+char169 "
+Of 24 0 0252
+char170 "
+Fo 24 0 0253
+char171 "
+no 24 0 0254
+char172 "
+char173 24 0 0255
+rg 24 0 0256
+char174 "
+a- 24 0 0257
+char175 "
+de 24 0 0260
+char176 "
+ao "
++- 24 0 0261
+char177 "
+S2 24 0 0262
+char178 "
+S3 24 0 0263
+char179 "
+aa 24 0 0264
+char180 "
+*m 24 0 0265
+char181 "
+ps 24 0 0266
+char182 "
+md 24 0 0267
+char183 "
+ac 24 0 0270
+char184 "
+S1 24 0 0271
+char185 "
+Om 24 0 0272
+char186 "
+Fc 24 0 0273
+char187 "
+14 24 0 0274
+char188 "
+12 24 0 0275
+char189 "
+34 24 0 0276
+char190 "
+r? 24 0 0277
+char191 "
+`A 24 0 0300
+char192 "
+'A 24 0 0301
+char193 "
+^A 24 0 0302
+char194 "
+~A 24 0 0303
+char195 "
+:A 24 0 0304
+char196 "
+oA 24 0 0305
+char197 "
+AE 24 0 0306
+char198 "
+,C 24 0 0307
+char199 "
+`E 24 0 0310
+char200 "
+'E 24 0 0311
+char201 "
+^E 24 0 0312
+char202 "
+:E 24 0 0313
+char203 "
+`I 24 0 0314
+char204 "
+'I 24 0 0315
+char205 "
+^I 24 0 0316
+char206 "
+:I 24 0 0317
+char207 "
+-D 24 0 0320
+char208 "
+~N 24 0 0321
+char209 "
+`O 24 0 0322
+char210 "
+'O 24 0 0323
+char211 "
+^O 24 0 0324
+char212 "
+~O 24 0 0325
+char213 "
+:O 24 0 0326
+char214 "
+mu 24 0 0327
+char215 "
+/O 24 0 0330
+char216 "
+`U 24 0 0331
+char217 "
+'U 24 0 0332
+char218 "
+^U 24 0 0333
+char219 "
+:U 24 0 0334
+char220 "
+'Y 24 0 0335
+char221 "
+TP 24 0 0336
+char222 "
+ss 24 0 0337
+char223 "
+`a 24 0 0340
+char224 "
+'a 24 0 0341
+char225 "
+^a 24 0 0342
+char226 "
+~a 24 0 0343
+char227 "
+:a 24 0 0344
+char228 "
+oa 24 0 0345
+char229 "
+ae 24 0 0346
+char230 "
+,c 24 0 0347
+char231 "
+`e 24 0 0350
+char232 "
+'e 24 0 0351
+char233 "
+^e 24 0 0352
+char234 "
+:e 24 0 0353
+char235 "
+`i 24 0 0354
+char236 "
+'i 24 0 0355
+char237 "
+^i 24 0 0356
+char238 "
+:i 24 0 0357
+char239 "
+Sd 24 0 0360
+char240 "
+~n 24 0 0361
+char241 "
+`o 24 0 0362
+char242 "
+'o 24 0 0363
+char243 "
+^o 24 0 0364
+char244 "
+~o 24 0 0365
+char245 "
+:o 24 0 0366
+char246 "
+di 24 0 0367
+char247 "
+/o 24 0 0370
+char248 "
+`u 24 0 0371
+char249 "
+'u 24 0 0372
+char250 "
+^u 24 0 0373
+char251 "
+:u 24 0 0374
+char252 "
+'y 24 0 0375
+char253 "
+Tp 24 0 0376
+char254 "
+:y 24 0 0377
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/AB b/gnu/usr.bin/groff/devices/devps/AB
new file mode 100644
index 000000000000..d5313f0de490
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/AB
@@ -0,0 +1,559 @@
+name AB
+internalname AvantGarde-Demi
+spacewidth 280
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -50
+A w -65
+A v -70
+A u -20
+A ' -90
+A Y -80
+A W -60
+A V -102
+A U -40
+A T -25
+A Q -50
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -45
+D W -25
+D V -50
+D A -50
+F . -129
+F e -20
+F , -162
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -15
+J . -15
+J a -20
+J A -30
+K y -20
+K u -15
+K o -45
+K e -40
+K O -30
+L y -23
+L ' -30
+L rq -30
+L Y -80
+L W -55
+L V -85
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -45
+O T -15
+O A -60
+P . -200
+P o -20
+P e -20
+P , -220
+P a -20
+P A -100
+Q , 20
+R W 25
+R V -10
+R U 25
+R T 40
+R O 25
+S , 20
+T y -10
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -49
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -70
+T O -15
+T A -25
+U . -20
+U , -20
+U A -40
+V u -55
+V ; -33
+V . -145
+V o -101
+V i -15
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -95
+V O -45
+V G -20
+V A -102
+W y -15
+W u -30
+W ; -33
+W . -106
+W o -46
+W i -10
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -145
+Y o -89
+Y - -100
+Y hy -100
+Y char173 -100
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -80
+a t 5
+a p 20
+a b 5
+b y -20
+b v -20
+c y -20
+c l -15
+c k -15
+, ' -70
+, rq -70
+e y -20
+e x -20
+e w -20
+e v -20
+f . -40
+f o -20
+f l -15
+f i -15
+f f -20
+f .i -15
+f , -40
+f a -15
+g i 25
+g a 15
+h y -30
+k y -5
+k o -30
+k e -40
+m y -20
+m u -20
+n y -15
+n v -30
+o y -20
+o x -30
+o w -20
+o v -30
+p y -20
+. ' -70
+. rq -70
+lq A -50
+` ` -80
+` oq -80
+oq ` -80
+oq oq -80
+` A -50
+oq A -50
+' v -10
+' t 10
+' s -15
+' r -20
+' ' -80
+' d -50
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -15
+r n 21
+r m 15
+r l 20
+r k 5
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g 1
+r e -4
+r d -6
+r , -75
+r c -7
+s . 20
+s , 20
+v . -90
+v o -20
+v e -20
+v , -90
+v a -30
+w . -90
+w o -30
+w e -20
+w , -90
+w a -30
+x e -20
+y . -100
+y o -30
+y e -20
+y , -100
+y c -35
+y a -30
+charset
+ha 600,740 2 0000 asciicircum
+ti 600,347 0 0001 asciitilde
+vS 520,944,15 2 0002 Scaron
+vZ 500,944 2 0003 Zcaron
+vs 440,774,18 2 0004 scaron
+vz 460,774 2 0005 zcaron
+:Y 620,939 2 0006 Ydieresis
+tm 1000,740 2 0007 trademark
+aq 220,740 2 0010 quotesingle
+space 280 0 0040
+! 280,740 2 0041 exclam
+" 360,740 2 0042 quotedbl
+# 560,700 0 0043 numbersign
+sh "
+$ 560,857,86 2 0044 dollar
+Do "
+% 860,755,15 2 0045 percent
+& 680,755,15 2 0046 ampersand
+' 280,740 2 0047 quoteright
+( 380,754,157 2 0050 parenleft
+) 380,754,157 2 0051 parenright
+* 440,755 2 0052 asterisk
++ 600,506 0 0053 plus
+, 280,133,141 0 0054 comma
+- 420,348 0 0055 hyphen
+hy "
+char173 "
+. 280,133 0 0056 period
+/ 460,740,100 2 0057 slash
+sl "
+0 560,755,15 2 0060 zero
+1 560,740 2 0061 one
+2 560,755 2 0062 two
+3 560,755,15 2 0063 three
+4 560,740 2 0064 four
+5 560,740,15 2 0065 five
+6 560,739,15 2 0066 six
+7 560,740 2 0067 seven
+8 560,755,15 2 0070 eight
+9 560,754 2 0071 nine
+: 280,555 0 0072 colon
+; 280,555,141 0 0073 semicolon
+< 600,514,8 0 0074 less
+= 600,425 0 0075 equal
+> 600,514,8 0 0076 greater
+? 560,755 2 0077 question
+@ 740,712,12 0 0100 at
+at "
+A 740,740 2 0101 A
+B 580,740 2 0102 B
+C 780,755,15 2 0103 C
+D 700,740 2 0104 D
+E 520,740 2 0105 E
+F 480,740 2 0106 F
+G 840,755,15 2 0107 G
+H 680,740 2 0110 H
+I 280,740 2 0111 I
+J 480,740,15 2 0112 J
+K 620,740 2 0113 K
+L 440,740 2 0114 L
+M 900,740 2 0115 M
+N 740,740 2 0116 N
+O 840,755,15 2 0117 O
+P 560,740 2 0120 P
+Q 840,755,15 2 0121 Q
+R 580,740 2 0122 R
+S 520,755,15 2 0123 S
+T 420,740 2 0124 T
+U 640,740,15 2 0125 U
+V 700,740 2 0126 V
+W 900,740 2 0127 W
+X 680,740 2 0130 X
+Y 620,740 2 0131 Y
+Z 500,740 2 0132 Z
+[ 320,754,157 2 0133 bracketleft
+lB "
+\ 640,740,100 2 0134 backslash
+rs "
+] 320,754,157 2 0135 bracketright
+rB "
+a^ 540,774 2 0136 circumflex
+^ "
+_ 500,0,125 0 0137 underscore
+` 280,740 2 0140 quoteleft
+oq "
+a 660,574,18 0 0141 a
+b 660,740,18 2 0142 b
+c 640,574,18 0 0143 c
+d 660,740,18 2 0144 d
+e 640,577,18 0 0145 e
+f 280,755 2 0146 f
+g 660,574,226 1 0147 g
+h 600,740 2 0150 h
+i 240,740 2 0151 i
+j 260,740,185 3 0152 j
+k 580,740 2 0153 k
+l 240,740 2 0154 l
+m 940,574 0 0155 m
+n 600,574 0 0156 n
+o 640,574,18 0 0157 o
+p 660,574,185 1 0160 p
+q 660,574,185 1 0161 q
+r 320,574 0 0162 r
+s 440,574,18 0 0163 s
+t 300,740 2 0164 t
+u 600,555,18 0 0165 u
+v 560,555 0 0166 v
+w 800,555 0 0167 w
+x 560,555 0 0170 x
+y 580,555,185 1 0171 y
+z 460,555 0 0172 z
+lC 340,747,191 3 0173 braceleft
+{ "
+ba 600,740,100 2 0174 bar
+| "
+rC 340,747,191 3 0175 braceright
+} "
+a~ 480,767 2 0176 tilde
+~ "
+bq 280,133,141 0 0200 quotesinglbase
+Fo 460,469 0 0201 guillemotleft
+char171 "
+Fc 460,469 0 0202 guillemotright
+char187 "
+bu 600,532 0 0203 bullet
+Fn 560,824,151 2 0204 florin
+f/ 160,740 2 0205 fraction
+%0 1280,755,15 2 0206 perthousand
+dg 560,740,142 2 0207 dagger
+dd 560,740,142 2 0210 daggerdbl
+en 500,348 0 0211 endash
+em 1000,348 0 0212 emdash
+fi 520,755 2 0214 fi
+fl 520,755 2 0215 fl
+.i 240,555 0 0220 dotlessi
+ga 420,851 2 0222 grave
+a" 700,862 2 0223 hungarumlaut
+a. 280,769 2 0224 dotaccent
+ab 480,770 2 0225 breve
+ah 540,774 2 0226 caron
+ao 360,834 2 0227 ring
+ho 340,9,195 1 0230 ogonek
+lq 480,740 2 0231 quotedblleft
+rq 480,740 2 0232 quotedblright
+oe 1080,574,18 0 0233 oe
+/l 320,740 2 0234 lslash
+Bq 480,133,141 0 0235 quotedblbase
+OE 1060,755,15 2 0236 OE
+/L 480,740 2 0237 Lslash
+r! 280,555,185 1 0241 exclamdown
+char161 "
+ct 560,715 0 0242 cent
+char162 "
+Po 560,755 2 0243 sterling
+char163 "
+Cs 560,577 0 0244 currency
+char164 "
+Ye 560,740 2 0245 yen
+char165 "
+bb 600,740,100 2 0246 brokenbar
+char166 "
+sc 560,755,158 2 0247 section
+char167 "
+ad 500,769 2 0250 dieresis
+char168 "
+co 740,752,12 2 0251 copyright
+char169 "
+Of 360,755 2 0252 ordfeminine
+char170 "
+fo 240,469 0 0253 guilsinglleft
+no 600,425 0 0254 logicalnot
+char172 "
+\- 600,313 0 0255 minus
+rg 740,752,12 2 0256 registered
+char174 "
+a- 420,759 2 0257 macron
+char175 "
+de 400,712 0 0260 degree
+char176 "
+char177 600,556,62 0 0261 plusminus
+S2 336,749 2 0262 twosuperior
+char178 "
+S3 336,749 2 0263 threesuperior
+char179 "
+aa 420,849 2 0264 acute
+char180 "
+char181 576,555,187 1 0265 mu
+ps 600,740,103 2 0266 paragraph
+char182 "
+char183 280,320 0 0267 periodcentered
+ac 340,6,251 1 0270 cedilla
+char184 "
+S1 336,740 2 0271 onesuperior
+char185 "
+Om 360,755 2 0272 ordmasculine
+char186 "
+fc 240,469 0 0273 guilsinglright
+14 840,740 2 0274 onequarter
+char188 "
+12 840,740 2 0275 onehalf
+char189 "
+34 840,749 2 0276 threequarters
+char190 "
+r? 560,555,200 1 0277 questiondown
+char191 "
+`A 740,1021 2 0300 Agrave
+char192 "
+'A 740,1019 2 0301 Aacute
+char193 "
+^A 740,944 2 0302 Acircumflex
+char194 "
+~A 740,937 2 0303 Atilde
+char195 "
+:A 740,939 2 0304 Adieresis
+char196 "
+oA 740,969 2 0305 Aring
+char197 "
+AE 900,740 2 0306 AE
+char198 "
+,C 780,755,251 3 0307 Ccedilla
+char199 "
+`E 520,1021 2 0310 Egrave
+char200 "
+'E 520,1019 2 0311 Eacute
+char201 "
+^E 520,944 2 0312 Ecircumflex
+char202 "
+:E 520,939 2 0313 Edieresis
+char203 "
+`I 280,1021 2 0314 Igrave
+char204 "
+'I 280,1019 2 0315 Iacute
+char205 "
+^I 280,944 2 0316 Icircumflex
+char206 "
+:I 280,939 2 0317 Idieresis
+char207 "
+-D 742,740 2 0320 Eth
+char208 "
+~N 740,937 2 0321 Ntilde
+char209 "
+`O 840,1021,15 2 0322 Ograve
+char210 "
+'O 840,1019,15 2 0323 Oacute
+char211 "
+^O 840,944,15 2 0324 Ocircumflex
+char212 "
+~O 840,937,15 2 0325 Otilde
+char213 "
+:O 840,939,15 2 0326 Odieresis
+char214 "
+char215 600,494 0 0327 multiply
+/O 840,814,71 2 0330 Oslash
+char216 "
+`U 640,1021,15 2 0331 Ugrave
+char217 "
+'U 640,1019,15 2 0332 Uacute
+char218 "
+^U 640,944,15 2 0333 Ucircumflex
+char219 "
+:U 640,939,15 2 0334 Udieresis
+char220 "
+'Y 620,1019 2 0335 Yacute
+char221 "
+TP 560,740 2 0336 Thorn
+char222 "
+ss 600,755,18 2 0337 germandbls
+char223 "
+`a 660,851,18 2 0340 agrave
+char224 "
+'a 660,849,18 2 0341 aacute
+char225 "
+^a 660,774,18 2 0342 acircumflex
+char226 "
+~a 660,767,18 2 0343 atilde
+char227 "
+:a 660,769,18 2 0344 adieresis
+char228 "
+oa 660,834,18 2 0345 aring
+char229 "
+ae 1080,574,18 0 0346 ae
+char230 "
+,c 640,574,251 1 0347 ccedilla
+char231 "
+`e 640,851,18 2 0350 egrave
+char232 "
+'e 640,849,18 2 0351 eacute
+char233 "
+^e 640,774,18 2 0352 ecircumflex
+char234 "
+:e 640,769,18 2 0353 edieresis
+char235 "
+`i 240,851 2 0354 igrave
+char236 "
+'i 240,849 2 0355 iacute
+char237 "
+^i 240,774 2 0356 icircumflex
+char238 "
+:i 240,769 2 0357 idieresis
+char239 "
+Sd 640,754,18 2 0360 eth
+char240 "
+~n 600,767 2 0361 ntilde
+char241 "
+`o 640,851,18 2 0362 ograve
+char242 "
+'o 640,849,18 2 0363 oacute
+char243 "
+^o 640,774,18 2 0364 ocircumflex
+char244 "
+~o 640,767,18 2 0365 otilde
+char245 "
+:o 640,769,18 2 0366 odieresis
+char246 "
+char247 600,526,20 0 0367 divide
+/o 660,608,50 0 0370 oslash
+char248 "
+`u 600,851,18 2 0371 ugrave
+char249 "
+'u 600,849,18 2 0372 uacute
+char250 "
+^u 600,774,18 2 0373 ucircumflex
+char251 "
+:u 600,769,18 2 0374 udieresis
+char252 "
+'y 580,849,185 3 0375 yacute
+char253 "
+Tp 660,740,185 3 0376 thorn
+char254 "
+:y 580,769,185 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/ABI b/gnu/usr.bin/groff/devices/devps/ABI
new file mode 100644
index 000000000000..000d9588589c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/ABI
@@ -0,0 +1,560 @@
+name ABI
+internalname AvantGarde-DemiOblique
+slant 10.5
+spacewidth 280
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -50
+A w -65
+A v -70
+A u -20
+A ' -90
+A Y -80
+A W -60
+A V -102
+A U -40
+A T -25
+A Q -50
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -45
+D W -25
+D V -50
+D A -50
+F . -129
+F e -20
+F , -162
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -15
+J . -15
+J a -20
+J A -30
+K y -20
+K u -15
+K o -45
+K e -40
+K O -30
+L y -23
+L ' -30
+L rq -30
+L Y -80
+L W -55
+L V -85
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -45
+O T -15
+O A -60
+P . -200
+P o -20
+P e -20
+P , -220
+P a -20
+P A -100
+Q , 20
+R W 25
+R V -10
+R U 25
+R T 40
+R O 25
+S , 20
+T y -10
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -49
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -70
+T O -15
+T A -25
+U . -20
+U , -20
+U A -40
+V u -55
+V ; -33
+V . -145
+V o -101
+V i -15
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -95
+V O -45
+V G -20
+V A -102
+W y -15
+W u -30
+W ; -33
+W . -106
+W o -46
+W i -10
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -145
+Y o -89
+Y - -100
+Y hy -100
+Y char173 -100
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -80
+a t 5
+a p 20
+a b 5
+b y -20
+b v -20
+c y -20
+c l -15
+c k -15
+, ' -70
+, rq -70
+e y -20
+e x -20
+e w -20
+e v -20
+f . -40
+f o -20
+f l -15
+f i -15
+f f -20
+f .i -15
+f , -40
+f a -15
+g i 25
+g a 15
+h y -30
+k y -5
+k o -30
+k e -40
+m y -20
+m u -20
+n y -15
+n v -30
+o y -20
+o x -30
+o w -20
+o v -30
+p y -20
+. ' -70
+. rq -70
+lq A -50
+` ` -80
+` oq -80
+oq ` -80
+oq oq -80
+` A -50
+oq A -50
+' v -10
+' t 10
+' s -15
+' r -20
+' ' -80
+' d -50
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -15
+r n 21
+r m 15
+r l 20
+r k 5
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g 1
+r e -4
+r d -6
+r , -75
+r c -7
+s . 20
+s , 20
+v . -90
+v o -20
+v e -20
+v , -90
+v a -30
+w . -90
+w o -30
+w e -20
+w , -90
+w a -30
+x e -20
+y . -100
+y o -30
+y e -20
+y , -100
+y c -35
+y a -30
+charset
+ha 600,740,0,46,-92,46 2 0000 asciicircum
+ti 600,347,0,29,-64,29 0 0001 asciitilde
+vS 520,944,15,165,1,82 2 0002 Scaron
+vZ 500,944,0,200,31,82 2 0003 Zcaron
+vs 440,774,18,173,1,82 2 0004 scaron
+vz 460,774,0,188,30,82 2 0005 zcaron
+:Y 620,939,0,189,-85,82 2 0006 Ydieresis
+tm 1000,740,0,8,-81,8 2 0007 trademark
+aq 220,740,0,144,-102,82 2 0010 quotesingle
+space 280 0 0040
+! 280,740,0,113,-23,82 2 0041 exclam
+" 360,740,0,168,-77,82 2 0042 quotedbl
+# 560,700,0,108,-16,82 0 0043 numbersign
+sh "
+$ 560,857,86,72,-49,72 2 0044 dollar
+Do "
+% 860,755,15,46,-89,46 2 0045 percent
+& 680,755,15,112,-21,82 2 0046 ampersand
+' 280,740,0,112,-109,82 2 0047 quoteright
+( 380,754,157,160,-70,82 2 0050 parenleft
+) 380,754,157,48,42,48 2 0051 parenright
+* 440,755,0,102,-124,82 2 0052 asterisk
++ 600,506,0,60,-34,60 0 0053 plus
+, 280,133,141,1,2,1 0 0054 comma
+- 420,348,0,43,-64,43 0 0055 hyphen
+hy "
+char173 "
+. 280,133,0,1,-23,1 0 0056 period
+/ 460,740,100,181,63,82 2 0057 slash
+sl "
+0 560,755,15,118,-20,82 2 0060 zero
+1 560,740,0,0,-180 2 0061 one
+2 560,755,0,112,6,82 2 0062 two
+3 560,755,15,75,-17,75 2 0063 three
+4 560,740,0,94,14,82 2 0064 four
+5 560,740,15,90,-14,82 2 0065 five
+6 560,739,15,77,-14,77 2 0066 six
+7 560,740,0,125,-33,82 2 0067 seven
+8 560,755,15,80,-21,80 2 0070 eight
+9 560,754,0,123,-60,82 2 0071 nine
+: 280,555,0,79,-23,79 0 0072 colon
+; 280,555,141,79,2,79 0 0073 semicolon
+< 600,514,8,99,-34,82 0 0074 less
+= 600,425,0,81,-13,81 0 0075 equal
+> 600,514,8,60,5,60 0 0076 greater
+? 560,755,0,83,-85,82 2 0077 question
+@ 740,712,12,142,-59,82 0 0100 at
+at "
+A 740,740,0,42,43,42 2 0101 A
+B 580,740,0,80,-20,80 2 0102 B
+C 780,755,15,134,-47,82 2 0103 C
+D 700,740,0,82,-13,82 2 0104 D
+E 520,740,0,126,-11,82 2 0105 E
+F 480,740,0,145,-11,82 2 0106 F
+G 840,755,15,97,-39,82 2 0107 G
+H 680,740,0,117,-21,82 2 0110 H
+I 280,740,0,116,-22,82 2 0111 I
+J 480,740,15,116,16,82 2 0112 J
+K 620,740,0,187,-39,82 2 0113 K
+L 440,740,0,69,-22,69 2 0114 L
+M 900,740,0,124,-13,82 2 0115 M
+N 740,740,0,118,-20,82 2 0116 N
+O 840,755,15,92,-45,82 2 0117 O
+P 560,740,0,135,-22,82 2 0120 P
+Q 840,755,15,92,-44,82 2 0121 Q
+R 580,740,0,126,-14,82 2 0122 R
+S 520,755,15,108,1,82 2 0123 S
+T 420,740,0,185,-69,82 2 0124 T
+U 640,740,15,132,-47,82 2 0125 U
+V 700,740,0,182,-95,82 2 0126 V
+W 900,740,0,186,-94,82 2 0127 W
+X 680,740,0,183,46,82 2 0130 X
+Y 620,740,0,189,-85,82 2 0131 Y
+Z 500,740,0,149,31,82 2 0132 Z
+[ 320,754,157,154,-39,82 2 0133 bracketleft
+lB "
+\ 640,740,100,0,-183 2 0134 backslash
+rs "
+] 320,754,157,72,43,72 2 0135 bracketright
+rB "
+a^ 540,774,0,98,-139,82 2 0136 circumflex
+^ "
+_ 500,0,125,36,73,36 0 0137 underscore
+` 280,740,0,111,-108,82 2 0140 quoteleft
+oq "
+a 660,574,18,106,-23,82 0 0141 a
+b 660,740,18,79,3,79 2 0142 b
+c 640,574,18,89,-34,82 0 0143 c
+d 660,740,18,145,-30,82 2 0144 d
+e 640,577,18,77,-27,77 0 0145 e
+f 280,755,0,190,-12,82 2 0146 f
+g 660,574,226,116,17,82 1 0147 g
+h 600,740,0,64,-4,64 2 0150 h
+i 240,740,0,133,-3,82 2 0151 i
+j 260,740,185,132,68,82 3 0152 j
+k 580,740,0,118,-30,82 2 0153 k
+l 240,740,0,134,-4,82 2 0154 l
+m 940,574,0,64,-4,64 0 0155 m
+n 600,574,0,63,-4,63 0 0156 n
+o 640,574,18,82,-21,82 0 0157 o
+p 660,574,185,76,37,76 1 0160 p
+q 660,574,185,106,-28,82 1 0161 q
+r 320,574,0,153,-13,82 0 0162 r
+s 440,574,18,93,1,82 0 0163 s
+t 300,740,0,152,-36,82 2 0164 t
+u 600,555,18,97,-37,82 0 0165 u
+v 560,555,0,149,-56,82 0 0166 v
+w 800,555,0,142,-64,82 0 0167 w
+x 560,555,0,122,47,82 0 0170 x
+y 580,555,185,144,-25,82 1 0171 y
+z 460,555,0,118,30,82 0 0172 z
+lC 340,747,191,165,10,82 3 0173 braceleft
+{ "
+ba 600,740,100,0,-164 2 0174 bar
+| "
+rC 340,747,191,115,62,82 3 0175 braceright
+} "
+a~ 480,767,0,134,-128,82 2 0176 tilde
+~ "
+bq 280,133,141,0,3 0 0200 quotesinglbase
+Fo 460,469,0,77,-55,77 0 0201 guillemotleft
+char171 "
+Fc 460,469,0,53,-31,53 0 0202 guillemotright
+char187 "
+bu 600,532,0,0,-165 0 0203 bullet
+Fn 560,824,151,154,77,82 2 0204 florin
+f/ 160,740,0,309,173,82 2 0205 fraction
+%0 1280,755,15,26,-89,26 2 0206 perthousand
+dg 560,740,142,102,-83,82 2 0207 dagger
+dd 560,740,142,108,-13,82 2 0210 daggerdbl
+en 500,348,0,79,-28,79 0 0211 endash
+em 1000,348,0,79,-28,79 0 0212 emdash
+fi 520,755,0,128,-22,82 2 0214 fi
+fl 520,755,0,128,-22,82 2 0215 fl
+.i 240,555,0,99,-3,82 0 0220 dotlessi
+ga 420,851,0,92,-139,82 2 0222 grave
+a" 700,862,0,104,-208,82 2 0223 hungarumlaut
+a. 280,769,0,120,-142,82 2 0224 dotaccent
+ab 480,770,0,152,-135,82 2 0225 breve
+ah 540,774,0,123,-164,82 2 0226 caron
+ao 360,834,0,114,-156,82 2 0227 ring
+ho 340,9,195,0,-9 1 0230 ogonek
+lq 480,740,0,116,-106,82 2 0231 quotedblleft
+rq 480,740,0,117,-107,82 2 0232 quotedblright
+oe 1080,574,18,78,-26,78 0 0233 oe
+/l 320,740,0,134,-24,82 2 0234 lslash
+Bq 480,133,141,5,5,5 0 0235 quotedblbase
+OE 1060,755,15,134,-48,82 2 0236 OE
+/L 480,740,0,54,-18,54 2 0237 Lslash
+r! 280,555,185,80,10,80 1 0241 exclamdown
+char161 "
+ct 560,715,0,89,-60,82 0 0242 cent
+char162 "
+Po 560,755,0,105,12,82 2 0243 sterling
+char163 "
+Cs 560,577,0,118,-3,82 0 0244 currency
+char164 "
+Ye 560,740,0,197,-33,82 2 0245 yen
+char165 "
+bb 600,740,100,0,-164 2 0246 brokenbar
+char166 "
+sc 560,755,158,92,-15,82 2 0247 section
+char167 "
+ad 500,769,0,115,-146,82 2 0250 dieresis
+char168 "
+co 740,752,12,137,0,82 2 0251 copyright
+char169 "
+Of 360,755,0,162,-77,82 2 0252 ordfeminine
+char170 "
+fo 240,469,0,87,-44,82 0 0253 guilsinglleft
+no 600,425,0,81,-55,81 0 0254 logicalnot
+char172 "
+\- 600,313,0,60,-34,60 0 0255 minus
+rg 740,752,12,137,0,82 2 0256 registered
+char174 "
+a- 420,759,0,120,-142,82 2 0257 macron
+char175 "
+de 400,712,0,101,-110,82 0 0260 degree
+char176 "
+char177 600,556,62,76,13,76 0 0261 plusminus
+S2 336,749,0,150,-23,82 2 0262 twosuperior
+char178 "
+S3 336,749,0,127,-37,82 2 0263 threesuperior
+char179 "
+aa 420,849,0,138,-174,82 2 0264 acute
+char180 "
+char181 576,555,187,116,47,82 1 0265 mu
+ps 600,740,103,194,-40,82 2 0266 paragraph
+char182 "
+char183 280,320,0,35,-58,35 0 0267 periodcentered
+ac 340,6,251,0,-17 1 0270 cedilla
+char184 "
+S1 336,740,0,74,-132,74 2 0271 onesuperior
+char185 "
+Om 360,755,0,141,-81,82 2 0272 ordmasculine
+char186 "
+fc 240,469,0,63,-20,63 0 0273 guilsinglright
+14 840,740,0,0,-137 2 0274 onequarter
+char188 "
+12 840,740,0,40,-107,40 2 0275 onehalf
+char189 "
+34 840,749,0,46,-47,46 2 0276 threequarters
+char190 "
+r? 560,555,200,17,-19,17 1 0277 questiondown
+char191 "
+`A 740,1021,0,42,43,42 2 0300 Agrave
+char192 "
+'A 740,1019,0,42,43,42 2 0301 Aacute
+char193 "
+^A 740,944,0,42,43,42 2 0302 Acircumflex
+char194 "
+~A 740,937,0,42,43,42 2 0303 Atilde
+char195 "
+:A 740,939,0,42,43,42 2 0304 Adieresis
+char196 "
+oA 740,969,0,42,43,42 2 0305 Aring
+char197 "
+AE 900,740,0,111,55,82 2 0306 AE
+char198 "
+,C 780,755,251,134,-47,82 3 0307 Ccedilla
+char199 "
+`E 520,1021,0,126,-11,82 2 0310 Egrave
+char200 "
+'E 520,1019,0,126,-11,82 2 0311 Eacute
+char201 "
+^E 520,944,0,139,-11,82 2 0312 Ecircumflex
+char202 "
+:E 520,939,0,136,-11,82 2 0313 Edieresis
+char203 "
+`I 280,1021,0,168,-22,82 2 0314 Igrave
+char204 "
+'I 280,1019,0,264,-22,82 2 0315 Iacute
+char205 "
+^I 280,944,0,259,-22,82 2 0316 Icircumflex
+char206 "
+:I 280,939,0,256,-22,82 2 0317 Idieresis
+char207 "
+-D 742,740,0,74,-33,74 2 0320 Eth
+char208 "
+~N 740,937,0,118,-20,82 2 0321 Ntilde
+char209 "
+`O 840,1021,15,92,-45,82 2 0322 Ograve
+char210 "
+'O 840,1019,15,92,-45,82 2 0323 Oacute
+char211 "
+^O 840,944,15,92,-45,82 2 0324 Ocircumflex
+char212 "
+~O 840,937,15,92,-45,82 2 0325 Otilde
+char213 "
+:O 840,939,15,92,-45,82 2 0326 Odieresis
+char214 "
+char215 600,494,0,67,-26,67 0 0327 multiply
+/O 840,814,71,101,-44,82 2 0330 Oslash
+char216 "
+`U 640,1021,15,132,-47,82 2 0331 Ugrave
+char217 "
+'U 640,1019,15,132,-47,82 2 0332 Uacute
+char218 "
+^U 640,944,15,132,-47,82 2 0333 Ucircumflex
+char219 "
+:U 640,939,15,132,-47,82 2 0334 Udieresis
+char220 "
+'Y 620,1019,0,189,-85,82 2 0335 Yacute
+char221 "
+TP 560,740,0,109,-22,82 2 0336 Thorn
+char222 "
+ss 600,755,18,79,-1,79 2 0337 germandbls
+char223 "
+`a 660,851,18,106,-23,82 2 0340 agrave
+char224 "
+'a 660,849,18,106,-23,82 2 0341 aacute
+char225 "
+^a 660,774,18,106,-23,82 2 0342 acircumflex
+char226 "
+~a 660,767,18,106,-23,82 2 0343 atilde
+char227 "
+:a 660,769,18,106,-23,82 2 0344 adieresis
+char228 "
+oa 660,834,18,106,-23,82 2 0345 aring
+char229 "
+ae 1080,574,18,75,-25,75 0 0346 ae
+char230 "
+,c 640,574,251,89,-33,82 1 0347 ccedilla
+char231 "
+`e 640,851,18,77,-27,77 2 0350 egrave
+char232 "
+'e 640,849,18,77,-27,77 2 0351 eacute
+char233 "
+^e 640,774,18,77,-27,77 2 0352 ecircumflex
+char234 "
+:e 640,769,18,77,-27,77 2 0353 edieresis
+char235 "
+`i 240,851,0,157,-3,82 2 0354 igrave
+char236 "
+'i 240,849,0,253,-3,82 2 0355 iacute
+char237 "
+^i 240,774,0,248,11,82 2 0356 icircumflex
+char238 "
+:i 240,769,0,245,-3,82 2 0357 idieresis
+char239 "
+Sd 640,754,18,109,-23,82 2 0360 eth
+char240 "
+~n 600,767,0,74,-4,74 2 0361 ntilde
+char241 "
+`o 640,851,18,82,-21,82 2 0362 ograve
+char242 "
+'o 640,849,18,82,-21,82 2 0363 oacute
+char243 "
+^o 640,774,18,82,-21,82 2 0364 ocircumflex
+char244 "
+~o 640,767,18,82,-21,82 2 0365 otilde
+char245 "
+:o 640,769,18,82,-21,82 2 0366 odieresis
+char246 "
+char247 600,526,20,60,-34,60 0 0367 divide
+/o 660,608,50,75,-31,75 0 0370 oslash
+char248 "
+`u 600,851,18,97,-37,82 2 0371 ugrave
+char249 "
+'u 600,849,18,97,-37,82 2 0372 uacute
+char250 "
+^u 600,774,18,97,-37,82 2 0373 ucircumflex
+char251 "
+:u 600,769,18,97,-37,82 2 0374 udieresis
+char252 "
+'y 580,849,185,144,-25,82 3 0375 yacute
+char253 "
+Tp 660,740,185,76,37,76 3 0376 thorn
+char254 "
+:y 580,769,185,144,-25,82 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/AI b/gnu/usr.bin/groff/devices/devps/AI
new file mode 100644
index 000000000000..686823706a30
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/AI
@@ -0,0 +1,559 @@
+name AI
+internalname AvantGarde-BookOblique
+slant 10.5
+spacewidth 277
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -62
+A w -65
+A v -70
+A u -20
+A ' -100
+A rq -100
+A Y -92
+A W -60
+A V -102
+A U -40
+A T -45
+A Q -40
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -30
+D W -10
+D V -50
+D A -50
+F . -160
+F e -20
+F , -180
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -20
+J . -15
+J a -20
+J A -30
+K o -15
+K e -20
+K O -20
+L y -23
+L ' -130
+L rq -130
+L Y -91
+L W -67
+L V -113
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -60
+O T -30
+O A -60
+P . -300
+P o -60
+P e -20
+P , -280
+P a -20
+P A -114
+Q , 20
+R Y -10
+R W 10
+R V -10
+R T 6
+S , 20
+T y -50
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -70
+T i 10
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -90
+T O -30
+T A -45
+U . -20
+U , -20
+U A -40
+V u -40
+V ; -33
+V . -165
+V o -101
+V i -5
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -104
+V O -60
+V G -20
+V A -102
+W y -2
+W u -30
+W ; -33
+W . -106
+W o -46
+W i 6
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -175
+Y o -89
+Y - -85
+Y hy -85
+Y char173 -85
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -92
+a p 20
+a b 20
+b y -20
+b v -20
+c y -20
+c k -15
+, ' -120
+, rq -120
+e y -20
+e w -20
+e v -20
+f . -50
+f o -40
+f l -30
+f i -34
+f f -60
+f e -20
+f .i -34
+f , -50
+f a -40
+g a -15
+h y -30
+k y -5
+k e -15
+m y -20
+m u -20
+m a -20
+n y -15
+n v -20
+o y -20
+o x -15
+o w -20
+o v -30
+p y -20
+. ' -120
+. rq -120
+lq ` -35
+lq oq -35
+lq A -100
+` ` -203
+` oq -203
+oq ` -203
+oq oq -203
+` A -100
+oq A -100
+' v -30
+' t 10
+' s -15
+' r -20
+' ' -203
+' rq -35
+' d -110
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -20
+r n 21
+r m 28
+r l 20
+r k 20
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g -15
+r e -4
+r d -6
+r , -75
+r c -20
+r a -20
+s . 20
+s , 20
+v . -130
+v o -30
+v e -20
+v , -100
+v a -30
+w . -100
+w o -30
+w h 15
+w e -20
+w , -90
+w a -30
+y . -125
+y o -30
+y e -20
+y , -110
+y a -30
+charset
+ha 606,740,0,54,-60,54 2 0000 asciicircum
+ti 606,319,0,28,-64,28 0 0001 asciitilde
+vS 498,927,13,145,-7,81 2 0002 Scaron
+vZ 480,927,0,166,38,81 2 0003 Zcaron
+vs 388,764,13,170,1,81 2 0004 scaron
+vz 425,764,0,152,40,81 2 0005 zcaron
+:Y 592,928,0,187,-88,81 2 0006 Ydieresis
+tm 1000,740,0,3,-87,3 2 0007 trademark
+aq 198,740,0,129,-103,81 2 0010 quotesingle
+space 277 0 0040
+! 295,740,0,77,-61,77 2 0041 exclam
+" 309,740,0,151,-80,81 2 0042 quotedbl
+# 554,740,0,116,-21,81 2 0043 numbersign
+sh "
+$ 554,811,70,77,-57,77 2 0044 dollar
+Do "
+% 775,751,13,62,-74,62 2 0045 percent
+& 757,753,12,68,-42,68 2 0046 ampersand
+' 351,740,0,92,-145,81 2 0047 quoteright
+( 369,757,205,176,-39,81 3 0050 parenleft
+) 369,757,205,63,74,63 3 0051 parenright
+* 425,740,0,104,-120,81 2 0052 asterisk
++ 606,506,0,52,-42,52 0 0053 plus
+, 277,126,67,0,48 0 0054 comma
+- 332,315,0,78,-26,78 0 0055 hyphen
+hy "
+char173 "
+. 277,126,0,0,-52 0 0056 period
+/ 437,740,100,153,25,81 2 0057 slash
+sl "
+0 554,753,13,118,-21,81 2 0060 zero
+1 554,740,0,0,-210 2 0061 one
+2 554,753,0,111,10,81 2 0062 two
+3 554,753,13,61,-23,61 2 0063 three
+4 554,740,0,94,11,81 2 0064 four
+5 554,740,13,101,-19,81 2 0065 five
+6 554,739,13,76,-15,76 2 0066 six
+7 554,740,0,124,-60,81 2 0067 seven
+8 554,753,13,76,-27,76 2 0070 eight
+9 554,752,0,122,-61,81 2 0071 nine
+: 277,548,0,51,-52,51 0 0072 colon
+; 277,548,67,51,48,51 0 0073 semicolon
+< 606,514,8,93,-37,81 0 0074 less
+= 606,388,0,71,-23,71 0 0075 equal
+> 606,514,8,57,-1,57 0 0076 greater
+? 591,752,0,87,-108,81 2 0077 question
+@ 867,753,13,71,-76,71 2 0100 at
+at "
+A 740,740,0,39,38,39 2 0101 A
+B 574,740,0,82,-24,81 2 0102 B
+C 813,752,13,107,-55,81 2 0103 C
+D 744,740,0,79,-24,79 2 0104 D
+E 536,740,0,126,-20,81 2 0105 E
+F 485,740,0,146,-20,81 2 0106 F
+G 872,753,13,69,-53,69 2 0107 G
+H 683,740,0,111,-26,81 2 0110 H
+I 226,740,0,111,-26,81 2 0111 I
+J 482,740,13,107,13,81 2 0112 J
+K 591,740,0,187,-31,81 2 0113 K
+L 462,740,0,62,-32,62 2 0114 L
+M 919,740,0,111,-26,81 2 0115 M
+N 740,740,0,111,-25,81 2 0116 N
+O 869,753,13,82,-55,81 2 0117 O
+P 592,740,0,122,-25,81 2 0120 P
+Q 871,753,13,91,-52,81 2 0121 Q
+R 607,740,0,112,-20,81 2 0122 R
+S 498,753,13,113,-7,81 2 0123 S
+T 426,740,0,180,-81,81 2 0124 T
+U 655,740,13,111,-68,81 2 0125 U
+V 702,740,0,178,-95,81 2 0126 V
+W 960,740,0,177,-98,81 2 0127 W
+X 609,740,0,165,42,81 2 0130 X
+Y 592,740,0,187,-88,81 2 0131 Y
+Z 480,740,0,166,38,81 2 0132 Z
+[ 351,753,179,176,-95,81 2 0133 bracketleft
+lB "
+\ 605,740,100,0,-205 2 0134 backslash
+rs "
+] 351,753,179,11,69,11 2 0135 bracketright
+rB "
+a^ 502,764,0,94,-142,81 2 0136 circumflex
+^ "
+_ 500,0,125,36,73,36 0 0137 underscore
+` 351,740,0,57,-182,57 2 0140 quoteleft
+oq "
+a 683,561,13,89,-38,81 0 0141 a
+b 682,740,13,71,-18,71 2 0142 b
+c 647,561,13,81,-37,81 0 0143 c
+d 685,740,13,120,-35,81 2 0144 d
+e 650,561,13,64,-34,64 0 0145 e
+f 314,753,0,190,-54,81 2 0146 f
+g 673,561,215,84,-6,81 1 0147 g
+h 610,740,0,46,-12,46 2 0150 h
+i 200,740,0,122,-15,81 2 0151 i
+j 203,740,192,121,130,81 3 0152 j
+k 502,740,0,136,-20,81 2 0153 k
+l 200,740,0,122,-15,81 2 0154 l
+m 938,561,0,50,-16,50 0 0155 m
+n 610,561,0,49,-15,49 0 0156 n
+o 655,561,13,64,-38,64 0 0157 o
+p 682,561,192,67,22,67 1 0160 p
+q 682,561,192,85,-33,81 1 0161 q
+r 301,561,0,144,-15,81 0 0162 r
+s 388,561,13,86,1,81 0 0163 s
+t 339,740,0,142,-54,81 2 0164 t
+u 608,547,13,84,-50,81 0 0165 u
+v 554,547,0,143,-58,81 0 0166 v
+w 831,547,0,140,-64,81 0 0167 w
+x 480,547,0,139,38,81 0 0170 x
+y 536,547,192,138,-47,81 1 0171 y
+z 425,547,0,123,40,81 0 0172 z
+lC 351,740,189,167,-65,81 2 0173 braceleft
+{ "
+ba 672,740,100,0,-230 2 0174 bar
+| "
+rC 351,740,189,37,65,37 2 0175 braceright
+} "
+a~ 439,754,0,131,-129,81 2 0176 tilde
+~ "
+bq 354,126,68,0,-26 0 0200 quotesinglbase
+Fo 425,481,0,94,-42,81 0 0201 guillemotleft
+char171 "
+Fc 425,481,0,62,-10,62 0 0202 guillemotright
+char187 "
+bu 606,532,0,0,-167 0 0203 bullet
+Fn 554,818,153,165,89,81 2 0204 florin
+f/ 166,740,0,301,163,81 2 0205 fraction
+%0 1174,751,13,58,-78,58 2 0206 perthousand
+dg 553,740,133,90,-96,81 2 0207 dagger
+dd 553,740,133,90,-22,81 2 0210 daggerdbl
+en 500,315,0,73,-31,73 0 0211 endash
+em 1000,315,0,73,-31,73 0 0212 emdash
+fi 487,753,0,122,-54,81 2 0214 fi
+fl 485,753,0,122,-54,81 2 0215 fl
+.i 200,547,0,86,-15,81 0 0220 dotlessi
+ga 378,786,0,97,-154,81 2 0222 grave
+a" 552,800,0,92,-189,81 2 0223 hungarumlaut
+a. 222,765,0,118,-142,81 2 0224 dotaccent
+ab 453,754,0,138,-142,81 2 0225 breve
+ah 502,764,0,113,-160,81 2 0226 caron
+ao 332,807,0,119,-141,81 2 0227 ring
+ho 302,0,191,0,-3 1 0230 ogonek
+lq 502,740,0,55,-184,55 2 0231 quotedblleft
+rq 484,740,0,108,-147,81 2 0232 quotedblright
+oe 1137,561,13,73,-30,73 0 0233 oe
+/l 300,740,0,104,-45,81 2 0234 lslash
+Bq 502,126,68,0,-26 0 0235 quotedblbase
+OE 1194,753,13,135,-57,81 2 0236 OE
+/L 517,740,0,62,-57,62 2 0237 Lslash
+r! 295,548,192,41,-24,41 1 0241 exclamdown
+char161 "
+ct 554,707,0,92,-65,81 0 0242 cent
+char162 "
+Po 554,753,0,110,21,81 2 0243 sterling
+char163 "
+Cs 554,580,0,141,26,81 0 0244 currency
+char164 "
+Ye 554,740,0,183,-25,81 2 0245 yen
+char165 "
+bb 672,740,100,0,-230 2 0246 brokenbar
+char166 "
+sc 615,753,141,32,-68,32 2 0247 section
+char167 "
+ad 369,765,0,118,-141,81 2 0250 dieresis
+char168 "
+co 747,752,12,133,-3,81 2 0251 copyright
+char169 "
+Of 369,753,0,175,-52,81 2 0252 ordfeminine
+char170 "
+fo 251,481,0,94,-42,81 0 0253 guilsinglleft
+no 606,388,0,71,-60,71 0 0254 logicalnot
+char172 "
+\- 606,287,0,52,-42,52 0 0255 minus
+rg 747,752,12,133,-3,81 2 0256 registered
+char174 "
+a- 485,736,0,112,-147,81 0 0257 macron
+char175 "
+de 400,709,0,101,-108,81 0 0260 degree
+char176 "
+char177 606,518,24,62,3,62 0 0261 plusminus
+S2 332,747,0,151,-24,81 2 0262 twosuperior
+char178 "
+S3 332,747,0,126,-48,81 2 0263 threesuperior
+char179 "
+aa 375,786,0,119,-153,81 2 0264 acute
+char180 "
+char181 608,547,184,70,4,70 0 0265 mu
+ps 564,740,110,174,-69,81 2 0266 paragraph
+char182 "
+char183 277,316,0,8,-87,8 0 0267 periodcentered
+ac 324,0,222,0,-2 1 0270 cedilla
+char184 "
+S1 332,740,0,53,-140,53 2 0271 onesuperior
+char185 "
+Om 369,753,0,147,-66,81 2 0272 ordmasculine
+char186 "
+fc 251,481,0,62,-10,62 0 0273 guilsinglright
+14 831,740,0,0,-133 2 0274 onequarter
+char188 "
+12 831,740,0,29,-114,29 2 0275 onehalf
+char189 "
+34 831,747,0,44,-76,44 2 0276 threequarters
+char190 "
+r? 591,548,205,0,-14 1 0277 questiondown
+char191 "
+`A 740,949,0,39,38,39 2 0300 Agrave
+char192 "
+'A 740,949,0,39,38,39 2 0301 Aacute
+char193 "
+^A 740,927,0,39,38,39 2 0302 Acircumflex
+char194 "
+~A 740,917,0,39,38,39 2 0303 Atilde
+char195 "
+:A 740,928,0,39,38,39 2 0304 Adieresis
+char196 "
+oA 740,955,0,39,38,39 2 0305 Aring
+char197 "
+AE 992,740,0,102,70,81 2 0306 AE
+char198 "
+,C 813,752,222,107,-55,81 3 0307 Ccedilla
+char199 "
+`E 536,949,0,126,-20,81 2 0310 Egrave
+char200 "
+'E 536,949,0,126,-20,81 2 0311 Eacute
+char201 "
+^E 536,927,0,126,-20,81 2 0312 Ecircumflex
+char202 "
+:E 536,928,0,126,-20,81 2 0313 Edieresis
+char203 "
+`I 226,949,0,164,-26,81 2 0314 Igrave
+char204 "
+'I 226,949,0,264,-26,81 2 0315 Iacute
+char205 "
+^I 226,927,0,263,-26,81 2 0316 Icircumflex
+char206 "
+:I 226,928,0,220,-26,81 2 0317 Idieresis
+char207 "
+-D 790,740,0,73,-54,73 2 0320 Eth
+char208 "
+~N 740,917,0,111,-25,81 2 0321 Ntilde
+char209 "
+`O 869,949,13,82,-55,81 2 0322 Ograve
+char210 "
+'O 869,949,13,82,-55,81 2 0323 Oacute
+char211 "
+^O 869,927,13,82,-55,81 2 0324 Ocircumflex
+char212 "
+~O 869,917,13,82,-55,81 2 0325 Otilde
+char213 "
+:O 869,928,13,82,-55,81 2 0326 Odieresis
+char214 "
+char215 606,482,0,56,-37,56 0 0327 multiply
+/O 868,819,83,111,-26,81 2 0330 Oslash
+char216 "
+`U 655,949,13,111,-68,81 2 0331 Ugrave
+char217 "
+'U 655,949,13,111,-68,81 2 0332 Uacute
+char218 "
+^U 655,927,13,111,-68,81 2 0333 Ucircumflex
+char219 "
+:U 655,928,13,111,-68,81 2 0334 Udieresis
+char220 "
+'Y 592,949,0,187,-88,81 2 0335 Yacute
+char221 "
+TP 592,740,0,79,-10,79 2 0336 Thorn
+char222 "
+ss 554,753,13,74,-11,74 2 0337 germandbls
+char223 "
+`a 683,786,13,89,-38,81 2 0340 agrave
+char224 "
+'a 683,786,13,89,-38,81 2 0341 aacute
+char225 "
+^a 683,764,13,89,-38,81 2 0342 acircumflex
+char226 "
+~a 683,754,13,89,-38,81 2 0343 atilde
+char227 "
+:a 683,765,13,89,-38,81 2 0344 adieresis
+char228 "
+oa 683,807,13,89,-38,81 2 0345 aring
+char229 "
+ae 1157,561,13,62,-30,62 0 0346 ae
+char230 "
+,c 647,561,222,81,-37,81 1 0347 ccedilla
+char231 "
+`e 650,786,13,64,-34,64 2 0350 egrave
+char232 "
+'e 650,786,13,64,-34,64 2 0351 eacute
+char233 "
+^e 650,764,13,64,-34,64 2 0352 ecircumflex
+char234 "
+:e 650,765,13,64,-34,64 2 0353 edieresis
+char235 "
+`i 200,786,0,146,-15,81 2 0354 igrave
+char236 "
+'i 200,786,0,247,-15,81 2 0355 iacute
+char237 "
+^i 200,764,0,245,9,81 2 0356 icircumflex
+char238 "
+:i 200,765,0,203,-15,81 2 0357 idieresis
+char239 "
+Sd 655,753,12,70,-38,70 2 0360 eth
+char240 "
+~n 610,754,0,49,-15,49 2 0361 ntilde
+char241 "
+`o 655,786,13,64,-38,64 2 0362 ograve
+char242 "
+'o 655,786,13,64,-38,64 2 0363 oacute
+char243 "
+^o 655,764,13,64,-38,64 2 0364 ocircumflex
+char244 "
+~o 655,754,13,64,-38,64 2 0365 otilde
+char245 "
+:o 655,765,13,64,-38,64 2 0366 odieresis
+char246 "
+char247 606,519,13,52,-42,52 0 0367 divide
+/o 653,614,64,100,-1,81 0 0370 oslash
+char248 "
+`u 608,786,13,84,-50,81 2 0371 ugrave
+char249 "
+'u 608,786,13,84,-50,81 2 0372 uacute
+char250 "
+^u 608,764,13,84,-50,81 2 0373 ucircumflex
+char251 "
+:u 608,765,13,84,-50,81 2 0374 udieresis
+char252 "
+'y 536,786,192,138,-47,81 3 0375 yacute
+char253 "
+Tp 682,740,192,67,22,67 3 0376 thorn
+char254 "
+:y 536,765,192,138,-47,81 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/AR b/gnu/usr.bin/groff/devices/devps/AR
new file mode 100644
index 000000000000..00fd6320b16b
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/AR
@@ -0,0 +1,558 @@
+name AR
+internalname AvantGarde-Book
+spacewidth 277
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -62
+A w -65
+A v -70
+A u -20
+A ' -100
+A rq -100
+A Y -92
+A W -60
+A V -102
+A U -40
+A T -45
+A Q -40
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -30
+D W -10
+D V -50
+D A -50
+F . -160
+F e -20
+F , -180
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -20
+J . -15
+J a -20
+J A -30
+K o -15
+K e -20
+K O -20
+L y -23
+L ' -130
+L rq -130
+L Y -91
+L W -67
+L V -113
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -60
+O T -30
+O A -60
+P . -300
+P o -60
+P e -20
+P , -280
+P a -20
+P A -114
+Q , 20
+R Y -10
+R W 10
+R V -10
+R T 6
+S , 20
+T y -50
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -70
+T i 10
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -90
+T O -30
+T A -45
+U . -20
+U , -20
+U A -40
+V u -40
+V ; -33
+V . -165
+V o -101
+V i -5
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -104
+V O -60
+V G -20
+V A -102
+W y -2
+W u -30
+W ; -33
+W . -106
+W o -46
+W i 6
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -175
+Y o -89
+Y - -85
+Y hy -85
+Y char173 -85
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -92
+a p 20
+a b 20
+b y -20
+b v -20
+c y -20
+c k -15
+, ' -120
+, rq -120
+e y -20
+e w -20
+e v -20
+f . -50
+f o -40
+f l -30
+f i -34
+f f -60
+f e -20
+f .i -34
+f , -50
+f a -40
+g a -15
+h y -30
+k y -5
+k e -15
+m y -20
+m u -20
+m a -20
+n y -15
+n v -20
+o y -20
+o x -15
+o w -20
+o v -30
+p y -20
+. ' -120
+. rq -120
+lq ` -35
+lq oq -35
+lq A -100
+` ` -203
+` oq -203
+oq ` -203
+oq oq -203
+` A -100
+oq A -100
+' v -30
+' t 10
+' s -15
+' r -20
+' ' -203
+' rq -35
+' d -110
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -20
+r n 21
+r m 28
+r l 20
+r k 20
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g -15
+r e -4
+r d -6
+r , -75
+r c -20
+r a -20
+s . 20
+s , 20
+v . -130
+v o -30
+v e -20
+v , -100
+v a -30
+w . -100
+w o -30
+w h 15
+w e -20
+w , -90
+w a -30
+y . -125
+y o -30
+y e -20
+y , -110
+y a -30
+charset
+ha 606,740 2 0000 asciicircum
+ti 606,319 0 0001 asciitilde
+vS 498,927,13 2 0002 Scaron
+vZ 480,927 2 0003 Zcaron
+vs 388,764,13 2 0004 scaron
+vz 425,764 2 0005 zcaron
+:Y 592,928 2 0006 Ydieresis
+tm 1000,740 2 0007 trademark
+aq 198,740 2 0010 quotesingle
+space 277 0 0040
+! 295,740 2 0041 exclam
+" 309,740 2 0042 quotedbl
+# 554,740 2 0043 numbersign
+sh "
+$ 554,811,70 2 0044 dollar
+Do "
+% 775,751,13 2 0045 percent
+& 757,753,12 2 0046 ampersand
+' 351,740 2 0047 quoteright
+( 369,757,205 3 0050 parenleft
+) 369,757,205 3 0051 parenright
+* 425,740 2 0052 asterisk
++ 606,506 0 0053 plus
+, 277,126,67 0 0054 comma
+- 332,315 0 0055 hyphen
+hy "
+char173 "
+. 277,126 0 0056 period
+/ 437,740,100 2 0057 slash
+sl "
+0 554,753,13 2 0060 zero
+1 554,740 2 0061 one
+2 554,753 2 0062 two
+3 554,753,13 2 0063 three
+4 554,740 2 0064 four
+5 554,740,13 2 0065 five
+6 554,739,13 2 0066 six
+7 554,740 2 0067 seven
+8 554,753,13 2 0070 eight
+9 554,752 2 0071 nine
+: 277,548 0 0072 colon
+; 277,548,67 0 0073 semicolon
+< 606,514,8 0 0074 less
+= 606,388 0 0075 equal
+> 606,514,8 0 0076 greater
+? 591,752 2 0077 question
+@ 867,753,13 2 0100 at
+at "
+A 740,740 2 0101 A
+B 574,740 2 0102 B
+C 813,752,13 2 0103 C
+D 744,740 2 0104 D
+E 536,740 2 0105 E
+F 485,740 2 0106 F
+G 872,753,13 2 0107 G
+H 683,740 2 0110 H
+I 226,740 2 0111 I
+J 482,740,13 2 0112 J
+K 591,740 2 0113 K
+L 462,740 2 0114 L
+M 919,740 2 0115 M
+N 740,740 2 0116 N
+O 869,753,13 2 0117 O
+P 592,740 2 0120 P
+Q 871,753,13 2 0121 Q
+R 607,740 2 0122 R
+S 498,753,13 2 0123 S
+T 426,740 2 0124 T
+U 655,740,13 2 0125 U
+V 702,740 2 0126 V
+W 960,740 2 0127 W
+X 609,740 2 0130 X
+Y 592,740 2 0131 Y
+Z 480,740 2 0132 Z
+[ 351,753,179 2 0133 bracketleft
+lB "
+\ 605,740,100 2 0134 backslash
+rs "
+] 351,753,179 2 0135 bracketright
+rB "
+a^ 502,764 2 0136 circumflex
+^ "
+_ 500,0,125 0 0137 underscore
+` 351,740 2 0140 quoteleft
+oq "
+a 683,561,13 0 0141 a
+b 682,740,13 2 0142 b
+c 647,561,13 0 0143 c
+d 685,740,13 2 0144 d
+e 650,561,13 0 0145 e
+f 314,753 2 0146 f
+g 673,561,215 1 0147 g
+h 610,740 2 0150 h
+i 200,740 2 0151 i
+j 203,740,192 3 0152 j
+k 502,740 2 0153 k
+l 200,740 2 0154 l
+m 938,561 0 0155 m
+n 610,561 0 0156 n
+o 655,561,13 0 0157 o
+p 682,561,192 1 0160 p
+q 682,561,192 1 0161 q
+r 301,561 0 0162 r
+s 388,561,13 0 0163 s
+t 339,740 2 0164 t
+u 608,547,13 0 0165 u
+v 554,547 0 0166 v
+w 831,547 0 0167 w
+x 480,547 0 0170 x
+y 536,547,192 1 0171 y
+z 425,547 0 0172 z
+lC 351,740,189 2 0173 braceleft
+{ "
+ba 672,740,100 2 0174 bar
+| "
+rC 351,740,189 2 0175 braceright
+} "
+a~ 439,754 2 0176 tilde
+~ "
+bq 354,126,68 0 0200 quotesinglbase
+Fo 425,481 0 0201 guillemotleft
+char171 "
+Fc 425,481 0 0202 guillemotright
+char187 "
+bu 606,532 0 0203 bullet
+Fn 554,818,153 2 0204 florin
+f/ 166,740 2 0205 fraction
+%0 1174,751,13 2 0206 perthousand
+dg 553,740,133 2 0207 dagger
+dd 553,740,133 2 0210 daggerdbl
+en 500,315 0 0211 endash
+em 1000,315 0 0212 emdash
+fi 487,753 2 0214 fi
+fl 485,753 2 0215 fl
+.i 200,547 0 0220 dotlessi
+ga 378,786 2 0222 grave
+a" 552,800 2 0223 hungarumlaut
+a. 222,765 2 0224 dotaccent
+ab 453,754 2 0225 breve
+ah 502,764 2 0226 caron
+ao 332,807 2 0227 ring
+ho 302,0,191 1 0230 ogonek
+lq 502,740 2 0231 quotedblleft
+rq 484,740 2 0232 quotedblright
+oe 1137,561,13 0 0233 oe
+/l 300,740 2 0234 lslash
+Bq 502,126,68 0 0235 quotedblbase
+OE 1194,753,13 2 0236 OE
+/L 517,740 2 0237 Lslash
+r! 295,548,192 1 0241 exclamdown
+char161 "
+ct 554,707 0 0242 cent
+char162 "
+Po 554,753 2 0243 sterling
+char163 "
+Cs 554,580 0 0244 currency
+char164 "
+Ye 554,740 2 0245 yen
+char165 "
+bb 672,740,100 2 0246 brokenbar
+char166 "
+sc 615,753,141 2 0247 section
+char167 "
+ad 369,765 2 0250 dieresis
+char168 "
+co 747,752,12 2 0251 copyright
+char169 "
+Of 369,753 2 0252 ordfeminine
+char170 "
+fo 251,481 0 0253 guilsinglleft
+no 606,388 0 0254 logicalnot
+char172 "
+\- 606,287 0 0255 minus
+rg 747,752,12 2 0256 registered
+char174 "
+a- 485,736 0 0257 macron
+char175 "
+de 400,709 0 0260 degree
+char176 "
+char177 606,518,24 0 0261 plusminus
+S2 332,747 2 0262 twosuperior
+char178 "
+S3 332,747 2 0263 threesuperior
+char179 "
+aa 375,786 2 0264 acute
+char180 "
+char181 608,547,184 0 0265 mu
+ps 564,740,110 2 0266 paragraph
+char182 "
+char183 277,316 0 0267 periodcentered
+ac 324,0,222 1 0270 cedilla
+char184 "
+S1 332,740 2 0271 onesuperior
+char185 "
+Om 369,753 2 0272 ordmasculine
+char186 "
+fc 251,481 0 0273 guilsinglright
+14 831,740 2 0274 onequarter
+char188 "
+12 831,740 2 0275 onehalf
+char189 "
+34 831,747 2 0276 threequarters
+char190 "
+r? 591,548,205 1 0277 questiondown
+char191 "
+`A 740,949 2 0300 Agrave
+char192 "
+'A 740,949 2 0301 Aacute
+char193 "
+^A 740,927 2 0302 Acircumflex
+char194 "
+~A 740,917 2 0303 Atilde
+char195 "
+:A 740,928 2 0304 Adieresis
+char196 "
+oA 740,955 2 0305 Aring
+char197 "
+AE 992,740 2 0306 AE
+char198 "
+,C 813,752,222 3 0307 Ccedilla
+char199 "
+`E 536,949 2 0310 Egrave
+char200 "
+'E 536,949 2 0311 Eacute
+char201 "
+^E 536,927 2 0312 Ecircumflex
+char202 "
+:E 536,928 2 0313 Edieresis
+char203 "
+`I 226,949 2 0314 Igrave
+char204 "
+'I 226,949 2 0315 Iacute
+char205 "
+^I 226,927 2 0316 Icircumflex
+char206 "
+:I 226,928 2 0317 Idieresis
+char207 "
+-D 790,740 2 0320 Eth
+char208 "
+~N 740,917 2 0321 Ntilde
+char209 "
+`O 869,949,13 2 0322 Ograve
+char210 "
+'O 869,949,13 2 0323 Oacute
+char211 "
+^O 869,927,13 2 0324 Ocircumflex
+char212 "
+~O 869,917,13 2 0325 Otilde
+char213 "
+:O 869,928,13 2 0326 Odieresis
+char214 "
+char215 606,482 0 0327 multiply
+/O 868,819,83 2 0330 Oslash
+char216 "
+`U 655,949,13 2 0331 Ugrave
+char217 "
+'U 655,949,13 2 0332 Uacute
+char218 "
+^U 655,927,13 2 0333 Ucircumflex
+char219 "
+:U 655,928,13 2 0334 Udieresis
+char220 "
+'Y 592,949 2 0335 Yacute
+char221 "
+TP 592,740 2 0336 Thorn
+char222 "
+ss 554,753,13 2 0337 germandbls
+char223 "
+`a 683,786,13 2 0340 agrave
+char224 "
+'a 683,786,13 2 0341 aacute
+char225 "
+^a 683,764,13 2 0342 acircumflex
+char226 "
+~a 683,754,13 2 0343 atilde
+char227 "
+:a 683,765,13 2 0344 adieresis
+char228 "
+oa 683,807,13 2 0345 aring
+char229 "
+ae 1157,561,13 0 0346 ae
+char230 "
+,c 647,561,222 1 0347 ccedilla
+char231 "
+`e 650,786,13 2 0350 egrave
+char232 "
+'e 650,786,13 2 0351 eacute
+char233 "
+^e 650,764,13 2 0352 ecircumflex
+char234 "
+:e 650,765,13 2 0353 edieresis
+char235 "
+`i 200,786 2 0354 igrave
+char236 "
+'i 200,786 2 0355 iacute
+char237 "
+^i 200,764 2 0356 icircumflex
+char238 "
+:i 200,765 2 0357 idieresis
+char239 "
+Sd 655,753,12 2 0360 eth
+char240 "
+~n 610,754 2 0361 ntilde
+char241 "
+`o 655,786,13 2 0362 ograve
+char242 "
+'o 655,786,13 2 0363 oacute
+char243 "
+^o 655,764,13 2 0364 ocircumflex
+char244 "
+~o 655,754,13 2 0365 otilde
+char245 "
+:o 655,765,13 2 0366 odieresis
+char246 "
+char247 606,519,13 0 0367 divide
+/o 653,614,64 0 0370 oslash
+char248 "
+`u 608,786,13 2 0371 ugrave
+char249 "
+'u 608,786,13 2 0372 uacute
+char250 "
+^u 608,764,13 2 0373 ucircumflex
+char251 "
+:u 608,765,13 2 0374 udieresis
+char252 "
+'y 536,786,192 3 0375 yacute
+char253 "
+Tp 682,740,192 3 0376 thorn
+char254 "
+:y 536,765,192 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/BMB b/gnu/usr.bin/groff/devices/devps/BMB
new file mode 100644
index 000000000000..270f7db5623f
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/BMB
@@ -0,0 +1,438 @@
+name BMB
+internalname Bookman-Demi
+spacewidth 340
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -1
+A w -9
+A v -8
+A Y -52
+A W -20
+A V -68
+A T -40
+F . -132
+F , -130
+F A -59
+L y 19
+L Y -35
+L W -41
+L V -50
+L T -4
+P . -128
+P , -129
+P A -46
+R y -8
+R Y -20
+R W -24
+R V -29
+R T -4
+T ; 5
+T s -10
+T r 27
+T . -122
+T o -28
+T i 27
+T - -10
+T hy -10
+T char173 -10
+T e -29
+T , -122
+T : 7
+T c -29
+T a -24
+T A -42
+V y 12
+V u -11
+V ; -38
+V r -15
+V . -105
+V o -79
+V i 15
+V - -10
+V hy -10
+V char173 -10
+V e -80
+V , -103
+V : -37
+V a -74
+V A -88
+W y 12
+W u -11
+W ; -38
+W r -15
+W . -105
+W o -78
+W i 15
+W - -10
+W hy -10
+W char173 -10
+W e -79
+W , -103
+W : -37
+W a -73
+W A -60
+Y v 24
+Y u -13
+Y ; -34
+Y q -66
+Y . -105
+Y p -23
+Y o -66
+Y i 2
+Y - -10
+Y hy -10
+Y char173 -10
+Y e -67
+Y , -103
+Y : -32
+Y a -60
+Y A -56
+f f 21
+r q -9
+r . -102
+r o -9
+r n 20
+r m 20
+r - -10
+r hy -10
+r char173 -10
+r h -23
+r g -9
+r f 20
+r e -10
+r d -10
+r , -101
+r c -9
+charset
+ha 600,681 2 0000 asciicircum
+ti 600,368 0 0001 asciitilde
+vS 660,896,17 2 0002 Scaron
+vZ 640,896 2 0003 Zcaron
+vs 520,717,8 2 0004 scaron
+vz 560,717 2 0005 zcaron
+:Y 700,877 2 0006 Ydieresis
+tm 980,681 2 0007 trademark
+aq 240,698 2 0010 quotesingle
+space 340 0 0040
+! 360,698,8 2 0041 exclam
+" 420,698 2 0042 quotedbl
+# 660,681 2 0043 numbersign
+sh "
+$ 660,805,119 2 0044 dollar
+Do "
+% 940,698,8 2 0045 percent
+& 800,698,17 2 0046 ampersand
+' 320,698 2 0047 quoteright
+( 320,749,150 2 0050 parenleft
+) 320,749,150 2 0051 parenright
+* 460,697 2 0052 asterisk
++ 600,514 0 0053 plus
+, 340,162,124 0 0054 comma
+- 360,318 0 0055 hyphen
+hy "
+char173 "
+. 340,172,8 0 0056 period
+/ 600,725,149 2 0057 slash
+sl "
+0 660,698,17 2 0060 zero
+1 660,681 2 0061 one
+2 660,698 2 0062 two
+3 660,698,17 2 0063 three
+4 660,681 2 0064 four
+5 660,723,17 2 0065 five
+6 660,698,17 2 0066 six
+7 660,681 2 0067 seven
+8 660,698,17 2 0070 eight
+9 660,698,17 2 0071 nine
+: 340,515,8 0 0072 colon
+; 340,515,124 0 0073 semicolon
+< 600,542,9 0 0074 less
+= 600,421 0 0075 equal
+> 600,542,9 0 0076 greater
+? 660,698,8 2 0077 question
+@ 820,698,17 2 0100 at
+at "
+A 720,681 2 0101 A
+B 720,681 2 0102 B
+C 740,698,17 2 0103 C
+D 780,681 2 0104 D
+E 720,681 2 0105 E
+F 680,681 2 0106 F
+G 780,698,17 2 0107 G
+H 820,681 2 0110 H
+I 400,681 2 0111 I
+J 640,681,17 2 0112 J
+K 800,681 2 0113 K
+L 640,681 2 0114 L
+M 940,681 2 0115 M
+N 740,681 2 0116 N
+O 800,698,17 2 0117 O
+P 660,681 2 0120 P
+Q 800,698,226 3 0121 Q
+R 780,681 2 0122 R
+S 660,698,17 2 0123 S
+T 700,681 2 0124 T
+U 740,681,17 2 0125 U
+V 720,681 2 0126 V
+W 940,681 2 0127 W
+X 780,681 2 0130 X
+Y 700,681 2 0131 Y
+Z 640,681 2 0132 Z
+[ 300,725,138 2 0133 bracketleft
+lB "
+\ 600,725 2 0134 backslash
+rs "
+] 300,725,138 2 0135 bracketright
+rB "
+a^ 500,731 2 0136 circumflex
+^ "
+_ 500,0,155 0 0137 underscore
+` 320,698 2 0140 quoteleft
+oq "
+a 580,515,8 0 0141 a
+b 600,725,8 2 0142 b
+c 580,515,8 0 0143 c
+d 640,725,8 2 0144 d
+e 580,515,8 0 0145 e
+f 380,741 2 0146 f
+g 580,595,243 1 0147 g
+h 680,725 2 0150 h
+i 360,729 2 0151 i
+j 340,729,221 3 0152 j
+k 660,725 2 0153 k
+l 340,725 2 0154 l
+m 1000,515 0 0155 m
+n 680,515 0 0156 n
+o 620,515,8 0 0157 o
+p 640,515,212 1 0160 p
+q 620,515,212 1 0161 q
+r 460,502 0 0162 r
+s 520,515,8 0 0163 s
+t 460,660,8 2 0164 t
+u 660,502,8 0 0165 u
+v 600,502 0 0166 v
+w 800,502 0 0167 w
+x 600,502 0 0170 x
+y 620,502,221 1 0171 y
+z 560,502 0 0172 z
+lC 320,726,139 2 0173 braceleft
+{ "
+ba 600,725 2 0174 bar
+| "
+rC 320,726,139 2 0175 braceright
+} "
+a~ 480,691 2 0176 tilde
+~ "
+bq 320,144,114 0 0200 quotesinglbase
+Fo 400,457 0 0201 guillemotleft
+char171 "
+Fc 400,457 0 0202 guillemotright
+char187 "
+bu 460,511 0 0203 bullet
+Fn 660,749,209 2 0204 florin
+f/ 120,681 2 0205 fraction
+%0 1360,698,8 2 0206 perthousand
+dg 440,698,156 2 0207 dagger
+dd 380,698,156 2 0210 daggerdbl
+en 500,318 0 0211 endash
+em 1000,318 0 0212 emdash
+fi 740,741 2 0214 fi
+fl 740,741 2 0215 fl
+.i 360,502 0 0220 dotlessi
+ga 400,730 2 0222 grave
+a" 440,741 2 0223 hungarumlaut
+a. 320,730 2 0224 dotaccent
+ab 500,722 2 0225 breve
+ah 500,717 2 0226 caron
+ao 340,755 2 0227 ring
+ho 320,0,163 0 0230 ogonek
+lq 540,698 2 0231 quotedblleft
+rq 540,698 2 0232 quotedblright
+oe 940,515,8 0 0233 oe
+/l 340,725 2 0234 lslash
+Bq 540,144,114 0 0235 quotedblbase
+OE 1220,698,17 2 0236 OE
+/L 640,681 2 0237 Lslash
+r! 360,515,191 0 0241 exclamdown
+char161 "
+ct 660,674 2 0242 cent
+char162 "
+Po 660,698,17 2 0243 sterling
+char163 "
+Cs 660,593 0 0244 currency
+char164 "
+Ye 660,681 2 0245 yen
+char165 "
+bb 600,725 2 0246 brokenbar
+char166 "
+sc 600,698,153 2 0247 section
+char167 "
+ad 500,698 2 0250 dieresis
+char168 "
+co 740,698,17 2 0251 copyright
+char169 "
+Of 400,698 2 0252 ordfeminine
+char170 "
+fo 220,457 0 0253 guilsinglleft
+no 600,421 0 0254 logicalnot
+char172 "
+\- 600,323 0 0255 minus
+rg 740,698,17 2 0256 registered
+char174 "
+a- 460,663 2 0257 macron
+char175 "
+de 400,698 2 0260 degree
+char176 "
+char177 600,514 0 0261 plusminus
+S2 396,698 2 0262 twosuperior
+char178 "
+S3 396,698 2 0263 threesuperior
+char179 "
+aa 400,731 2 0264 acute
+char180 "
+char181 660,502,221 1 0265 mu
+ps 800,681,101 2 0266 paragraph
+char182 "
+char183 340,355 0 0267 periodcentered
+ac 360,0,213 1 0270 cedilla
+char184 "
+S1 396,687 2 0271 onesuperior
+char185 "
+Om 400,698 2 0272 ordmasculine
+char186 "
+fc 220,457 0 0273 guilsinglright
+14 990,681 2 0274 onequarter
+char188 "
+12 990,681 2 0275 onehalf
+char189 "
+34 990,692 2 0276 threequarters
+char190 "
+r? 660,515,191 0 0277 questiondown
+char191 "
+`A 720,909 2 0300 Agrave
+char192 "
+'A 720,910 2 0301 Aacute
+char193 "
+^A 720,910 2 0302 Acircumflex
+char194 "
+~A 720,870 2 0303 Atilde
+char195 "
+:A 720,877 2 0304 Adieresis
+char196 "
+oA 720,934 2 0305 Aring
+char197 "
+AE 1140,681 2 0306 AE
+char198 "
+,C 740,698,213 3 0307 Ccedilla
+char199 "
+`E 720,909 2 0310 Egrave
+char200 "
+'E 720,910 2 0311 Eacute
+char201 "
+^E 720,910 2 0312 Ecircumflex
+char202 "
+:E 720,877 2 0313 Edieresis
+char203 "
+`I 400,909 2 0314 Igrave
+char204 "
+'I 400,910 2 0315 Iacute
+char205 "
+^I 400,910 2 0316 Icircumflex
+char206 "
+:I 400,877 2 0317 Idieresis
+char207 "
+-D 780,681 2 0320 Eth
+char208 "
+~N 740,870 2 0321 Ntilde
+char209 "
+`O 800,909,17 2 0322 Ograve
+char210 "
+'O 800,910,17 2 0323 Oacute
+char211 "
+^O 800,910,17 2 0324 Ocircumflex
+char212 "
+~O 800,870,17 2 0325 Otilde
+char213 "
+:O 800,877,17 2 0326 Odieresis
+char214 "
+char215 600,514 0 0327 multiply
+/O 800,781,110 2 0330 Oslash
+char216 "
+`U 740,909,17 2 0331 Ugrave
+char217 "
+'U 740,910,17 2 0332 Uacute
+char218 "
+^U 740,910,17 2 0333 Ucircumflex
+char219 "
+:U 740,877,17 2 0334 Udieresis
+char220 "
+'Y 700,910 2 0335 Yacute
+char221 "
+TP 660,681 2 0336 Thorn
+char222 "
+ss 660,699,91 2 0337 germandbls
+char223 "
+`a 580,730,8 2 0340 agrave
+char224 "
+'a 580,731,8 2 0341 aacute
+char225 "
+^a 580,731,8 2 0342 acircumflex
+char226 "
+~a 580,691,8 2 0343 atilde
+char227 "
+:a 580,698,8 2 0344 adieresis
+char228 "
+oa 580,755,8 2 0345 aring
+char229 "
+ae 880,515,8 0 0346 ae
+char230 "
+,c 580,515,213 1 0347 ccedilla
+char231 "
+`e 580,730,8 2 0350 egrave
+char232 "
+'e 580,731,8 2 0351 eacute
+char233 "
+^e 580,731,8 2 0352 ecircumflex
+char234 "
+:e 580,698,8 2 0353 edieresis
+char235 "
+`i 360,730 2 0354 igrave
+char236 "
+'i 360,731 2 0355 iacute
+char237 "
+^i 360,731 2 0356 icircumflex
+char238 "
+:i 360,698 2 0357 idieresis
+char239 "
+Sd 620,741,8 2 0360 eth
+char240 "
+~n 680,691 2 0361 ntilde
+char241 "
+`o 620,730,8 2 0362 ograve
+char242 "
+'o 620,731,8 2 0363 oacute
+char243 "
+^o 620,731,8 2 0364 ocircumflex
+char244 "
+~o 620,691,8 2 0365 otilde
+char245 "
+:o 620,698,8 2 0366 odieresis
+char246 "
+char247 600,521 0 0367 divide
+/o 620,551,40 0 0370 oslash
+char248 "
+`u 660,730,8 2 0371 ugrave
+char249 "
+'u 660,731,8 2 0372 uacute
+char250 "
+^u 660,731,8 2 0373 ucircumflex
+char251 "
+:u 660,698,8 2 0374 udieresis
+char252 "
+'y 620,731,221 3 0375 yacute
+char253 "
+Tp 640,725,212 3 0376 thorn
+char254 "
+:y 620,698,221 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/BMBI b/gnu/usr.bin/groff/devices/devps/BMBI
new file mode 100644
index 000000000000..0670451a9a50
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/BMBI
@@ -0,0 +1,441 @@
+name BMBI
+internalname Bookman-DemiItalic
+slant 10
+spacewidth 340
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y 20
+A w 20
+A v 20
+A Y -25
+A W -35
+A V -40
+A T -17
+F . -105
+F , -98
+F A -35
+L y 62
+L Y -5
+L W -15
+L V -19
+L T -26
+P . -105
+P , -98
+P A -31
+R y 27
+R Y 4
+R W -4
+R V -8
+R T -3
+T y 56
+T w 69
+T u 42
+T ; 31
+T s -1
+T r 41
+T . -107
+T o -5
+T i 42
+T - -20
+T hy -20
+T char173 -20
+T e -10
+T , -100
+T : 26
+T c -8
+T a -8
+T A -42
+V y 17
+V u -1
+V ; -22
+V r 2
+V . -115
+V o -50
+V i 32
+V - -20
+V hy -20
+V char173 -20
+V e -50
+V , -137
+V : -28
+V a -50
+V A -50
+W y -51
+W u -69
+W ; -81
+W r -66
+W . -183
+W o -100
+W i -36
+W - -22
+W hy -22
+W char173 -22
+W e -100
+W , -201
+W : -86
+W a -100
+W A -77
+Y v 26
+Y u -1
+Y ; -4
+Y q -43
+Y . -113
+Y o -41
+Y i 20
+Y - -20
+Y hy -20
+Y char173 -20
+Y e -46
+Y , -106
+Y : -9
+Y a -45
+Y A -30
+f f 10
+r q -3
+r . -120
+r o -1
+r n 39
+r m 39
+r - -20
+r hy -20
+r char173 -20
+r h -35
+r g -23
+r f 42
+r e -6
+r d -3
+r , -113
+r c -5
+charset
+ha 620,681,0,24,-42,24 2 0000 asciicircum
+ti 620,368,0,35,-51,35 0 0001 asciitilde
+vS 700,915,17,81,-9,73 2 0002 Scaron
+vZ 680,915,0,110,27,73 2 0003 Zcaron
+vs 540,749,8,83,18,73 2 0004 scaron
+vz 560,749,8,76,14,73 2 0005 zcaron
+:Y 660,900,0,207,-22,73 2 0006 Ydieresis
+tm 940,681,0,92,8,73 2 0007 trademark
+aq 180,696,0,165,-76,73 2 0010 quotesingle
+space 340 0 0040
+! 320,698,8,96,-36,73 2 0041 exclam
+" 380,697,0,177,-90,73 2 0042 quotedbl
+# 680,681,0,19,-107,19 2 0043 numbersign
+sh "
+$ 680,790,164,67,5,67 2 0044 dollar
+Do "
+% 880,698,17,69,-56,69 2 0045 percent
+& 980,698,17,86,2,73 2 0046 ampersand
+' 320,698,0,79,-121,73 2 0047 quoteright
+( 260,741,134,178,19,73 2 0050 parenleft
+) 260,741,134,112,85,73 2 0051 parenright
+* 460,698,0,98,-76,73 2 0052 asterisk
++ 600,514,0,45,-41,45 0 0053 plus
+, 340,185,124,8,-50,8 0 0054 comma
+- 280,313,0,89,-9,73 0 0055 hyphen
+hy "
+char173 "
+. 340,177,8,6,-56,6 0 0056 period
+/ 360,742,106,192,41,73 2 0057 slash
+sl "
+0 680,698,17,73,-37,73 2 0060 zero
+1 680,681,0,0,-73 2 0061 one
+2 680,698,0,44,-17,44 2 0062 two
+3 680,698,17,53,-22,53 2 0063 three
+4 680,681,0,78,-13,73 2 0064 four
+5 680,681,17,39,-28,39 2 0065 five
+6 680,698,17,74,-38,73 2 0066 six
+7 680,681,0,109,-73,73 2 0067 seven
+8 680,698,17,56,-18,56 2 0070 eight
+9 680,698,17,82,-21,73 2 0071 nine
+: 340,515,8,66,-56,66 0 0072 colon
+; 340,515,124,62,-50,62 0 0073 semicolon
+< 620,540,9,18,-29,18 0 0074 less
+= 600,421,0,45,-41,45 0 0075 equal
+> 620,540,9,28,-39,28 0 0076 greater
+? 620,698,8,98,-95,73 2 0077 question
+@ 780,698,17,60,-30,60 2 0100 at
+at "
+A 720,681,0,99,77,73 2 0101 A
+B 720,681,0,92,36,73 2 0102 B
+C 700,698,17,104,-28,73 2 0103 C
+D 760,681,0,95,36,73 2 0104 D
+E 720,681,0,107,36,73 2 0105 E
+F 660,681,0,153,36,73 2 0106 F
+G 760,698,17,118,-27,73 2 0107 G
+H 800,681,0,160,36,73 2 0110 H
+I 380,681,0,155,36,73 2 0111 I
+J 620,681,17,151,42,73 2 0112 J
+K 780,681,0,149,36,73 2 0113 K
+L 640,681,0,135,36,73 2 0114 L
+M 860,681,0,160,36,73 2 0115 M
+N 740,681,0,155,36,73 2 0116 N
+O 760,698,17,96,-28,73 2 0117 O
+P 640,681,0,134,56,73 2 0120 P
+Q 760,698,213,95,13,73 3 0121 Q
+R 740,681,0,75,36,73 2 0122 R
+S 700,698,17,81,-9,73 2 0123 S
+T 700,681,0,152,-20,73 2 0124 T
+U 740,681,17,165,-62,73 2 0125 U
+V 660,681,0,209,-22,73 2 0126 V
+W 1000,681,0,140,-22,73 2 0127 W
+X 740,681,0,145,57,73 2 0130 X
+Y 660,681,0,207,-22,73 2 0131 Y
+Z 680,681,0,110,27,73 2 0132 Z
+[ 260,741,118,164,41,73 2 0133 bracketleft
+lB "
+\ 580,741,0,45,-23,45 2 0134 backslash
+rs "
+] 260,741,118,137,68,73 2 0135 bracketright
+rB "
+a^ 480,749,0,93,-133,73 2 0136 circumflex
+^ "
+_ 500,0,155,50,50,50 0 0137 underscore
+` 320,698,0,63,-105,63 2 0140 quoteleft
+oq "
+a 680,515,8,105,-34,73 0 0141 a
+b 600,732,8,83,-7,73 2 0142 b
+c 560,515,8,87,-8,73 0 0143 c
+d 680,732,8,84,-10,73 2 0144 d
+e 560,515,8,86,-9,73 0 0145 e
+f 420,741,213,271,242,73 3 0146 f
+g 620,515,213,99,29,73 1 0147 g
+h 700,732,8,86,-43,73 2 0150 h
+i 380,755,8,90,-33,73 2 0151 i
+j 320,755,213,122,210,73 3 0152 j
+k 700,732,8,82,-47,73 2 0153 k
+l 380,732,8,80,-59,73 2 0154 l
+m 960,515,8,86,-33,73 0 0155 m
+n 680,515,8,85,-33,73 0 0156 n
+o 600,515,8,77,-9,73 0 0157 o
+p 660,515,213,72,74,72 1 0160 p
+q 620,515,213,70,-10,70 1 0161 q
+r 500,515,0,132,-34,73 0 0162 r
+s 540,515,8,83,18,73 0 0163 s
+t 440,658,8,98,-56,73 2 0164 t
+u 680,507,8,90,-33,73 0 0165 u
+v 540,515,8,82,-6,73 0 0166 v
+w 860,515,8,81,-6,73 0 0167 w
+x 620,515,8,84,40,73 0 0170 x
+y 600,507,213,92,25,73 1 0171 y
+z 560,515,8,76,14,73 0 0172 z
+lC 300,742,123,159,-3,73 2 0173 braceleft
+{ "
+ba 620,741,0,0,-253 2 0174 bar
+| "
+rC 300,742,123,102,54,73 2 0175 braceright
+} "
+a~ 480,709,0,103,-128,73 2 0176 tilde
+~ "
+bq 300,166,112,34,-56,34 0 0200 quotesinglbase
+Fo 380,503,0,76,-12,73 0 0201 guillemotleft
+char171 "
+Fc 380,503,0,76,-12,73 0 0202 guillemotright
+char187 "
+bu 360,511,0,94,-10,73 0 0203 bullet
+Fn 680,741,199,113,78,73 2 0204 florin
+f/ 120,681,0,312,194,73 2 0205 fraction
+%0 1360,698,17,23,-56,23 2 0206 perthousand
+dg 420,698,137,96,-39,73 2 0207 dagger
+dd 420,698,137,116,-29,73 2 0210 daggerdbl
+en 500,311,0,123,10,73 0 0211 endash
+em 1000,311,0,123,10,73 0 0212 emdash
+fi 820,741,213,80,241,73 3 0214 fi
+fl 820,741,213,80,241,73 3 0215 fl
+.i 380,507,8,90,-33,73 0 0220 dotlessi
+ga 380,771,0,94,-143,73 2 0222 grave
+a" 560,775,0,106,-131,73 2 0223 hungarumlaut
+a. 380,734,0,15,-130,15 2 0224 dotaccent
+ab 460,707,0,106,-127,73 2 0225 breve
+ah 480,749,0,93,-133,73 2 0226 caron
+ao 360,775,0,96,-135,73 2 0227 ring
+ho 320,0,182,0,-18 0 0230 ogonek
+lq 520,698,0,75,-106,73 2 0231 quotedblleft
+rq 520,698,0,90,-121,73 2 0232 quotedblright
+oe 920,515,8,91,2,73 0 0233 oe
+/l 380,732,8,82,-13,73 2 0234 lslash
+Bq 520,166,112,25,-56,25 0 0235 quotedblbase
+OE 1180,698,17,115,-44,73 2 0236 OE
+/L 640,681,0,134,36,73 2 0237 Lslash
+r! 320,515,191,74,-14,73 0 0241 exclamdown
+char161 "
+ct 680,718,0,0,-111 2 0242 cent
+char162 "
+Po 680,698,17,157,50,73 2 0243 sterling
+char163 "
+Cs 680,571,0,7,-98,7 0 0244 currency
+char164 "
+Ye 680,681,0,152,-42,73 2 0245 yen
+char165 "
+bb 620,741,0,0,-253 2 0246 brokenbar
+char166 "
+sc 620,698,137,68,4,68 2 0247 section
+char167 "
+ad 520,734,0,99,-130,73 2 0250 dieresis
+char168 "
+co 780,698,17,53,-33,53 2 0251 copyright
+char169 "
+Of 440,685,0,105,-5,73 2 0252 ordfeminine
+char170 "
+fo 220,503,0,79,-12,73 0 0253 guilsinglleft
+no 620,421,0,15,-31,15 0 0254 logicalnot
+char172 "
+\- 600,323,0,45,-41,45 0 0255 minus
+rg 780,698,17,53,-33,53 2 0256 registered
+char174 "
+a- 480,691,0,101,-127,73 2 0257 macron
+char175 "
+de 400,698,0,80,-80,73 2 0260 degree
+char176 "
+char177 600,514,0,45,-41,45 0 0261 plusminus
+S2 408,698,0,127,-41,73 2 0262 twosuperior
+char178 "
+S3 408,698,0,125,-36,73 2 0263 threesuperior
+char179 "
+aa 340,771,0,117,-126,73 2 0264 acute
+char180 "
+char181 680,507,213,90,-4,73 1 0265 mu
+ps 680,681,204,96,-20,73 2 0266 paragraph
+char182 "
+char183 340,358,0,26,-76,26 0 0267 periodcentered
+ac 360,0,220,0,-18 1 0270 cedilla
+char184 "
+S1 408,688,0,48,-68,48 2 0271 onesuperior
+char185 "
+Om 440,685,0,77,3,73 2 0272 ordmasculine
+char186 "
+fc 220,503,0,79,-12,73 0 0273 guilsinglright
+14 1020,681,0,84,-68,73 2 0274 onequarter
+char188 "
+12 1020,681,0,66,-68,66 2 0275 onehalf
+char189 "
+34 1020,691,0,84,-36,73 2 0276 threequarters
+char190 "
+r? 620,515,189,36,-33,36 0 0277 questiondown
+char191 "
+`A 720,937,0,99,77,73 2 0300 Agrave
+char192 "
+'A 720,937,0,99,77,73 2 0301 Aacute
+char193 "
+^A 720,915,0,99,77,73 2 0302 Acircumflex
+char194 "
+~A 720,875,0,99,77,73 2 0303 Atilde
+char195 "
+:A 720,900,0,99,77,73 2 0304 Adieresis
+char196 "
+oA 720,941,0,99,77,73 2 0305 Aring
+char197 "
+AE 1140,681,0,117,77,73 2 0306 AE
+char198 "
+,C 700,698,220,104,-28,73 3 0307 Ccedilla
+char199 "
+`E 720,937,0,107,36,73 2 0310 Egrave
+char200 "
+'E 720,937,0,107,36,73 2 0311 Eacute
+char201 "
+^E 720,915,0,107,36,73 2 0312 Ecircumflex
+char202 "
+:E 720,900,0,107,36,73 2 0313 Edieresis
+char203 "
+`I 380,937,0,155,36,73 2 0314 Igrave
+char204 "
+'I 380,937,0,155,36,73 2 0315 Iacute
+char205 "
+^I 380,915,0,163,36,73 2 0316 Icircumflex
+char206 "
+:I 380,900,0,169,36,73 2 0317 Idieresis
+char207 "
+-D 760,681,0,95,36,73 2 0320 Eth
+char208 "
+~N 740,875,0,155,36,73 2 0321 Ntilde
+char209 "
+`O 760,937,17,96,-28,73 2 0322 Ograve
+char210 "
+'O 760,937,17,96,-28,73 2 0323 Oacute
+char211 "
+^O 760,915,17,96,-28,73 2 0324 Ocircumflex
+char212 "
+~O 760,875,17,96,-28,73 2 0325 Otilde
+char213 "
+:O 760,900,17,96,-28,73 2 0326 Odieresis
+char214 "
+char215 600,514,0,45,-41,45 0 0327 multiply
+/O 760,725,29,137,29,73 2 0330 Oslash
+char216 "
+`U 740,937,17,165,-62,73 2 0331 Ugrave
+char217 "
+'U 740,937,17,165,-62,73 2 0332 Uacute
+char218 "
+^U 740,915,17,165,-62,73 2 0333 Ucircumflex
+char219 "
+:U 740,900,17,165,-62,73 2 0334 Udieresis
+char220 "
+'Y 660,937,0,207,-22,73 2 0335 Yacute
+char221 "
+TP 640,681,0,111,56,73 2 0336 Thorn
+char222 "
+ss 660,741,213,92,281,73 3 0337 germandbls
+char223 "
+`a 680,771,8,105,-34,73 2 0340 agrave
+char224 "
+'a 680,771,8,105,-34,73 2 0341 aacute
+char225 "
+^a 680,749,8,105,-34,73 2 0342 acircumflex
+char226 "
+~a 680,709,8,105,-34,73 2 0343 atilde
+char227 "
+:a 680,734,8,105,-34,73 2 0344 adieresis
+char228 "
+oa 680,775,8,105,-34,73 2 0345 aring
+char229 "
+ae 880,515,8,83,11,73 0 0346 ae
+char230 "
+,c 560,515,220,87,-8,73 1 0347 ccedilla
+char231 "
+`e 560,771,8,86,-9,73 2 0350 egrave
+char232 "
+'e 560,771,8,86,-9,73 2 0351 eacute
+char233 "
+^e 560,749,8,86,-9,73 2 0352 ecircumflex
+char234 "
+:e 560,734,8,86,-9,73 2 0353 edieresis
+char235 "
+`i 380,771,8,94,-33,73 2 0354 igrave
+char236 "
+'i 380,771,8,90,-33,73 2 0355 iacute
+char237 "
+^i 380,749,8,103,-33,73 2 0356 icircumflex
+char238 "
+:i 380,734,8,149,-33,73 2 0357 idieresis
+char239 "
+Sd 600,741,8,112,-9,73 2 0360 eth
+char240 "
+~n 680,709,8,85,-33,73 2 0361 ntilde
+char241 "
+`o 600,771,8,77,-9,73 2 0362 ograve
+char242 "
+'o 600,771,8,77,-9,73 2 0363 oacute
+char243 "
+^o 600,749,8,77,-9,73 2 0364 ocircumflex
+char244 "
+~o 600,709,8,77,-9,73 2 0365 otilde
+char245 "
+:o 600,734,8,77,-9,73 2 0366 odieresis
+char246 "
+char247 600,521,0,45,-41,45 0 0367 divide
+/o 600,571,54,111,33,73 0 0370 oslash
+char248 "
+`u 680,771,8,90,-33,73 2 0371 ugrave
+char249 "
+'u 680,771,8,90,-33,73 2 0372 uacute
+char250 "
+^u 680,749,8,90,-33,73 2 0373 ucircumflex
+char251 "
+:u 680,734,8,90,-33,73 2 0374 udieresis
+char252 "
+'y 600,771,213,92,25,73 3 0375 yacute
+char253 "
+Tp 660,732,213,72,74,72 3 0376 thorn
+char254 "
+:y 600,734,213,92,25,73 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/BMI b/gnu/usr.bin/groff/devices/devps/BMI
new file mode 100644
index 000000000000..7eaa3f1f6b34
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/BMI
@@ -0,0 +1,434 @@
+name BMI
+internalname Bookman-LightItalic
+slant 10
+spacewidth 300
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A Y -62
+A W -73
+A V -78
+A T -5
+F . -97
+F , -98
+F A -16
+L y 20
+L Y 7
+L W 9
+L V 4
+P . -105
+P , -106
+P A -30
+R Y 11
+R W 2
+R V 2
+R T 65
+T ; 48
+T s -7
+T r 67
+T . -78
+T o 14
+T i 71
+T - 20
+T hy 20
+T char173 20
+T e 10
+T , -79
+T : 48
+T c 16
+T a 9
+T A -14
+V y -14
+V u -10
+V ; -44
+V r -20
+V . -100
+V o -70
+V i 3
+V - 20
+V hy 20
+V char173 20
+V e -70
+V , -109
+V : -35
+V a -70
+V A -70
+W y -14
+W u -20
+W ; -42
+W r -30
+W . -100
+W o -60
+W i 3
+W - 20
+W hy 20
+W char173 20
+W e -60
+W , -109
+W : -35
+W a -60
+W A -60
+Y v -19
+Y u -31
+Y ; -40
+Y q -72
+Y . -100
+Y p -37
+Y o -75
+Y i -11
+Y - 20
+Y hy 20
+Y char173 20
+Y e -78
+Y , -109
+Y : -35
+Y a -79
+Y A -82
+f f -19
+r q -14
+r . -134
+r o -10
+r n 38
+r m 37
+r - 20
+r hy 20
+r char173 20
+r h -20
+r g -3
+r f -9
+r e -15
+r d -9
+r , -143
+r c -8
+charset
+ha 600,681,0,49,-47,49 2 0000 asciicircum
+ti 600,386,0,45,-41,45 0 0001 asciitilde
+vS 640,871,17,78,-11,70 2 0002 Scaron
+vZ 580,871,0,165,42,70 2 0003 Zcaron
+vs 540,684,8,57,-15,57 2 0004 scaron
+vz 520,684,8,91,12,70 2 0005 zcaron
+:Y 660,875,0,199,-37,70 2 0006 Ydieresis
+tm 980,681,0,35,-19,35 2 0007 trademark
+aq 200,698,0,97,-49,70 2 0010 quotesingle
+space 300 0 0040
+! 320,698,8,72,-53,70 2 0041 exclam
+" 360,698,0,92,-57,70 2 0042 quotedbl
+# 620,681,0,28,-57,28 2 0043 numbersign
+sh "
+$ 620,762,85,49,-28,49 2 0044 dollar
+Do "
+% 800,691,8,61,-6,61 2 0045 percent
+& 820,698,18,78,-15,70 2 0046 ampersand
+' 280,698,0,58,-98,58 2 0047 quoteright
+( 280,727,146,153,-46,70 2 0050 parenleft
+) 280,727,146,49,58,49 2 0051 parenright
+* 440,698,0,115,-89,70 2 0052 asterisk
++ 600,548,0,45,-41,45 0 0053 plus
+, 300,112,115,0,-38 0 0054 comma
+- 320,325,0,66,-28,66 0 0055 hyphen
+hy "
+char173 "
+. 300,127,8,0,-46 0 0056 period
+/ 600,717,149,12,-54,12 2 0057 slash
+sl "
+0 620,698,17,76,-36,70 2 0060 zero
+1 620,681,0,0,-104 2 0061 one
+2 620,698,0,66,-16,66 2 0062 two
+3 620,698,17,52,-5,52 2 0063 three
+4 620,681,0,64,-19,64 2 0064 four
+5 620,681,17,44,-20,44 2 0065 five
+6 620,698,17,87,-39,70 2 0066 six
+7 620,681,0,102,-93,70 2 0067 seven
+8 620,698,17,85,-11,70 2 0070 eight
+9 620,698,17,79,-27,70 2 0071 nine
+: 300,494,8,42,-46,42 0 0072 colon
+; 300,494,114,42,-38,42 0 0073 semicolon
+< 600,561,0,38,-29,38 0 0074 less
+= 600,433,0,45,-41,45 0 0075 equal
+> 600,561,0,52,-43,52 0 0076 greater
+? 540,698,8,114,-64,70 2 0077 question
+@ 780,698,17,72,-52,70 2 0100 at
+at "
+A 700,681,0,70,75,70 2 0101 A
+B 720,681,0,76,29,70 2 0102 B
+C 720,698,17,76,-38,70 2 0103 C
+D 740,681,0,92,29,70 2 0104 D
+E 680,681,0,106,29,70 2 0105 E
+F 620,681,0,173,29,70 2 0106 F
+G 760,698,17,103,-38,70 2 0107 G
+H 800,681,0,138,29,70 2 0110 H
+I 320,681,0,142,29,70 2 0111 I
+J 560,681,17,156,52,70 2 0112 J
+K 720,681,0,134,29,70 2 0113 K
+L 580,681,0,126,29,70 2 0114 L
+M 860,681,0,146,32,70 2 0115 M
+N 720,681,0,153,32,70 2 0116 N
+O 760,698,17,89,-38,70 2 0117 O
+P 600,681,0,131,29,70 2 0120 P
+Q 780,698,191,82,-11,70 2 0121 Q
+R 700,681,0,86,29,70 2 0122 R
+S 640,698,17,78,-11,70 2 0123 S
+T 600,681,0,175,0,70 2 0124 T
+U 720,681,17,172,-68,70 2 0125 U
+V 680,681,0,185,-37,70 2 0126 V
+W 960,681,0,185,-37,70 2 0127 W
+X 700,681,0,165,75,70 2 0130 X
+Y 660,681,0,199,-37,70 2 0131 Y
+Z 580,681,0,165,42,70 2 0132 Z
+[ 260,717,136,141,-6,70 2 0133 bracketleft
+lB "
+\ 600,717,0,0,-34 2 0134 backslash
+rs "
+] 260,717,136,99,35,70 2 0135 bracketright
+rB "
+a^ 440,685,0,89,-126,70 2 0136 circumflex
+^ "
+_ 500,0,155,50,50,50 0 0137 underscore
+` 280,698,0,100,-141,70 2 0140 quoteleft
+oq "
+a 620,494,8,116,-21,70 0 0141 a
+b 600,717,8,71,-38,70 2 0142 b
+c 480,494,8,92,-15,70 0 0143 c
+d 640,717,8,105,-15,70 2 0144 d
+e 540,494,8,85,-15,70 0 0145 e
+f 340,725,218,267,210,70 3 0146 f
+g 560,494,221,71,46,70 1 0147 g
+h 620,717,8,119,-38,70 2 0150 h
+i 280,663,8,121,-38,70 2 0151 i
+j 280,663,221,78,250,70 3 0152 j
+k 600,717,8,107,-38,70 2 0153 k
+l 280,717,8,112,-50,70 2 0154 l
+m 880,494,8,122,-38,70 0 0155 m
+n 620,494,8,103,-38,70 0 0156 n
+o 540,494,8,82,-15,70 0 0157 o
+p 600,494,212,70,74,70 1 0160 p
+q 560,494,212,74,-15,70 1 0161 q
+r 400,494,0,131,-38,70 0 0162 r
+s 540,494,8,57,-15,57 0 0163 s
+t 340,664,8,121,-38,70 2 0164 t
+u 620,484,8,116,-38,70 0 0165 u
+v 540,494,8,72,-38,70 0 0166 v
+w 880,494,8,63,-38,63 0 0167 w
+x 540,494,8,136,41,70 0 0170 x
+y 600,484,221,59,-10,59 1 0171 y
+z 520,494,8,91,12,70 0 0172 z
+lC 360,717,191,129,-75,70 2 0173 braceleft
+{ "
+ba 600,717,0,0,-244 2 0174 bar
+| "
+rC 380,717,191,0,35 2 0175 braceright
+} "
+a~ 440,671,0,98,-130,70 2 0176 tilde
+~ "
+bq 320,113,114,0,-37 0 0200 quotesinglbase
+Fo 300,434,0,63,-20,63 0 0201 guillemotleft
+char171 "
+Fc 300,434,0,53,-10,53 0 0202 guillemotright
+char187 "
+bu 460,511,0,34,-50,34 0 0203 bullet
+Fn 620,725,218,122,76,70 3 0204 florin
+f/ 20,681,0,353,278,70 2 0205 fraction
+%0 1180,691,8,69,-6,69 2 0206 perthousand
+dg 620,698,130,0,-142 2 0207 dagger
+dd 620,698,122,0,-94 2 0210 daggerdbl
+en 500,325,0,111,17,70 0 0211 endash
+em 1000,325,0,111,17,70 0 0212 emdash
+fi 640,725,222,119,209,70 3 0214 fi
+fl 660,725,218,103,209,70 3 0215 fl
+.i 280,484,8,121,-38,70 0 0220 dotlessi
+ga 340,706,0,87,-132,70 2 0222 grave
+a" 340,738,0,112,-117,70 2 0223 hungarumlaut
+a. 260,664,0,80,-119,70 2 0224 dotaccent
+ab 440,680,0,110,-141,70 2 0225 breve
+ah 440,684,0,91,-128,70 2 0226 caron
+ao 300,706,0,84,-128,70 2 0227 ring
+ho 260,0,173,0,-1 0 0230 ogonek
+lq 440,698,0,103,-141,70 2 0231 quotedblleft
+rq 440,698,0,61,-98,61 2 0232 quotedblright
+oe 900,494,8,98,-15,70 0 0233 oe
+/l 340,717,8,108,0,70 2 0234 lslash
+Bq 480,113,114,0,-37 0 0235 quotedblbase
+OE 1180,698,17,107,-38,70 2 0236 OE
+/L 580,681,0,126,29,70 2 0237 Lslash
+r! 320,494,213,31,-23,31 1 0241 exclamdown
+char161 "
+ct 620,715,29,26,-98,26 2 0242 cent
+char162 "
+Po 620,698,17,132,46,70 2 0243 sterling
+char163 "
+Cs 620,591,0,35,-50,35 0 0244 currency
+char164 "
+Ye 620,681,0,165,-21,70 2 0245 yen
+char165 "
+bb 600,717,0,0,-244 2 0246 brokenbar
+char166 "
+sc 620,698,178,68,12,68 2 0247 section
+char167 "
+ad 420,688,0,97,-135,70 2 0250 dieresis
+char168 "
+co 740,698,17,94,-34,70 2 0251 copyright
+char169 "
+Of 440,698,0,123,-44,70 2 0252 ordfeminine
+char170 "
+fo 180,434,0,78,-25,70 0 0253 guilsinglleft
+no 600,433,0,45,-41,45 0 0254 logicalnot
+char172 "
+\- 600,335,0,45,-41,45 0 0255 minus
+rg 740,698,17,94,-34,70 2 0256 registered
+char174 "
+a- 440,658,0,94,-128,70 0 0257 macron
+char175 "
+de 400,698,0,70,-70,70 2 0260 degree
+char176 "
+char177 600,548,0,45,-41,45 0 0261 plusminus
+S2 372,698,0,117,-18,70 2 0262 twosuperior
+char178 "
+S3 372,698,0,117,-20,70 2 0263 threesuperior
+char179 "
+aa 320,706,0,103,-128,70 2 0264 acute
+char180 "
+char181 620,484,221,116,-3,70 1 0265 mu
+ps 620,681,0,148,-62,70 2 0266 paragraph
+char182 "
+char183 300,364,0,22,-87,22 0 0267 periodcentered
+ac 320,0,178,0,5 0 0270 cedilla
+char184 "
+S1 372,688,0,17,-64,17 2 0271 onesuperior
+char185 "
+Om 400,698,0,105,-44,70 2 0272 ordmasculine
+char186 "
+fc 180,434,0,73,-20,70 0 0273 guilsinglright
+14 930,681,0,33,-41,33 2 0274 onequarter
+char188 "
+12 930,681,0,45,-41,45 2 0275 onehalf
+char189 "
+34 930,691,0,33,-49,33 2 0276 threequarters
+char190 "
+r? 540,494,212,18,32,18 1 0277 questiondown
+char191 "
+`A 700,893,0,70,75,70 2 0300 Agrave
+char192 "
+'A 700,893,0,70,75,70 2 0301 Aacute
+char193 "
+^A 700,872,0,70,75,70 2 0302 Acircumflex
+char194 "
+~A 700,858,0,70,75,70 2 0303 Atilde
+char195 "
+:A 700,875,0,70,75,70 2 0304 Adieresis
+char196 "
+oA 700,893,0,70,75,70 2 0305 Aring
+char197 "
+AE 1220,681,0,99,95,70 2 0306 AE
+char198 "
+,C 720,698,178,76,-38,70 2 0307 Ccedilla
+char199 "
+`E 680,893,0,106,29,70 2 0310 Egrave
+char200 "
+'E 680,893,0,106,29,70 2 0311 Eacute
+char201 "
+^E 680,872,0,106,29,70 2 0312 Ecircumflex
+char202 "
+:E 680,875,0,106,29,70 2 0313 Edieresis
+char203 "
+`I 320,893,0,142,29,70 2 0314 Igrave
+char204 "
+'I 320,893,0,142,29,70 2 0315 Iacute
+char205 "
+^I 320,872,0,149,29,70 2 0316 Icircumflex
+char206 "
+:I 320,875,0,147,29,70 2 0317 Idieresis
+char207 "
+-D 740,681,0,92,29,70 2 0320 Eth
+char208 "
+~N 720,858,0,153,32,70 2 0321 Ntilde
+char209 "
+`O 760,893,17,89,-38,70 2 0322 Ograve
+char210 "
+'O 760,893,17,89,-38,70 2 0323 Oacute
+char211 "
+^O 760,872,17,89,-38,70 2 0324 Ocircumflex
+char212 "
+~O 760,858,17,89,-38,70 2 0325 Otilde
+char213 "
+:O 760,875,17,89,-38,70 2 0326 Odieresis
+char214 "
+char215 600,548,0,45,-41,45 0 0327 multiply
+/O 760,777,95,89,-38,70 2 0330 Oslash
+char216 "
+`U 720,893,17,172,-68,70 2 0331 Ugrave
+char217 "
+'U 720,893,17,172,-68,70 2 0332 Uacute
+char218 "
+^U 720,872,17,172,-68,70 2 0333 Ucircumflex
+char219 "
+:U 720,875,17,172,-68,70 2 0334 Udieresis
+char220 "
+'Y 660,893,0,199,-37,70 2 0335 Yacute
+char221 "
+TP 600,681,0,106,29,70 2 0336 Thorn
+char222 "
+ss 620,698,111,83,171,70 2 0337 germandbls
+char223 "
+`a 620,706,8,116,-21,70 2 0340 agrave
+char224 "
+'a 620,706,8,116,-21,70 2 0341 aacute
+char225 "
+^a 620,685,8,116,-21,70 2 0342 acircumflex
+char226 "
+~a 620,671,8,116,-21,70 2 0343 atilde
+char227 "
+:a 620,688,8,116,-21,70 2 0344 adieresis
+char228 "
+oa 620,706,8,116,-21,70 2 0345 aring
+char229 "
+ae 880,494,8,88,-21,70 0 0346 ae
+char230 "
+,c 480,494,178,92,-15,70 0 0347 ccedilla
+char231 "
+`e 540,706,8,85,-15,70 2 0350 egrave
+char232 "
+'e 540,706,8,85,-15,70 2 0351 eacute
+char233 "
+^e 540,685,8,85,-15,70 2 0352 ecircumflex
+char234 "
+:e 540,688,8,85,-15,70 2 0353 edieresis
+char235 "
+`i 280,706,8,121,-38,70 2 0354 igrave
+char236 "
+'i 280,706,8,121,-38,70 2 0355 iacute
+char237 "
+^i 280,685,8,149,-26,70 2 0356 icircumflex
+char238 "
+:i 280,688,8,147,-38,70 2 0357 idieresis
+char239 "
+Sd 540,725,8,152,-15,70 2 0360 eth
+char240 "
+~n 620,671,8,103,-38,70 2 0361 ntilde
+char241 "
+`o 540,706,8,82,-15,70 2 0362 ograve
+char242 "
+'o 540,706,8,82,-15,70 2 0363 oacute
+char243 "
+^o 540,685,8,82,-15,70 2 0364 ocircumflex
+char244 "
+~o 540,671,8,82,-15,70 2 0365 otilde
+char245 "
+:o 540,688,8,82,-15,70 2 0366 odieresis
+char246 "
+char247 600,548,0,45,-41,45 0 0367 divide
+/o 540,532,49,81,-15,70 0 0370 oslash
+char248 "
+`u 620,706,8,116,-38,70 2 0371 ugrave
+char249 "
+'u 620,706,8,116,-38,70 2 0372 uacute
+char250 "
+^u 620,685,8,116,-38,70 2 0373 ucircumflex
+char251 "
+:u 620,688,8,116,-38,70 2 0374 udieresis
+char252 "
+'y 600,706,221,59,-10,59 3 0375 yacute
+char253 "
+Tp 600,717,212,70,74,70 3 0376 thorn
+char254 "
+:y 600,688,221,59,-10,59 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/BMR b/gnu/usr.bin/groff/devices/devps/BMR
new file mode 100644
index 000000000000..8e90c100093e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/BMR
@@ -0,0 +1,430 @@
+name BMR
+internalname Bookman-Light
+spacewidth 320
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y 32
+A w 4
+A v 7
+A Y -35
+A W -40
+A V -56
+A T 1
+F . -46
+F , -41
+F A -21
+L y 79
+L Y 13
+L W 1
+L V -4
+L T 28
+P . -60
+P , -55
+P A -8
+R y 59
+R Y 26
+R W 13
+R V 8
+R T 71
+T s 16
+T r 38
+T . -33
+T o 15
+T i 42
+T - 90
+T hy 90
+T char173 90
+T e 13
+T , -28
+T c 14
+T a 17
+T A 1
+V y 15
+V u -38
+V r -41
+V . -40
+V o -71
+V i -20
+V - 11
+V hy 11
+V char173 11
+V e -72
+V , -34
+V a -69
+V A -66
+W y 15
+W u -38
+W r -41
+W . -40
+W o -68
+W i -20
+W - 11
+W hy 11
+W char173 11
+W e -69
+W , -34
+W a -66
+W A -64
+Y v 15
+Y u -38
+Y q -55
+Y . -40
+Y p -31
+Y o -57
+Y i -37
+Y - 11
+Y hy 11
+Y char173 11
+Y e -58
+Y , -34
+Y a -54
+Y A -53
+f f 29
+r q 9
+r . -64
+r o 8
+r n 31
+r m 31
+r - 70
+r hy 70
+r char173 70
+r h -21
+r g -4
+r f 33
+r e 7
+r d 7
+r , -58
+r c 7
+charset
+ha 600,681 2 0000 asciicircum
+ti 600,352 0 0001 asciitilde
+vS 660,869,17 2 0002 Scaron
+vZ 640,869 2 0003 Zcaron
+vs 520,672,8 2 0004 scaron
+vz 480,672 2 0005 zcaron
+:Y 640,871 2 0006 Ydieresis
+tm 980,681 2 0007 trademark
+aq 220,698 2 0010 quotesingle
+space 320 0 0040
+! 300,698,8 2 0041 exclam
+" 380,698 2 0042 quotedbl
+# 620,681 2 0043 numbersign
+sh "
+$ 620,791,109 2 0044 dollar
+Do "
+% 900,698,8 2 0045 percent
+& 800,698,17 2 0046 ampersand
+' 220,698 2 0047 quoteright
+( 300,727,145 2 0050 parenleft
+) 300,727,146 2 0051 parenright
+* 440,698 2 0052 asterisk
++ 600,513 0 0053 plus
+, 320,114,114 0 0054 comma
+- 400,292 0 0055 hyphen
+hy "
+char173 "
+. 320,123,8 0 0056 period
+/ 600,717,149 2 0057 slash
+sl "
+0 620,698,17 2 0060 zero
+1 620,681 2 0061 one
+2 620,698 2 0062 two
+3 620,698,17 2 0063 three
+4 620,681 2 0064 four
+5 620,717,17 2 0065 five
+6 620,698,17 2 0066 six
+7 620,681 2 0067 seven
+8 620,698,17 2 0070 eight
+9 620,698,17 2 0071 nine
+: 320,494,8 0 0072 colon
+; 320,494,114 0 0073 semicolon
+< 600,526,2 0 0074 less
+= 600,398 0 0075 equal
+> 600,526,2 0 0076 greater
+? 540,698,8 2 0077 question
+@ 820,698,17 2 0100 at
+at "
+A 680,681 2 0101 A
+B 740,681 2 0102 B
+C 740,698,17 2 0103 C
+D 800,681 2 0104 D
+E 720,681 2 0105 E
+F 640,681 2 0106 F
+G 800,698,17 2 0107 G
+H 800,681 2 0110 H
+I 340,681 2 0111 I
+J 600,681,17 2 0112 J
+K 720,681 2 0113 K
+L 600,681 2 0114 L
+M 920,681 2 0115 M
+N 740,681 2 0116 N
+O 800,698,17 2 0117 O
+P 620,681 2 0120 P
+Q 820,698,189 2 0121 Q
+R 720,681 2 0122 R
+S 660,698,17 2 0123 S
+T 620,681 2 0124 T
+U 780,681,17 2 0125 U
+V 700,681 2 0126 V
+W 960,681 2 0127 W
+X 720,681 2 0130 X
+Y 640,681 2 0131 Y
+Z 640,681 2 0132 Z
+[ 300,717,136 2 0133 bracketleft
+lB "
+\ 600,717 2 0134 backslash
+rs "
+] 300,717,136 2 0135 bracketright
+rB "
+a^ 420,685 2 0136 circumflex
+^ "
+_ 500,0,155 0 0137 underscore
+` 220,698 2 0140 quoteleft
+oq "
+a 580,494,8 0 0141 a
+b 620,717,8 2 0142 b
+c 520,494,8 0 0143 c
+d 620,717,8 2 0144 d
+e 520,494,8 0 0145 e
+f 320,734 2 0146 f
+g 540,567,243 1 0147 g
+h 660,717 2 0150 h
+i 300,654 0 0151 i
+j 300,654,251 1 0152 j
+k 620,717 2 0153 k
+l 300,717 2 0154 l
+m 940,494 0 0155 m
+n 660,494 0 0156 n
+o 560,494,8 0 0157 o
+p 620,494,228 1 0160 p
+q 580,494,228 1 0161 q
+r 440,494 0 0162 r
+s 520,494,8 0 0163 s
+t 380,667,8 2 0164 t
+u 680,484,8 0 0165 u
+v 520,484 0 0166 v
+w 780,484 0 0167 w
+x 560,484 0 0170 x
+y 540,484,236 1 0171 y
+z 480,484 0 0172 z
+lC 280,717,136 2 0173 braceleft
+{ "
+ba 600,717 2 0174 bar
+| "
+rC 280,717,136 2 0175 braceright
+} "
+a~ 440,661 0 0176 tilde
+~ "
+bq 220,110,108 0 0200 quotesinglbase
+Fo 360,437 0 0201 guillemotleft
+char171 "
+Fc 360,437 0 0202 guillemotright
+char187 "
+bu 460,511 0 0203 bullet
+Fn 620,749,155 2 0204 florin
+f/ 140,681 2 0205 fraction
+%0 1280,698,8 2 0206 perthousand
+dg 540,698,156 2 0207 dagger
+dd 540,698,156 2 0210 daggerdbl
+en 500,292 0 0211 endash
+em 1000,292 0 0212 emdash
+fi 620,734 2 0214 fi
+fl 620,734 2 0215 fl
+.i 300,484 0 0220 dotlessi
+ga 340,689 2 0222 grave
+a" 380,699 2 0223 hungarumlaut
+a. 260,672 2 0224 dotaccent
+ab 460,687 2 0225 breve
+ah 420,672 2 0226 caron
+ao 320,731 2 0227 ring
+ho 320,0,145 0 0230 ogonek
+lq 400,698 2 0231 quotedblleft
+rq 400,698 2 0232 quotedblright
+oe 900,494,8 0 0233 oe
+/l 320,717 2 0234 lslash
+Bq 400,110,108 0 0235 quotedblbase
+OE 1240,698,17 2 0236 OE
+/L 600,681 2 0237 Lslash
+r! 300,494,214 0 0241 exclamdown
+char161 "
+ct 620,651 0 0242 cent
+char162 "
+Po 620,698,17 2 0243 sterling
+char163 "
+Cs 620,591 0 0244 currency
+char164 "
+Ye 620,681 2 0245 yen
+char165 "
+bb 600,717 2 0246 brokenbar
+char166 "
+sc 520,698,178 2 0247 section
+char167 "
+ad 420,674 2 0250 dieresis
+char168 "
+co 740,698,17 2 0251 copyright
+char169 "
+Of 420,698 2 0252 ordfeminine
+char170 "
+fo 240,437 0 0253 guilsinglleft
+no 600,398 0 0254 logicalnot
+char172 "
+\- 600,300 0 0255 minus
+rg 740,698,17 2 0256 registered
+char174 "
+a- 440,635 0 0257 macron
+char175 "
+de 400,698 2 0260 degree
+char176 "
+char177 600,513 0 0261 plusminus
+S2 372,698 2 0262 twosuperior
+char178 "
+S3 372,698 2 0263 threesuperior
+char179 "
+aa 340,689 2 0264 acute
+char180 "
+char181 680,484,251 1 0265 mu
+ps 600,681 2 0266 paragraph
+char182 "
+char183 320,327 0 0267 periodcentered
+ac 320,0,200 0 0270 cedilla
+char184 "
+S1 372,688 2 0271 onesuperior
+char185 "
+Om 420,698 2 0272 ordmasculine
+char186 "
+fc 240,437 0 0273 guilsinglright
+14 930,681 2 0274 onequarter
+char188 "
+12 930,681 2 0275 onehalf
+char189 "
+34 930,691 2 0276 threequarters
+char190 "
+r? 540,494,217 0 0277 questiondown
+char191 "
+`A 680,886 2 0300 Agrave
+char192 "
+'A 680,886 2 0301 Aacute
+char193 "
+^A 680,882 2 0302 Acircumflex
+char194 "
+~A 680,858 2 0303 Atilde
+char195 "
+:A 680,871 2 0304 Adieresis
+char196 "
+oA 680,928 2 0305 Aring
+char197 "
+AE 1260,681 2 0306 AE
+char198 "
+,C 740,698,200 2 0307 Ccedilla
+char199 "
+`E 720,886 2 0310 Egrave
+char200 "
+'E 720,886 2 0311 Eacute
+char201 "
+^E 720,882 2 0312 Ecircumflex
+char202 "
+:E 720,871 2 0313 Edieresis
+char203 "
+`I 340,886 2 0314 Igrave
+char204 "
+'I 340,886 2 0315 Iacute
+char205 "
+^I 340,882 2 0316 Icircumflex
+char206 "
+:I 340,871 2 0317 Idieresis
+char207 "
+-D 800,681 2 0320 Eth
+char208 "
+~N 740,858 2 0321 Ntilde
+char209 "
+`O 800,886,17 2 0322 Ograve
+char210 "
+'O 800,886,17 2 0323 Oacute
+char211 "
+^O 800,882,17 2 0324 Ocircumflex
+char212 "
+~O 800,858,17 2 0325 Otilde
+char213 "
+:O 800,871,17 2 0326 Odieresis
+char214 "
+char215 600,513 0 0327 multiply
+/O 800,733,53 2 0330 Oslash
+char216 "
+`U 780,886,17 2 0331 Ugrave
+char217 "
+'U 780,886,17 2 0332 Uacute
+char218 "
+^U 780,882,17 2 0333 Ucircumflex
+char219 "
+:U 780,871,17 2 0334 Udieresis
+char220 "
+'Y 640,886 2 0335 Yacute
+char221 "
+TP 620,681 2 0336 Thorn
+char222 "
+ss 660,698,110 2 0337 germandbls
+char223 "
+`a 580,689,8 2 0340 agrave
+char224 "
+'a 580,689,8 2 0341 aacute
+char225 "
+^a 580,685,8 2 0342 acircumflex
+char226 "
+~a 580,661,8 0 0343 atilde
+char227 "
+:a 580,674,8 2 0344 adieresis
+char228 "
+oa 580,731,8 2 0345 aring
+char229 "
+ae 860,494,8 0 0346 ae
+char230 "
+,c 520,494,200 0 0347 ccedilla
+char231 "
+`e 520,689,8 2 0350 egrave
+char232 "
+'e 520,689,8 2 0351 eacute
+char233 "
+^e 520,685,8 2 0352 ecircumflex
+char234 "
+:e 520,674,8 2 0353 edieresis
+char235 "
+`i 300,689 2 0354 igrave
+char236 "
+'i 300,689 2 0355 iacute
+char237 "
+^i 300,685 2 0356 icircumflex
+char238 "
+:i 300,674 2 0357 idieresis
+char239 "
+Sd 560,734,8 2 0360 eth
+char240 "
+~n 660,661 0 0361 ntilde
+char241 "
+`o 560,689,8 2 0362 ograve
+char242 "
+'o 560,689,8 2 0363 oacute
+char243 "
+^o 560,685,8 2 0364 ocircumflex
+char244 "
+~o 560,661,8 0 0365 otilde
+char245 "
+:o 560,674,8 2 0366 odieresis
+char246 "
+char247 600,514 0 0367 divide
+/o 560,534,40 0 0370 oslash
+char248 "
+`u 680,689,8 2 0371 ugrave
+char249 "
+'u 680,689,8 2 0372 uacute
+char250 "
+^u 680,685,8 2 0373 ucircumflex
+char251 "
+:u 680,674,8 2 0374 udieresis
+char252 "
+'y 540,689,236 3 0375 yacute
+char253 "
+Tp 620,717,228 3 0376 thorn
+char254 "
+:y 540,674,236 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/CB b/gnu/usr.bin/groff/devices/devps/CB
new file mode 100644
index 000000000000..c199fd93f9e6
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/CB
@@ -0,0 +1,336 @@
+name CB
+internalname Courier-Bold
+spacewidth 600
+encoding text.enc
+charset
+ha 600,616 2 0000 asciicircum
+ti 600,356 0 0001 asciitilde
+vS 600,790,22 2 0002 Scaron
+vZ 600,790 2 0003 Zcaron
+vs 600,667,17 2 0004 scaron
+vz 600,667 2 0005 zcaron
+:Y 600,748 2 0006 Ydieresis
+tm 600,562 2 0007 trademark
+aq 600,562 2 0010 quotesingle
+space 600 0 0040
+! 600,572,15 2 0041 exclam
+" 600,562 2 0042 quotedbl
+# 600,651,45 2 0043 numbersign
+sh "
+$ 600,666,126 2 0044 dollar
+Do "
+% 600,616,15 2 0045 percent
+& 600,543,15 0 0046 ampersand
+' 600,562 2 0047 quoteright
+( 600,616,102 2 0050 parenleft
+) 600,616,102 2 0051 parenright
+* 600,601 2 0052 asterisk
++ 600,478 0 0053 plus
+, 600,174,111 0 0054 comma
+- 600,313 0 0055 hyphen
+hy "
+char173 "
+. 600,171,15 0 0056 period
+/ 600,626,77 2 0057 slash
+sl "
+0 600,616,15 2 0060 zero
+1 600,616 2 0061 one
+2 600,616 2 0062 two
+3 600,616,15 2 0063 three
+4 600,616 2 0064 four
+5 600,601,15 2 0065 five
+6 600,616,15 2 0066 six
+7 600,601 2 0067 seven
+8 600,616,15 2 0070 eight
+9 600,616,15 2 0071 nine
+: 600,425,15 0 0072 colon
+; 600,425,111 0 0073 semicolon
+< 600,501 0 0074 less
+= 600,398 0 0075 equal
+> 600,501 0 0076 greater
+? 600,580,14 2 0077 question
+@ 600,616,15 2 0100 at
+at "
+A 600,562 2 0101 A
+B 600,562 2 0102 B
+C 600,580,18 2 0103 C
+D 600,562 2 0104 D
+E 600,562 2 0105 E
+F 600,562 2 0106 F
+G 600,580,18 2 0107 G
+H 600,562 2 0110 H
+I 600,562 2 0111 I
+J 600,562,18 2 0112 J
+K 600,562 2 0113 K
+L 600,562 2 0114 L
+M 600,562 2 0115 M
+N 600,562,12 2 0116 N
+O 600,580,18 2 0117 O
+P 600,562 2 0120 P
+Q 600,580,138 2 0121 Q
+R 600,562 2 0122 R
+S 600,582,22 2 0123 S
+T 600,562 2 0124 T
+U 600,562,18 2 0125 U
+V 600,562 2 0126 V
+W 600,562 2 0127 W
+X 600,562 2 0130 X
+Y 600,562 2 0131 Y
+Z 600,562 2 0132 Z
+[ 600,616,102 2 0133 bracketleft
+lB "
+\ 600,626,77 2 0134 backslash
+rs "
+] 600,616,102 2 0135 bracketright
+rB "
+a^ 600,657 2 0136 circumflex
+^ "
+_ 600,0,125 0 0137 underscore
+` 600,562 2 0140 quoteleft
+oq "
+a 600,454,15 0 0141 a
+b 600,626,15 2 0142 b
+c 600,459,15 0 0143 c
+d 600,626,15 2 0144 d
+e 600,454,15 0 0145 e
+f 600,626 2 0146 f
+g 600,454,146 1 0147 g
+h 600,626 2 0150 h
+i 600,658 2 0151 i
+j 600,658,146 3 0152 j
+k 600,626 2 0153 k
+l 600,626 2 0154 l
+m 600,454 0 0155 m
+n 600,454 0 0156 n
+o 600,454,15 0 0157 o
+p 600,454,142 1 0160 p
+q 600,454,142 1 0161 q
+r 600,454 0 0162 r
+s 600,459,17 0 0163 s
+t 600,562,15 2 0164 t
+u 600,439,15 0 0165 u
+v 600,439 0 0166 v
+w 600,439 0 0167 w
+x 600,439 0 0170 x
+y 600,439,142 1 0171 y
+z 600,439 0 0172 z
+lC 600,616,102 2 0173 braceleft
+{ "
+ba 600,750,250 3 0174 bar
+| "
+rC 600,616,102 2 0175 braceright
+} "
+a~ 600,636 2 0176 tilde
+~ "
+bq 600,143,142 1 0200 quotesinglbase
+Fo 600,446 0 0201 guillemotleft
+char171 "
+Fc 600,446 0 0202 guillemotright
+char187 "
+bu 600,430 0 0203 bullet
+Fn 600,616,131 2 0204 florin
+f/ 600,661,60 2 0205 fraction
+%0 600,616,15 2 0206 perthousand
+dg 600,580,70 2 0207 dagger
+dd 600,580,70 2 0210 daggerdbl
+en 600,313 0 0211 endash
+em 600,313 0 0212 emdash
+fi 600,626 2 0214 fi
+fl 600,626 2 0215 fl
+.i 600,439 0 0220 dotlessi
+ga 600,661 2 0222 grave
+a" 600,661 2 0223 hungarumlaut
+a. 600,625 2 0224 dotaccent
+ab 600,631 2 0225 breve
+ah 600,667 2 0226 caron
+ao 600,678 2 0227 ring
+ho 600,0,199 1 0230 ogonek
+lq 600,562 2 0231 quotedblleft
+rq 600,562 2 0232 quotedblright
+oe 600,454,15 0 0233 oe
+/l 600,626 2 0234 lslash
+Bq 600,143,142 1 0235 quotedblbase
+OE 600,562 2 0236 OE
+/L 600,562 2 0237 Lslash
+r! 600,449,146 1 0241 exclamdown
+char161 "
+ct 600,614,49 2 0242 cent
+char162 "
+Po 600,611,28 2 0243 sterling
+char163 "
+Cs 600,517 0 0244 currency
+char164 "
+Ye 600,562 2 0245 yen
+char165 "
+bb 600,675,175 3 0246 brokenbar
+char166 "
+sc 600,580,70 2 0247 section
+char167 "
+ad 600,625 2 0250 dieresis
+char168 "
+co 600,580,18 2 0251 copyright
+char169 "
+Of 600,580 2 0252 ordfeminine
+char170 "
+fo 600,446 0 0253 guilsinglleft
+no 600,413 0 0254 logicalnot
+char172 "
+\- 600,313 0 0255 minus
+rg 600,580,18 2 0256 registered
+char174 "
+a- 600,585 2 0257 macron
+char175 "
+de 600,616 2 0260 degree
+char176 "
+char177 600,515 0 0261 plusminus
+S2 600,616 2 0262 twosuperior
+char178 "
+S3 600,616 2 0263 threesuperior
+char179 "
+aa 600,661 2 0264 acute
+char180 "
+char181 600,439,142 1 0265 mu
+ps 600,580,70 2 0266 paragraph
+char182 "
+char183 600,351 0 0267 periodcentered
+ac 600,0,206 1 0270 cedilla
+char184 "
+S1 600,616 2 0271 onesuperior
+char185 "
+Om 600,580 2 0272 ordmasculine
+char186 "
+fc 600,446 0 0273 guilsinglright
+14 600,661,60 2 0274 onequarter
+char188 "
+12 600,661,60 2 0275 onehalf
+char189 "
+34 600,661,60 2 0276 threequarters
+char190 "
+r? 600,449,146 1 0277 questiondown
+char191 "
+`A 600,784 2 0300 Agrave
+char192 "
+'A 600,784 2 0301 Aacute
+char193 "
+^A 600,780 2 0302 Acircumflex
+char194 "
+~A 600,759 2 0303 Atilde
+char195 "
+:A 600,748 2 0304 Adieresis
+char196 "
+oA 600,801 2 0305 Aring
+char197 "
+AE 600,562 2 0306 AE
+char198 "
+,C 600,580,206 3 0307 Ccedilla
+char199 "
+`E 600,784 2 0310 Egrave
+char200 "
+'E 600,784 2 0311 Eacute
+char201 "
+^E 600,780 2 0312 Ecircumflex
+char202 "
+:E 600,748 2 0313 Edieresis
+char203 "
+`I 600,784 2 0314 Igrave
+char204 "
+'I 600,784 2 0315 Iacute
+char205 "
+^I 600,780 2 0316 Icircumflex
+char206 "
+:I 600,748 2 0317 Idieresis
+char207 "
+-D 600,562 2 0320 Eth
+char208 "
+~N 600,759,12 2 0321 Ntilde
+char209 "
+`O 600,784,18 2 0322 Ograve
+char210 "
+'O 600,784,18 2 0323 Oacute
+char211 "
+^O 600,780,18 2 0324 Ocircumflex
+char212 "
+~O 600,759,18 2 0325 Otilde
+char213 "
+:O 600,748,18 2 0326 Odieresis
+char214 "
+char215 600,478 0 0327 multiply
+/O 600,584,22 2 0330 Oslash
+char216 "
+`U 600,784,18 2 0331 Ugrave
+char217 "
+'U 600,784,18 2 0332 Uacute
+char218 "
+^U 600,780,18 2 0333 Ucircumflex
+char219 "
+:U 600,748,18 2 0334 Udieresis
+char220 "
+'Y 600,784 2 0335 Yacute
+char221 "
+TP 600,562 2 0336 Thorn
+char222 "
+ss 600,626,15 2 0337 germandbls
+char223 "
+`a 600,661,15 2 0340 agrave
+char224 "
+'a 600,661,15 2 0341 aacute
+char225 "
+^a 600,657,15 2 0342 acircumflex
+char226 "
+~a 600,636,15 2 0343 atilde
+char227 "
+:a 600,625,15 2 0344 adieresis
+char228 "
+oa 600,678,15 2 0345 aring
+char229 "
+ae 600,454,15 0 0346 ae
+char230 "
+,c 600,459,206 1 0347 ccedilla
+char231 "
+`e 600,661,15 2 0350 egrave
+char232 "
+'e 600,661,15 2 0351 eacute
+char233 "
+^e 600,657,15 2 0352 ecircumflex
+char234 "
+:e 600,625,15 2 0353 edieresis
+char235 "
+`i 600,661 2 0354 igrave
+char236 "
+'i 600,661 2 0355 iacute
+char237 "
+^i 600,657 2 0356 icircumflex
+char238 "
+:i 600,625 2 0357 idieresis
+char239 "
+Sd 600,626,27 2 0360 eth
+char240 "
+~n 600,636 2 0361 ntilde
+char241 "
+`o 600,661,15 2 0362 ograve
+char242 "
+'o 600,661,15 2 0363 oacute
+char243 "
+^o 600,657,15 2 0364 ocircumflex
+char244 "
+~o 600,636,15 2 0365 otilde
+char245 "
+:o 600,625,15 2 0366 odieresis
+char246 "
+char247 600,500 0 0367 divide
+/o 600,463,24 0 0370 oslash
+char248 "
+`u 600,661,15 2 0371 ugrave
+char249 "
+'u 600,661,15 2 0372 uacute
+char250 "
+^u 600,657,15 2 0373 ucircumflex
+char251 "
+:u 600,625,15 2 0374 udieresis
+char252 "
+'y 600,661,142 3 0375 yacute
+char253 "
+Tp 600,626,142 3 0376 thorn
+char254 "
+:y 600,625,142 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/CBI b/gnu/usr.bin/groff/devices/devps/CBI
new file mode 100644
index 000000000000..802e3366d7ac
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/CBI
@@ -0,0 +1,337 @@
+name CBI
+internalname Courier-BoldOblique
+slant 12
+spacewidth 600
+encoding text.enc
+charset
+ha 600,616,0,5,-121,5 2 0000 asciicircum
+ti 600,356,0,39,-70,39 0 0001 asciitilde
+vS 600,790,22,122,-4,75 2 0002 Scaron
+vZ 600,790,0,109,-12,75 2 0003 Zcaron
+vs 600,667,17,82,-17,75 2 0004 scaron
+vz 600,667,0,82,-31,75 2 0005 zcaron
+:Y 600,748,0,158,-59,75 2 0006 Ydieresis
+tm 600,562,0,318,-36,75 2 0007 trademark
+aq 600,562,0,0,-254 2 0010 quotesingle
+space 600 0 0040
+! 600,572,15,0,-166 2 0041 exclam
+" 600,562,0,34,-162,34 2 0042 quotedbl
+# 600,651,45,90,-38,75 2 0043 numbersign
+sh "
+$ 600,666,126,79,-37,75 2 0044 dollar
+Do "
+% 600,616,15,74,-52,74 2 0045 percent
+& 600,543,15,44,-12,44 0 0046 ampersand
+' 600,562,0,0,-180 2 0047 quoteright
+( 600,616,102,42,-216,42 2 0050 parenleft
+) 600,616,102,0,-67 2 0051 parenright
+* 600,601,0,47,-129,47 2 0052 asterisk
++ 600,478,0,46,-64,46 0 0053 plus
+, 600,174,111,0,-49 0 0054 comma
+- 600,313,0,17,-93,17 0 0055 hyphen
+hy "
+char173 "
+. 600,171,15,0,-157 0 0056 period
+/ 600,626,77,76,-41,75 2 0057 slash
+sl "
+0 600,616,15,42,-86,42 2 0060 zero
+1 600,616,0,11,-43,11 2 0061 one
+2 600,616,0,43,-11,43 2 0062 two
+3 600,616,15,21,-22,21 2 0063 three
+4 600,616,0,8,-32,8 2 0064 four
+5 600,601,15,71,-27,71 2 0065 five
+6 600,616,15,102,-86,75 2 0066 six
+7 600,601,0,72,-97,72 2 0067 seven
+8 600,616,15,54,-65,54 2 0070 eight
+9 600,616,15,42,-26,42 2 0071 nine
+: 600,425,15,0,-156 0 0072 colon
+; 600,425,111,0,-49 0 0073 semicolon
+< 600,501,0,62,-71,62 0 0074 less
+= 600,398,0,64,-46,64 0 0075 equal
+> 600,501,0,39,-47,39 0 0076 greater
+? 600,580,14,41,-133,41 2 0077 question
+@ 600,616,15,91,-16,75 2 0100 at
+at "
+A 600,562,0,81,59,75 2 0101 A
+B 600,562,0,79,20,75 2 0102 B
+C 600,580,18,124,-25,75 2 0103 C
+D 600,562,0,114,20,75 2 0104 D
+E 600,562,0,119,25,75 2 0105 E
+F 600,562,0,133,11,75 2 0106 F
+G 600,580,18,124,-25,75 2 0107 G
+H 600,562,0,149,30,75 2 0110 H
+I 600,562,0,92,-27,75 2 0111 I
+J 600,562,18,170,-9,75 2 0112 J
+K 600,562,0,141,29,75 2 0113 K
+L 600,562,0,85,11,75 2 0114 L
+M 600,562,0,171,52,75 2 0115 M
+N 600,562,12,179,42,75 2 0116 N
+O 600,580,18,95,-24,75 2 0117 O
+P 600,562,0,92,2,75 2 0120 P
+Q 600,580,138,86,-34,75 2 0121 Q
+R 600,562,0,67,26,67 2 0122 R
+S 600,582,22,122,-4,75 2 0123 S
+T 600,562,0,128,-36,75 2 0124 T
+U 600,562,18,165,-51,75 2 0125 U
+V 600,562,0,182,-34,75 2 0126 V
+W 600,562,0,187,-34,75 2 0127 W
+X 600,562,0,139,38,75 2 0130 X
+Y 600,562,0,158,-59,75 2 0131 Y
+Z 600,562,0,86,-12,75 2 0132 Z
+[ 600,616,102,56,-173,56 2 0133 bracketleft
+lB "
+\ 600,626,77,0,-173 2 0134 backslash
+rs "
+] 600,616,102,0,-53 2 0135 bracketright
+rB "
+a^ 600,657,0,56,-162,56 2 0136 circumflex
+^ "
+_ 600,0,125,34,77,34 0 0137 underscore
+` 600,562,0,0,-247 2 0140 quoteleft
+oq "
+a 600,454,15,42,-12,42 0 0141 a
+b 600,626,15,86,37,75 2 0142 b
+c 600,459,15,81,-31,75 0 0143 c
+d 600,626,15,94,-11,75 2 0144 d
+e 600,454,15,54,-31,54 0 0145 e
+f 600,626,0,127,-33,75 2 0146 f
+g 600,454,146,123,9,75 1 0147 g
+h 600,626,0,64,32,64 2 0150 h
+i 600,658,0,0,-27 2 0151 i
+j 600,658,146,30,13,30 3 0152 j
+k 600,626,0,92,17,75 2 0153 k
+l 600,626,0,0,-27 2 0154 l
+m 600,454,0,98,72,75 0 0155 m
+n 600,454,0,64,32,64 0 0156 n
+o 600,454,15,72,-21,72 0 0157 o
+p 600,454,142,72,81,72 1 0160 p
+q 600,454,142,134,-11,75 1 0161 q
+r 600,454,0,104,3,75 0 0162 r
+s 600,459,17,57,-17,57 0 0163 s
+t 600,562,15,16,-68,16 2 0164 t
+u 600,439,15,41,-20,41 0 0165 u
+v 600,439,0,144,-20,75 0 0166 v
+w 600,439,0,161,-3,75 0 0167 w
+x 600,439,0,120,44,75 0 0170 x
+y 600,439,142,144,70,75 1 0171 y
+z 600,439,0,63,-31,63 0 0172 z
+lC 600,616,102,45,-154,45 2 0173 braceleft
+{ "
+ba 600,750,250,0,-152 3 0174 bar
+| "
+rC 600,616,102,0,-64 2 0175 braceright
+} "
+a~ 600,636,0,92,-150,75 2 0176 tilde
+~ "
+bq 600,143,142,0,-95 1 0200 quotesinglbase
+Fo 600,446,0,88,-13,75 0 0201 guillemotleft
+char171 "
+Fc 600,446,0,97,-22,75 0 0202 guillemotright
+char187 "
+bu 600,430,0,0,-147 0 0203 bullet
+Fn 600,616,131,151,106,75 2 0204 florin
+f/ 600,661,60,157,28,75 2 0205 fraction
+%0 600,616,15,192,94,75 2 0206 perthousand
+dg 600,580,70,36,-126,36 2 0207 dagger
+dd 600,580,70,36,-72,36 2 0210 daggerdbl
+en 600,313,0,52,-58,52 0 0211 endash
+em 600,313,0,127,17,75 0 0212 emdash
+fi 600,626,0,93,38,75 2 0214 fi
+fl 600,626,0,93,38,75 2 0215 fl
+.i 600,439,0,0,-27 0 0220 dotlessi
+ga 600,661,0,0,-222 2 0222 grave
+a" 600,661,0,178,-122,75 2 0223 hungarumlaut
+a. 600,625,0,0,-296 2 0224 dotaccent
+ab 600,631,0,101,-167,75 2 0225 breve
+ah 600,667,0,82,-188,75 2 0226 caron
+ao 600,678,0,0,-269 2 0227 ring
+ho 600,0,199,0,-94 1 0230 ogonek
+lq 600,562,0,44,-140,44 2 0231 quotedblleft
+rq 600,562,0,94,-70,75 2 0232 quotedblright
+oe 600,454,15,111,31,75 0 0233 oe
+/l 600,626,0,28,-27,28 2 0234 lslash
+Bq 600,143,142,9,15,9 1 0235 quotedblbase
+OE 600,562,0,150,24,75 2 0236 OE
+/L 600,562,0,85,11,75 2 0237 Lslash
+r! 600,449,146,0,-147 1 0241 exclamdown
+char161 "
+ct 600,614,49,54,-71,54 2 0242 cent
+char162 "
+Po 600,611,28,100,-57,75 2 0243 sterling
+char163 "
+Cs 600,517,0,93,-27,75 0 0244 currency
+char164 "
+Ye 600,562,0,159,-48,75 2 0245 yen
+char165 "
+bb 600,675,175,0,-168 3 0246 brokenbar
+char166 "
+sc 600,580,70,69,-24,69 2 0247 section
+char167 "
+ad 600,625,0,42,-194,42 2 0250 dieresis
+char168 "
+co 600,580,18,117,-3,75 2 0251 copyright
+char169 "
+Of 600,580,0,0,-139 2 0252 ordfeminine
+char170 "
+fo 600,446,0,0,-146 0 0253 guilsinglleft
+no 600,413,0,67,-85,67 0 0254 logicalnot
+char172 "
+\- 600,313,0,46,-64,46 0 0255 minus
+rg 600,580,18,117,-3,75 2 0256 registered
+char174 "
+a- 600,585,0,86,-145,75 2 0257 macron
+char175 "
+de 600,616,0,19,-123,19 2 0260 degree
+char176 "
+char177 600,515,0,64,-26,64 0 0261 plusminus
+S2 600,616,0,0,-142 2 0262 twosuperior
+char178 "
+S3 600,616,0,0,-143 2 0263 threesuperior
+char179 "
+aa 600,661,0,58,-263,58 2 0264 acute
+char180 "
+char181 600,439,142,41,0,41 1 0265 mu
+ps 600,580,70,149,-11,75 2 0266 paragraph
+char182 "
+char183 600,351,0,0,-199 0 0267 periodcentered
+ac 600,0,206,0,-119 1 0270 cedilla
+char184 "
+S1 600,616,0,0,-163 2 0271 onesuperior
+char185 "
+Om 600,580,0,0,-139 2 0272 ordmasculine
+char186 "
+fc 600,446,0,0,-116 0 0273 guilsinglright
+14 600,661,60,156,36,75 2 0274 onequarter
+char188 "
+12 600,661,60,165,27,75 2 0275 onehalf
+char189 "
+34 600,661,60,148,42,75 2 0276 threequarters
+char190 "
+r? 600,449,146,0,-51 1 0277 questiondown
+char191 "
+`A 600,784,0,81,59,75 2 0300 Agrave
+char192 "
+'A 600,784,0,115,59,75 2 0301 Aacute
+char193 "
+^A 600,780,0,81,59,75 2 0302 Acircumflex
+char194 "
+~A 600,759,0,88,59,75 2 0303 Atilde
+char195 "
+:A 600,748,0,81,59,75 2 0304 Adieresis
+char196 "
+oA 600,801,0,81,59,75 2 0305 Aring
+char197 "
+AE 600,562,0,157,79,75 2 0306 AE
+char198 "
+,C 600,580,206,124,-24,75 3 0307 Ccedilla
+char199 "
+`E 600,784,0,119,25,75 2 0310 Egrave
+char200 "
+'E 600,784,0,119,25,75 2 0311 Eacute
+char201 "
+^E 600,780,0,119,25,75 2 0312 Ecircumflex
+char202 "
+:E 600,748,0,119,25,75 2 0313 Edieresis
+char203 "
+`I 600,784,0,92,-27,75 2 0314 Igrave
+char204 "
+'I 600,784,0,92,-27,75 2 0315 Iacute
+char205 "
+^I 600,780,0,92,-27,75 2 0316 Icircumflex
+char206 "
+:I 600,748,0,92,-27,75 2 0317 Idieresis
+char207 "
+-D 600,562,0,114,20,75 2 0320 Eth
+char208 "
+~N 600,759,12,179,42,75 2 0321 Ntilde
+char209 "
+`O 600,784,18,95,-24,75 2 0322 Ograve
+char210 "
+'O 600,784,18,95,-24,75 2 0323 Oacute
+char211 "
+^O 600,780,18,95,-24,75 2 0324 Ocircumflex
+char212 "
+~O 600,759,18,118,-24,75 2 0325 Otilde
+char213 "
+:O 600,748,18,95,-24,75 2 0326 Odieresis
+char214 "
+char215 600,478,0,56,-55,56 0 0327 multiply
+/O 600,584,22,122,2,75 2 0330 Oslash
+char216 "
+`U 600,784,18,165,-51,75 2 0331 Ugrave
+char217 "
+'U 600,784,18,165,-51,75 2 0332 Uacute
+char218 "
+^U 600,780,18,165,-51,75 2 0333 Ucircumflex
+char219 "
+:U 600,748,18,165,-51,75 2 0334 Udieresis
+char220 "
+'Y 600,784,0,158,-59,75 2 0335 Yacute
+char221 "
+TP 600,562,0,69,2,69 2 0336 Thorn
+char222 "
+ss 600,626,15,78,28,75 2 0337 germandbls
+char223 "
+`a 600,661,15,42,-12,42 2 0340 agrave
+char224 "
+'a 600,661,15,58,-12,58 2 0341 aacute
+char225 "
+^a 600,657,15,42,-12,42 2 0342 acircumflex
+char226 "
+~a 600,636,15,92,-12,75 2 0343 atilde
+char227 "
+:a 600,625,15,42,-12,42 2 0344 adieresis
+char228 "
+oa 600,678,15,42,-12,42 2 0345 aring
+char229 "
+ae 600,454,15,101,29,75 0 0346 ae
+char230 "
+,c 600,459,206,81,-31,75 1 0347 ccedilla
+char231 "
+`e 600,661,15,54,-31,54 2 0350 egrave
+char232 "
+'e 600,661,15,58,-31,58 2 0351 eacute
+char233 "
+^e 600,657,15,56,-31,56 2 0352 ecircumflex
+char234 "
+:e 600,625,15,54,-31,54 2 0353 edieresis
+char235 "
+`i 600,661,0,0,-27 2 0354 igrave
+char236 "
+'i 600,661,0,58,-27,58 2 0355 iacute
+char237 "
+^i 600,657,0,16,-27,16 2 0356 icircumflex
+char238 "
+:i 600,625,0,2,-27,2 2 0357 idieresis
+char239 "
+Sd 600,626,27,111,-43,75 2 0360 eth
+char240 "
+~n 600,636,0,92,32,75 2 0361 ntilde
+char241 "
+`o 600,661,15,72,-21,72 2 0362 ograve
+char242 "
+'o 600,661,15,72,-21,72 2 0363 oacute
+char243 "
+^o 600,657,15,72,-21,72 2 0364 ocircumflex
+char244 "
+~o 600,636,15,92,-21,75 2 0365 otilde
+char245 "
+:o 600,625,15,72,-21,72 2 0366 odieresis
+char246 "
+char247 600,500,0,46,-64,46 0 0367 divide
+/o 600,463,24,87,-5,75 0 0370 oslash
+char248 "
+`u 600,661,15,41,-20,41 2 0371 ugrave
+char249 "
+'u 600,661,15,58,-20,58 2 0372 uacute
+char250 "
+^u 600,657,15,41,-20,41 2 0373 ucircumflex
+char251 "
+:u 600,625,15,41,-20,41 2 0374 udieresis
+char252 "
+'y 600,661,142,144,70,75 3 0375 yacute
+char253 "
+Tp 600,626,142,72,81,72 3 0376 thorn
+char254 "
+:y 600,625,142,144,70,75 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/CI b/gnu/usr.bin/groff/devices/devps/CI
new file mode 100644
index 000000000000..f63f1931e1db
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/CI
@@ -0,0 +1,337 @@
+name CI
+internalname Courier-Oblique
+slant 12
+spacewidth 600
+encoding text.enc
+charset
+ha 600,622,0,37,-125,37 2 0000 asciicircum
+ti 600,320,0,50,-66,50 0 0001 asciitilde
+vS 600,805,20,123,-26,72 2 0002 Scaron
+vZ 600,805,0,93,-36,72 2 0003 Zcaron
+vs 600,669,15,64,-28,64 2 0004 scaron
+vz 600,669,0,74,-49,72 2 0005 zcaron
+:Y 600,731,0,145,-83,72 2 0006 Ydieresis
+tm 600,562,0,192,-25,72 2 0007 trademark
+aq 600,562,0,0,-295 2 0010 quotesingle
+space 600 0 0040
+! 600,572,15,0,-193 2 0041 exclam
+" 600,562,0,0,-223 2 0042 quotedbl
+# 600,639,32,46,-83,46 2 0043 numbersign
+sh "
+$ 600,662,126,46,-58,46 2 0044 dollar
+Do "
+% 600,622,15,49,-84,49 2 0045 percent
+& 600,543,15,30,-37,30 0 0046 ampersand
+' 600,562,0,0,-233 2 0047 quoteright
+( 600,622,108,22,-263,22 2 0050 parenleft
+) 600,622,108,0,-87 2 0051 parenright
+* 600,607,0,30,-162,30 2 0052 asterisk
++ 600,470,0,30,-79,30 0 0053 plus
+, 600,122,112,0,-107 0 0054 comma
+- 600,285,0,8,-102,8 0 0055 hyphen
+hy "
+char173 "
+. 600,109,15,0,-188 0 0056 period
+/ 600,629,80,54,-62,54 2 0057 slash
+sl "
+0 600,622,15,25,-104,25 2 0060 zero
+1 600,622,0,0,-48 2 0061 one
+2 600,622,0,18,-20,18 2 0062 two
+3 600,622,15,0,-32 2 0063 three
+4 600,622,0,0,-58 2 0064 four
+5 600,607,15,39,-49,39 2 0065 five
+6 600,622,15,79,-105,72 2 0066 six
+7 600,607,0,62,-132,62 2 0067 seven
+8 600,622,15,38,-82,38 2 0070 eight
+9 600,622,15,24,-43,24 2 0071 nine
+: 600,385,15,0,-188 0 0072 colon
+; 600,385,112,0,-107 0 0073 semicolon
+< 600,472,0,60,-46,60 0 0074 less
+= 600,376,0,50,-59,50 0 0075 equal
+> 600,472,0,49,-35,49 0 0076 greater
+? 600,572,15,33,-172,33 2 0077 question
+@ 600,622,15,32,-77,32 2 0100 at
+at "
+A 600,562,0,57,47,57 2 0101 A
+B 600,562,0,66,7,66 2 0102 B
+C 600,580,18,105,-43,72 2 0103 C
+D 600,562,0,95,7,72 2 0104 D
+E 600,562,0,110,-3,72 2 0105 E
+F 600,562,0,110,-3,72 2 0106 F
+G 600,580,18,95,-33,72 2 0107 G
+H 600,562,0,137,18,72 2 0110 H
+I 600,562,0,73,-46,72 2 0111 I
+J 600,562,18,135,-2,72 2 0112 J
+K 600,562,0,121,12,72 2 0113 K
+L 600,562,0,57,3,57 2 0114 L
+M 600,562,0,165,46,72 2 0115 M
+N 600,562,13,162,43,72 2 0116 N
+O 600,580,18,75,-44,72 2 0117 O
+P 600,562,0,94,-29,72 2 0120 P
+Q 600,580,138,75,-45,72 2 0121 Q
+R 600,562,0,48,12,48 2 0122 R
+S 600,580,20,100,-26,72 2 0123 S
+T 600,562,0,115,-58,72 2 0124 T
+U 600,562,18,152,-75,72 2 0125 U
+V 600,562,13,173,-55,72 2 0126 V
+W 600,562,13,172,-56,72 2 0127 W
+X 600,562,0,125,27,72 2 0130 X
+Y 600,562,0,145,-83,72 2 0131 Y
+Z 600,562,0,60,-36,60 2 0132 Z
+[ 600,622,108,24,-196,24 2 0133 bracketleft
+lB "
+\ 600,629,80,0,-199 2 0134 backslash
+rs "
+] 600,622,108,0,-85 2 0135 bracketright
+rB "
+a^ 600,654,0,31,-179,31 2 0136 circumflex
+^ "
+_ 600,0,125,34,77,34 0 0137 underscore
+` 600,562,0,0,-293 2 0140 quoteleft
+oq "
+a 600,441,15,19,-26,19 0 0141 a
+b 600,629,15,75,21,72 2 0142 b
+c 600,441,15,58,-56,58 0 0143 c
+d 600,629,15,90,-35,72 2 0144 d
+e 600,441,15,48,-56,48 0 0145 e
+f 600,629,0,112,-64,72 2 0146 f
+g 600,441,157,107,-11,72 1 0147 g
+h 600,629,0,42,17,42 2 0150 h
+i 600,657,0,0,-45 2 0151 i
+j 600,657,157,0,-2 3 0152 j
+k 600,629,0,83,-8,72 2 0153 k
+l 600,629,0,0,-45 2 0154 l
+m 600,441,0,65,55,65 0 0155 m
+n 600,441,0,35,24,35 0 0156 n
+o 600,441,15,38,-52,38 0 0157 o
+p 600,441,157,55,74,55 1 0160 p
+q 600,441,157,132,-35,72 1 0161 q
+r 600,441,0,86,-10,72 0 0162 r
+s 600,441,15,34,-28,34 0 0163 s
+t 600,561,15,11,-117,11 2 0164 t
+u 600,426,15,22,-51,22 0 0165 u
+v 600,426,10,131,-40,72 0 0166 v
+w 600,426,10,145,-26,72 0 0167 w
+x 600,426,0,105,30,72 0 0170 x
+y 600,426,157,133,54,72 1 0171 y
+z 600,426,0,43,-49,43 0 0172 z
+lC 600,622,108,19,-183,19 2 0173 braceleft
+{ "
+ba 600,750,250,0,-172 3 0174 bar
+| "
+rC 600,622,108,0,-90 2 0175 braceright
+} "
+a~ 600,606,0,79,-162,72 2 0176 tilde
+~ "
+bq 600,100,134,0,-135 0 0200 quotesinglbase
+Fo 600,446,0,102,-42,72 0 0201 guillemotleft
+char171 "
+Fc 600,446,0,68,-8,68 0 0202 guillemotright
+char187 "
+bu 600,383,0,0,-174 0 0203 bullet
+Fn 600,622,143,121,76,72 2 0204 florin
+f/ 600,665,57,96,-34,72 2 0205 fraction
+%0 600,622,15,77,-9,72 2 0206 perthousand
+dg 600,580,78,0,-167 2 0207 dagger
+dd 600,580,78,0,-113 2 0210 daggerdbl
+en 600,285,0,36,-74,36 0 0211 endash
+em 600,285,0,111,1,72 0 0212 emdash
+fi 600,629,0,69,47,69 2 0214 fi
+fl 600,629,0,69,47,69 2 0215 fl
+.i 600,426,0,0,-45 0 0220 dotlessi
+ga 600,672,0,0,-244 2 0222 grave
+a" 600,672,0,133,-189,72 2 0223 hungarumlaut
+a. 600,580,0,0,-310 2 0224 dotaccent
+ab 600,609,0,26,-229,26 2 0225 breve
+ah 600,669,0,64,-212,64 2 0226 caron
+ao 600,627,0,0,-282 2 0227 ring
+ho 600,0,151,0,-157 0 0230 ogonek
+lq 600,562,0,0,-212 2 0231 quotedblleft
+rq 600,562,0,26,-163,26 2 0232 quotedblright
+oe 600,441,15,65,-4,65 0 0233 oe
+/l 600,629,0,33,-45,33 2 0234 lslash
+Bq 600,100,134,0,-65 0 0235 quotedblbase
+OE 600,562,0,122,-9,72 2 0236 OE
+/L 600,562,0,57,3,57 2 0237 Lslash
+r! 600,430,157,0,-175 1 0241 exclamdown
+char161 "
+ct 600,614,49,38,-101,38 2 0242 cent
+char162 "
+Po 600,611,21,71,-74,71 2 0243 sterling
+char163 "
+Cs 600,506,0,78,-44,72 0 0244 currency
+char164 "
+Ye 600,562,0,143,-70,72 2 0245 yen
+char165 "
+bb 600,675,175,0,-188 3 0246 brokenbar
+char166 "
+sc 600,580,78,40,-54,40 2 0247 section
+char167 "
+ad 600,595,0,20,-212,20 2 0250 dieresis
+char168 "
+co 600,580,18,117,-3,72 2 0251 copyright
+char169 "
+Of 600,580,0,0,-159 2 0252 ordfeminine
+char170 "
+fo 600,446,0,0,-154 0 0253 guilsinglleft
+no 600,369,0,41,-105,41 0 0254 logicalnot
+char172 "
+\- 600,283,0,30,-79,30 0 0255 minus
+rg 600,580,18,117,-3,72 2 0256 registered
+char174 "
+a- 600,565,0,50,-182,50 2 0257 macron
+char175 "
+de 600,622,0,26,-164,26 2 0260 degree
+char176 "
+char177 600,558,0,44,-46,44 0 0261 plusminus
+S2 600,622,0,0,-180 2 0262 twosuperior
+char178 "
+S3 600,622,0,0,-163 2 0263 threesuperior
+char179 "
+aa 600,672,0,62,-298,62 2 0264 acute
+char180 "
+char181 600,426,157,22,-22,22 1 0265 mu
+ps 600,562,78,80,-50,72 2 0266 paragraph
+char182 "
+char183 600,327,0,0,-225 0 0267 periodcentered
+ac 600,10,151,0,-147 0 0270 cedilla
+char184 "
+S1 600,622,0,0,-181 2 0271 onesuperior
+char185 "
+Om 600,580,0,0,-160 2 0272 ordmasculine
+char186 "
+fc 600,446,0,0,-120 0 0273 guilsinglright
+14 600,665,57,124,-15,72 2 0274 onequarter
+char188 "
+12 600,665,57,119,-15,72 2 0275 onehalf
+char189 "
+34 600,666,56,109,-23,72 2 0276 threequarters
+char190 "
+r? 600,430,157,0,-55 1 0277 questiondown
+char191 "
+`A 600,793,0,57,47,57 2 0300 Agrave
+char192 "
+'A 600,793,0,108,47,72 2 0301 Aacute
+char193 "
+^A 600,775,0,57,47,57 2 0302 Acircumflex
+char194 "
+~A 600,732,0,106,47,72 2 0303 Atilde
+char195 "
+:A 600,731,0,57,47,57 2 0304 Adieresis
+char196 "
+oA 600,753,0,57,47,57 2 0305 Aring
+char197 "
+AE 600,562,0,105,47,72 2 0306 AE
+char198 "
+,C 600,580,151,108,-43,72 2 0307 Ccedilla
+char199 "
+`E 600,793,0,110,-3,72 2 0310 Egrave
+char200 "
+'E 600,793,0,118,-3,72 2 0311 Eacute
+char201 "
+^E 600,775,0,110,-3,72 2 0312 Ecircumflex
+char202 "
+:E 600,731,0,110,-3,72 2 0313 Edieresis
+char203 "
+`I 600,793,0,73,-46,72 2 0314 Igrave
+char204 "
+'I 600,793,0,88,-46,72 2 0315 Iacute
+char205 "
+^I 600,775,0,73,-46,72 2 0316 Icircumflex
+char206 "
+:I 600,731,0,73,-46,72 2 0317 Idieresis
+char207 "
+-D 600,562,0,95,7,72 2 0320 Eth
+char208 "
+~N 600,732,13,162,43,72 2 0321 Ntilde
+char209 "
+`O 600,793,18,75,-44,72 2 0322 Ograve
+char210 "
+'O 600,793,18,88,-44,72 2 0323 Oacute
+char211 "
+^O 600,775,18,75,-44,72 2 0324 Ocircumflex
+char212 "
+~O 600,732,18,106,-44,72 2 0325 Otilde
+char213 "
+:O 600,731,18,75,-44,72 2 0326 Odieresis
+char214 "
+char215 600,470,0,57,-53,57 0 0327 multiply
+/O 600,629,80,75,-44,72 2 0330 Oslash
+char216 "
+`U 600,793,18,152,-75,72 2 0331 Ugrave
+char217 "
+'U 600,793,18,152,-75,72 2 0332 Uacute
+char218 "
+^U 600,775,18,152,-75,72 2 0333 Ucircumflex
+char219 "
+:U 600,731,18,152,-75,72 2 0334 Udieresis
+char220 "
+'Y 600,793,0,145,-83,72 2 0335 Yacute
+char221 "
+TP 600,562,0,56,-29,56 2 0336 Thorn
+char222 "
+ss 600,629,15,67,2,67 2 0337 germandbls
+char223 "
+`a 600,672,15,19,-26,19 2 0340 agrave
+char224 "
+'a 600,672,15,62,-26,62 2 0341 aacute
+char225 "
+^a 600,654,15,31,-26,31 2 0342 acircumflex
+char226 "
+~a 600,606,15,79,-26,72 2 0343 atilde
+char227 "
+:a 600,595,15,20,-26,20 2 0344 adieresis
+char228 "
+oa 600,627,15,19,-26,19 2 0345 aring
+char229 "
+ae 600,441,15,76,9,72 0 0346 ae
+char230 "
+,c 600,441,151,64,-56,64 0 0347 ccedilla
+char231 "
+`e 600,672,15,48,-56,48 2 0350 egrave
+char232 "
+'e 600,672,15,62,-56,62 2 0351 eacute
+char233 "
+^e 600,654,15,48,-56,48 2 0352 ecircumflex
+char234 "
+:e 600,595,15,48,-56,48 2 0353 edieresis
+char235 "
+`i 600,672,0,0,-45 2 0354 igrave
+char236 "
+'i 600,672,0,62,-45,62 2 0355 iacute
+char237 "
+^i 600,654,0,1,-45,1 2 0356 icircumflex
+char238 "
+:i 600,595,0,0,-45 2 0357 idieresis
+char239 "
+Sd 600,629,15,89,-52,72 2 0360 eth
+char240 "
+~n 600,606,0,79,24,72 2 0361 ntilde
+char241 "
+`o 600,672,15,38,-52,38 2 0362 ograve
+char242 "
+'o 600,672,15,62,-52,62 2 0363 oacute
+char243 "
+^o 600,654,15,38,-52,38 2 0364 ocircumflex
+char244 "
+~o 600,606,15,79,-52,72 2 0365 otilde
+char245 "
+:o 600,595,15,38,-52,38 2 0366 odieresis
+char246 "
+char247 600,467,0,23,-86,23 0 0367 divide
+/o 600,506,80,38,-52,38 0 0370 oslash
+char248 "
+`u 600,672,15,22,-51,22 2 0371 ugrave
+char249 "
+'u 600,672,15,52,-51,52 2 0372 uacute
+char250 "
+^u 600,654,15,22,-51,22 2 0373 ucircumflex
+char251 "
+:u 600,595,15,22,-51,22 2 0374 udieresis
+char252 "
+'y 600,672,157,133,54,72 3 0375 yacute
+char253 "
+Tp 600,629,157,55,74,55 3 0376 thorn
+char254 "
+:y 600,595,157,133,54,72 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/CR b/gnu/usr.bin/groff/devices/devps/CR
new file mode 100644
index 000000000000..c6a92a16d973
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/CR
@@ -0,0 +1,336 @@
+name CR
+internalname Courier
+spacewidth 600
+encoding text.enc
+charset
+ha 600,622 2 0000 asciicircum
+ti 600,320 0 0001 asciitilde
+vS 600,805,20 2 0002 Scaron
+vZ 600,805 2 0003 Zcaron
+vs 600,669,15 2 0004 scaron
+vz 600,669 2 0005 zcaron
+:Y 600,731 2 0006 Ydieresis
+tm 600,562 2 0007 trademark
+aq 600,562 2 0010 quotesingle
+space 600 0 0040
+! 600,572,15 2 0041 exclam
+" 600,562 2 0042 quotedbl
+# 600,639,32 2 0043 numbersign
+sh "
+$ 600,662,126 2 0044 dollar
+Do "
+% 600,622,15 2 0045 percent
+& 600,543,15 0 0046 ampersand
+' 600,562 2 0047 quoteright
+( 600,622,108 2 0050 parenleft
+) 600,622,108 2 0051 parenright
+* 600,607 2 0052 asterisk
++ 600,470 0 0053 plus
+, 600,122,112 0 0054 comma
+- 600,285 0 0055 hyphen
+hy "
+char173 "
+. 600,109,15 0 0056 period
+/ 600,629,80 2 0057 slash
+sl "
+0 600,622,15 2 0060 zero
+1 600,622 2 0061 one
+2 600,622 2 0062 two
+3 600,622,15 2 0063 three
+4 600,622 2 0064 four
+5 600,607,15 2 0065 five
+6 600,622,15 2 0066 six
+7 600,607 2 0067 seven
+8 600,622,15 2 0070 eight
+9 600,622,15 2 0071 nine
+: 600,385,15 0 0072 colon
+; 600,385,112 0 0073 semicolon
+< 600,472 0 0074 less
+= 600,376 0 0075 equal
+> 600,472 0 0076 greater
+? 600,572,15 2 0077 question
+@ 600,622,15 2 0100 at
+at "
+A 600,562 2 0101 A
+B 600,562 2 0102 B
+C 600,580,18 2 0103 C
+D 600,562 2 0104 D
+E 600,562 2 0105 E
+F 600,562 2 0106 F
+G 600,580,18 2 0107 G
+H 600,562 2 0110 H
+I 600,562 2 0111 I
+J 600,562,18 2 0112 J
+K 600,562 2 0113 K
+L 600,562 2 0114 L
+M 600,562 2 0115 M
+N 600,562,13 2 0116 N
+O 600,580,18 2 0117 O
+P 600,562 2 0120 P
+Q 600,580,138 2 0121 Q
+R 600,562 2 0122 R
+S 600,580,20 2 0123 S
+T 600,562 2 0124 T
+U 600,562,18 2 0125 U
+V 600,562,13 2 0126 V
+W 600,562,13 2 0127 W
+X 600,562 2 0130 X
+Y 600,562 2 0131 Y
+Z 600,562 2 0132 Z
+[ 600,622,108 2 0133 bracketleft
+lB "
+\ 600,629,80 2 0134 backslash
+rs "
+] 600,622,108 2 0135 bracketright
+rB "
+a^ 600,654 2 0136 circumflex
+^ "
+_ 600,0,125 0 0137 underscore
+` 600,562 2 0140 quoteleft
+oq "
+a 600,441,15 0 0141 a
+b 600,629,15 2 0142 b
+c 600,441,15 0 0143 c
+d 600,629,15 2 0144 d
+e 600,441,15 0 0145 e
+f 600,629 2 0146 f
+g 600,441,157 1 0147 g
+h 600,629 2 0150 h
+i 600,657 2 0151 i
+j 600,657,157 3 0152 j
+k 600,629 2 0153 k
+l 600,629 2 0154 l
+m 600,441 0 0155 m
+n 600,441 0 0156 n
+o 600,441,15 0 0157 o
+p 600,441,157 1 0160 p
+q 600,441,157 1 0161 q
+r 600,441 0 0162 r
+s 600,441,15 0 0163 s
+t 600,561,15 2 0164 t
+u 600,426,15 0 0165 u
+v 600,426,10 0 0166 v
+w 600,426,10 0 0167 w
+x 600,426 0 0170 x
+y 600,426,157 1 0171 y
+z 600,426 0 0172 z
+lC 600,622,108 2 0173 braceleft
+{ "
+ba 600,750,250 3 0174 bar
+| "
+rC 600,622,108 2 0175 braceright
+} "
+a~ 600,606 2 0176 tilde
+~ "
+bq 600,100,134 0 0200 quotesinglbase
+Fo 600,446 0 0201 guillemotleft
+char171 "
+Fc 600,446 0 0202 guillemotright
+char187 "
+bu 600,383 0 0203 bullet
+Fn 600,622,143 2 0204 florin
+f/ 600,665,57 2 0205 fraction
+%0 600,622,15 2 0206 perthousand
+dg 600,580,78 2 0207 dagger
+dd 600,580,78 2 0210 daggerdbl
+en 600,285 0 0211 endash
+em 600,285 0 0212 emdash
+fi 600,629 2 0214 fi
+fl 600,629 2 0215 fl
+.i 600,426 0 0220 dotlessi
+ga 600,672 2 0222 grave
+a" 600,672 2 0223 hungarumlaut
+a. 600,580 2 0224 dotaccent
+ab 600,609 2 0225 breve
+ah 600,669 2 0226 caron
+ao 600,627 2 0227 ring
+ho 600,0,151 0 0230 ogonek
+lq 600,562 2 0231 quotedblleft
+rq 600,562 2 0232 quotedblright
+oe 600,441,15 0 0233 oe
+/l 600,629 2 0234 lslash
+Bq 600,100,134 0 0235 quotedblbase
+OE 600,562 2 0236 OE
+/L 600,562 2 0237 Lslash
+r! 600,430,157 1 0241 exclamdown
+char161 "
+ct 600,614,49 2 0242 cent
+char162 "
+Po 600,611,21 2 0243 sterling
+char163 "
+Cs 600,506 0 0244 currency
+char164 "
+Ye 600,562 2 0245 yen
+char165 "
+bb 600,675,175 3 0246 brokenbar
+char166 "
+sc 600,580,78 2 0247 section
+char167 "
+ad 600,595 2 0250 dieresis
+char168 "
+co 600,580,18 2 0251 copyright
+char169 "
+Of 600,580 2 0252 ordfeminine
+char170 "
+fo 600,446 0 0253 guilsinglleft
+no 600,369 0 0254 logicalnot
+char172 "
+\- 600,283 0 0255 minus
+rg 600,580,18 2 0256 registered
+char174 "
+a- 600,565 2 0257 macron
+char175 "
+de 600,622 2 0260 degree
+char176 "
+char177 600,558 0 0261 plusminus
+S2 600,622 2 0262 twosuperior
+char178 "
+S3 600,622 2 0263 threesuperior
+char179 "
+aa 600,672 2 0264 acute
+char180 "
+char181 600,426,157 1 0265 mu
+ps 600,562,78 2 0266 paragraph
+char182 "
+char183 600,327 0 0267 periodcentered
+ac 600,10,151 0 0270 cedilla
+char184 "
+S1 600,622 2 0271 onesuperior
+char185 "
+Om 600,580 2 0272 ordmasculine
+char186 "
+fc 600,446 0 0273 guilsinglright
+14 600,665,57 2 0274 onequarter
+char188 "
+12 600,665,57 2 0275 onehalf
+char189 "
+34 600,666,56 2 0276 threequarters
+char190 "
+r? 600,430,157 1 0277 questiondown
+char191 "
+`A 600,793 2 0300 Agrave
+char192 "
+'A 600,793 2 0301 Aacute
+char193 "
+^A 600,775 2 0302 Acircumflex
+char194 "
+~A 600,732 2 0303 Atilde
+char195 "
+:A 600,731 2 0304 Adieresis
+char196 "
+oA 600,753 2 0305 Aring
+char197 "
+AE 600,562 2 0306 AE
+char198 "
+,C 600,580,151 2 0307 Ccedilla
+char199 "
+`E 600,793 2 0310 Egrave
+char200 "
+'E 600,793 2 0311 Eacute
+char201 "
+^E 600,775 2 0312 Ecircumflex
+char202 "
+:E 600,731 2 0313 Edieresis
+char203 "
+`I 600,793 2 0314 Igrave
+char204 "
+'I 600,793 2 0315 Iacute
+char205 "
+^I 600,775 2 0316 Icircumflex
+char206 "
+:I 600,731 2 0317 Idieresis
+char207 "
+-D 600,562 2 0320 Eth
+char208 "
+~N 600,732,13 2 0321 Ntilde
+char209 "
+`O 600,793,18 2 0322 Ograve
+char210 "
+'O 600,793,18 2 0323 Oacute
+char211 "
+^O 600,775,18 2 0324 Ocircumflex
+char212 "
+~O 600,732,18 2 0325 Otilde
+char213 "
+:O 600,731,18 2 0326 Odieresis
+char214 "
+char215 600,470 0 0327 multiply
+/O 600,629,80 2 0330 Oslash
+char216 "
+`U 600,793,18 2 0331 Ugrave
+char217 "
+'U 600,793,18 2 0332 Uacute
+char218 "
+^U 600,775,18 2 0333 Ucircumflex
+char219 "
+:U 600,731,18 2 0334 Udieresis
+char220 "
+'Y 600,793 2 0335 Yacute
+char221 "
+TP 600,562 2 0336 Thorn
+char222 "
+ss 600,629,15 2 0337 germandbls
+char223 "
+`a 600,672,15 2 0340 agrave
+char224 "
+'a 600,672,15 2 0341 aacute
+char225 "
+^a 600,654,15 2 0342 acircumflex
+char226 "
+~a 600,606,15 2 0343 atilde
+char227 "
+:a 600,595,15 2 0344 adieresis
+char228 "
+oa 600,627,15 2 0345 aring
+char229 "
+ae 600,441,15 0 0346 ae
+char230 "
+,c 600,441,151 0 0347 ccedilla
+char231 "
+`e 600,672,15 2 0350 egrave
+char232 "
+'e 600,672,15 2 0351 eacute
+char233 "
+^e 600,654,15 2 0352 ecircumflex
+char234 "
+:e 600,595,15 2 0353 edieresis
+char235 "
+`i 600,672 2 0354 igrave
+char236 "
+'i 600,672 2 0355 iacute
+char237 "
+^i 600,654 2 0356 icircumflex
+char238 "
+:i 600,595 2 0357 idieresis
+char239 "
+Sd 600,629,15 2 0360 eth
+char240 "
+~n 600,606 2 0361 ntilde
+char241 "
+`o 600,672,15 2 0362 ograve
+char242 "
+'o 600,672,15 2 0363 oacute
+char243 "
+^o 600,654,15 2 0364 ocircumflex
+char244 "
+~o 600,606,15 2 0365 otilde
+char245 "
+:o 600,595,15 2 0366 odieresis
+char246 "
+char247 600,467 0 0367 divide
+/o 600,506,80 0 0370 oslash
+char248 "
+`u 600,672,15 2 0371 ugrave
+char249 "
+'u 600,672,15 2 0372 uacute
+char250 "
+^u 600,654,15 2 0373 ucircumflex
+char251 "
+:u 600,595,15 2 0374 udieresis
+char252 "
+'y 600,672,157 3 0375 yacute
+char253 "
+Tp 600,629,157 3 0376 thorn
+char254 "
+:y 600,595,157 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/DESC b/gnu/usr.bin/groff/devices/devps/DESC
new file mode 100644
index 000000000000..1aba05961ec2
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/DESC
@@ -0,0 +1,14 @@
+res 72000
+hor 1
+vert 1
+sizescale 1000
+unitwidth 1000
+sizes 1000-10000000 0
+styles R I B BI
+family T
+fonts 9 0 0 0 0 0 SS S ZD ZDR
+tcommand
+postpro grops
+broken 0
+paperlength 792000
+print lpr
diff --git a/gnu/usr.bin/groff/devices/devps/DESC-A4 b/gnu/usr.bin/groff/devices/devps/DESC-A4
new file mode 100644
index 000000000000..9e842c94deae
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/DESC-A4
@@ -0,0 +1,14 @@
+res 72000
+hor 1
+vert 1
+sizescale 1000
+unitwidth 1000
+sizes 1000-10000000 0
+styles R I B BI
+family T
+fonts 9 0 0 0 0 0 SS S ZD ZDR
+tcommand
+postpro grops
+broken 0
+paperlength 841890
+print lpr
diff --git a/gnu/usr.bin/groff/devices/devps/DESC-letter b/gnu/usr.bin/groff/devices/devps/DESC-letter
new file mode 100644
index 000000000000..1aba05961ec2
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/DESC-letter
@@ -0,0 +1,14 @@
+res 72000
+hor 1
+vert 1
+sizescale 1000
+unitwidth 1000
+sizes 1000-10000000 0
+styles R I B BI
+family T
+fonts 9 0 0 0 0 0 SS S ZD ZDR
+tcommand
+postpro grops
+broken 0
+paperlength 792000
+print lpr
diff --git a/gnu/usr.bin/groff/devices/devps/HB b/gnu/usr.bin/groff/devices/devps/HB
new file mode 100644
index 000000000000..8c2ed083a390
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HB
@@ -0,0 +1,546 @@
+name HB
+internalname Helvetica-Bold
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -30
+A w -30
+A v -40
+A u -30
+A Y -110
+A W -60
+A V -80
+A U -50
+A T -90
+A Q -40
+A O -40
+A G -50
+A C -40
+B U -10
+B A -30
+D . -30
+D , -30
+D Y -70
+D W -40
+D V -40
+D A -40
+F . -100
+F , -100
+F a -20
+F A -80
+J u -20
+J . -20
+J , -20
+J A -20
+K y -40
+K u -30
+K o -35
+K e -15
+K O -30
+L y -30
+L ' -140
+L rq -140
+L Y -120
+L W -80
+L V -110
+L T -90
+O . -40
+O , -40
+O Y -70
+O X -50
+O W -50
+O V -50
+O T -40
+O A -50
+P . -120
+P o -40
+P e -30
+P , -120
+P a -30
+P A -100
+Q . 20
+Q , 20
+Q U -10
+R Y -50
+R W -40
+R V -50
+R U -20
+R T -20
+R O -20
+T y -60
+T w -60
+T u -90
+T ; -40
+T r -80
+T . -80
+T o -80
+T - -120
+T hy -120
+T char173 -120
+T e -60
+T , -80
+T : -40
+T a -80
+T O -40
+T A -90
+U . -30
+U , -30
+U A -50
+V u -60
+V ; -40
+V . -120
+V o -90
+V - -80
+V hy -80
+V char173 -80
+V e -50
+V , -120
+V : -40
+V a -60
+V O -50
+V G -50
+V A -80
+W y -20
+W u -45
+W ; -10
+W . -80
+W o -60
+W - -40
+W hy -40
+W char173 -40
+W e -35
+W , -80
+W : -10
+W a -40
+W O -20
+W A -60
+Y u -100
+Y ; -50
+Y . -100
+Y o -100
+Y e -80
+Y , -100
+Y : -50
+Y a -90
+Y O -70
+Y A -110
+a y -20
+a w -15
+a v -15
+a g -10
+b y -20
+b v -20
+b u -20
+b l -10
+c y -10
+c l -20
+c k -20
+c h -10
+, ' -120
+, rq -120
+d y -15
+d w -15
+d v -15
+d d -10
+e y -15
+e x -15
+e w -15
+e v -15
+e . 20
+e , 10
+f ' 30
+f rq 30
+f . -10
+f o -20
+f e -10
+f , -10
+g g -10
+g e 10
+h y -20
+k o -15
+l y -15
+l w -15
+m y -30
+m u -20
+n y -20
+n v -40
+n u -10
+o y -20
+o x -30
+o w -15
+o v -20
+p y -15
+. ' -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+' s -60
+' r -40
+' ' -46
+' l -20
+' d -80
+r y 10
+r v 10
+r t 20
+r s -15
+r q -20
+r . -60
+r o -20
+r - -20
+r hy -20
+r char173 -20
+r g -15
+r d -20
+r , -60
+r c -20
+s w -15
+v . -80
+v o -30
+v , -80
+v a -20
+w . -40
+w o -20
+w , -40
+x e -10
+y . -80
+y o -25
+y e -10
+y , -80
+y a -30
+z e 10
+charset
+ha 584,698 2 0000 asciicircum
+ti 584,343 0 0001 asciitilde
+vS 667,936,19 2 0002 Scaron
+vZ 611,936 2 0003 Zcaron
+vs 556,750,14 2 0004 scaron
+vz 500,750 2 0005 zcaron
+:Y 667,915 2 0006 Ydieresis
+tm 1000,718 2 0007 trademark
+aq 238,718 2 0010 quotesingle
+space 278 0 0040
+! 333,718 2 0041 exclam
+" 474,718 2 0042 quotedbl
+# 556,698 2 0043 numbersign
+sh "
+$ 556,775,115 2 0044 dollar
+Do "
+% 889,710,19 2 0045 percent
+& 722,718,19 2 0046 ampersand
+' 278,718 2 0047 quoteright
+( 333,734,208 3 0050 parenleft
+) 333,734,208 3 0051 parenright
+* 389,718 2 0052 asterisk
++ 584,506 0 0053 plus
+, 278,146,168 0 0054 comma
+- 333,345 0 0055 hyphen
+hy "
+char173 "
+. 278,146 0 0056 period
+/ 278,737,19 2 0057 slash
+sl "
+0 556,710,19 2 0060 zero
+1 556,710 2 0061 one
+2 556,710 2 0062 two
+3 556,710,19 2 0063 three
+4 556,710 2 0064 four
+5 556,698,19 2 0065 five
+6 556,710,19 2 0066 six
+7 556,698 2 0067 seven
+8 556,710,19 2 0070 eight
+9 556,710,19 2 0071 nine
+: 333,512 0 0072 colon
+; 333,512,168 0 0073 semicolon
+< 584,514,8 0 0074 less
+= 584,419 0 0075 equal
+> 584,514,8 0 0076 greater
+? 611,727 2 0077 question
+@ 975,737,19 2 0100 at
+at "
+A 722,718 2 0101 A
+B 722,718 2 0102 B
+C 722,737,19 2 0103 C
+D 722,718 2 0104 D
+E 667,718 2 0105 E
+F 611,718 2 0106 F
+G 778,737,19 2 0107 G
+H 722,718 2 0110 H
+I 278,718 2 0111 I
+J 556,718,18 2 0112 J
+K 722,718 2 0113 K
+L 611,718 2 0114 L
+M 833,718 2 0115 M
+N 722,718 2 0116 N
+O 778,737,19 2 0117 O
+P 667,718 2 0120 P
+Q 778,737,52 2 0121 Q
+R 722,718 2 0122 R
+S 667,737,19 2 0123 S
+T 611,718 2 0124 T
+U 722,718,19 2 0125 U
+V 667,718 2 0126 V
+W 944,718 2 0127 W
+X 667,718 2 0130 X
+Y 667,718 2 0131 Y
+Z 611,718 2 0132 Z
+[ 333,722,196 2 0133 bracketleft
+lB "
+\ 278,737,19 2 0134 backslash
+rs "
+] 333,722,196 2 0135 bracketright
+rB "
+a^ 333,750 2 0136 circumflex
+^ "
+_ 556,0,125 0 0137 underscore
+` 278,727 2 0140 quoteleft
+oq "
+a 556,546,14 0 0141 a
+b 611,718,14 2 0142 b
+c 556,546,14 0 0143 c
+d 611,718,14 2 0144 d
+e 556,546,14 0 0145 e
+f 333,727 2 0146 f
+g 611,546,217 1 0147 g
+h 611,718 2 0150 h
+i 278,725 2 0151 i
+j 278,725,214 3 0152 j
+k 556,718 2 0153 k
+l 278,718 2 0154 l
+m 889,546 0 0155 m
+n 611,546 0 0156 n
+o 611,546,14 0 0157 o
+p 611,546,207 1 0160 p
+q 611,546,207 1 0161 q
+r 389,546 0 0162 r
+s 556,546,14 0 0163 s
+t 333,676,6 2 0164 t
+u 611,532,14 0 0165 u
+v 556,532 0 0166 v
+w 778,532 0 0167 w
+x 556,532 0 0170 x
+y 556,532,214 1 0171 y
+z 500,532 0 0172 z
+lC 389,722,196 2 0173 braceleft
+{ "
+ba 280,737,19 2 0174 bar
+| "
+rC 389,722,196 2 0175 braceright
+} "
+a~ 333,737 2 0176 tilde
+~ "
+bq 278,127,146 0 0200 quotesinglbase
+Fo 556,484 0 0201 guillemotleft
+char171 "
+Fc 556,484 0 0202 guillemotright
+char187 "
+bu 350,524 0 0203 bullet
+Fn 556,737,210 3 0204 florin
+f/ 167,710,19 2 0205 fraction
+%0 1000,710,19 2 0206 perthousand
+dg 556,718,171 2 0207 dagger
+dd 556,718,171 2 0210 daggerdbl
+en 556,333 0 0211 endash
+em 1000,333 0 0212 emdash
+fi 611,727 2 0214 fi
+fl 611,727 2 0215 fl
+.i 278,532 0 0220 dotlessi
+ga 333,750 2 0222 grave
+a" 333,750 2 0223 hungarumlaut
+a. 333,729 2 0224 dotaccent
+ab 333,750 2 0225 breve
+ah 333,750 2 0226 caron
+ao 333,776 2 0227 ring
+ho 333,0,228 1 0230 ogonek
+lq 500,727 2 0231 quotedblleft
+rq 500,718 2 0232 quotedblright
+oe 944,546,14 0 0233 oe
+/l 278,718 2 0234 lslash
+Bq 500,127,146 0 0235 quotedblbase
+OE 1000,737,19 2 0236 OE
+/L 611,718 2 0237 Lslash
+r! 333,532,186 0 0241 exclamdown
+char161 "
+ct 556,628,118 0 0242 cent
+char162 "
+Po 556,718,16 2 0243 sterling
+char163 "
+Cs 556,636 0 0244 currency
+char164 "
+Ye 556,698 2 0245 yen
+char165 "
+bb 280,737,19 2 0246 brokenbar
+char166 "
+sc 556,727,184 2 0247 section
+char167 "
+ad 333,729 2 0250 dieresis
+char168 "
+co 737,737,19 2 0251 copyright
+char169 "
+Of 370,737 2 0252 ordfeminine
+char170 "
+fo 333,484 0 0253 guilsinglleft
+no 584,419 0 0254 logicalnot
+char172 "
+\- 584,309 0 0255 minus
+rg 737,737,19 2 0256 registered
+char174 "
+a- 333,678 2 0257 macron
+char175 "
+de 400,712 2 0260 degree
+char176 "
+char177 584,506 0 0261 plusminus
+S2 333,710 2 0262 twosuperior
+char178 "
+S3 333,710 2 0263 threesuperior
+char179 "
+aa 333,750 2 0264 acute
+char180 "
+char181 611,532,207 1 0265 mu
+ps 556,700,191 2 0266 paragraph
+char182 "
+char183 278,334 0 0267 periodcentered
+ac 333,0,228 1 0270 cedilla
+char184 "
+S1 333,710 2 0271 onesuperior
+char185 "
+Om 365,737 2 0272 ordmasculine
+char186 "
+fc 333,484 0 0273 guilsinglright
+14 834,710,19 2 0274 onequarter
+char188 "
+12 834,710,19 2 0275 onehalf
+char189 "
+34 834,710,19 2 0276 threequarters
+char190 "
+r? 611,532,195 0 0277 questiondown
+char191 "
+`A 722,936 2 0300 Agrave
+char192 "
+'A 722,936 2 0301 Aacute
+char193 "
+^A 722,936 2 0302 Acircumflex
+char194 "
+~A 722,923 2 0303 Atilde
+char195 "
+:A 722,915 2 0304 Adieresis
+char196 "
+oA 722,962 2 0305 Aring
+char197 "
+AE 1000,718 2 0306 AE
+char198 "
+,C 722,737,228 3 0307 Ccedilla
+char199 "
+`E 667,936 2 0310 Egrave
+char200 "
+'E 667,936 2 0311 Eacute
+char201 "
+^E 667,936 2 0312 Ecircumflex
+char202 "
+:E 667,915 2 0313 Edieresis
+char203 "
+`I 278,936 2 0314 Igrave
+char204 "
+'I 278,936 2 0315 Iacute
+char205 "
+^I 278,936 2 0316 Icircumflex
+char206 "
+:I 278,915 2 0317 Idieresis
+char207 "
+-D 722,718 2 0320 Eth
+char208 "
+~N 722,923 2 0321 Ntilde
+char209 "
+`O 778,936,19 2 0322 Ograve
+char210 "
+'O 778,936,19 2 0323 Oacute
+char211 "
+^O 778,936,19 2 0324 Ocircumflex
+char212 "
+~O 778,923,19 2 0325 Otilde
+char213 "
+:O 778,915,19 2 0326 Odieresis
+char214 "
+char215 584,505 0 0327 multiply
+/O 778,745,27 2 0330 Oslash
+char216 "
+`U 722,936,19 2 0331 Ugrave
+char217 "
+'U 722,936,19 2 0332 Uacute
+char218 "
+^U 722,936,19 2 0333 Ucircumflex
+char219 "
+:U 722,915,19 2 0334 Udieresis
+char220 "
+'Y 667,936 2 0335 Yacute
+char221 "
+TP 667,718 2 0336 Thorn
+char222 "
+ss 611,731,14 2 0337 germandbls
+char223 "
+`a 556,750,14 2 0340 agrave
+char224 "
+'a 556,750,14 2 0341 aacute
+char225 "
+^a 556,750,14 2 0342 acircumflex
+char226 "
+~a 556,737,14 2 0343 atilde
+char227 "
+:a 556,729,14 2 0344 adieresis
+char228 "
+oa 556,776,14 2 0345 aring
+char229 "
+ae 889,546,14 0 0346 ae
+char230 "
+,c 556,546,228 1 0347 ccedilla
+char231 "
+`e 556,750,14 2 0350 egrave
+char232 "
+'e 556,750,14 2 0351 eacute
+char233 "
+^e 556,750,14 2 0352 ecircumflex
+char234 "
+:e 556,729,14 2 0353 edieresis
+char235 "
+`i 278,750 2 0354 igrave
+char236 "
+'i 278,750 2 0355 iacute
+char237 "
+^i 278,750 2 0356 icircumflex
+char238 "
+:i 278,729 2 0357 idieresis
+char239 "
+Sd 611,737,14 2 0360 eth
+char240 "
+~n 611,737 2 0361 ntilde
+char241 "
+`o 611,750,14 2 0362 ograve
+char242 "
+'o 611,750,14 2 0363 oacute
+char243 "
+^o 611,750,14 2 0364 ocircumflex
+char244 "
+~o 611,737,14 2 0365 otilde
+char245 "
+:o 611,729,14 2 0366 odieresis
+char246 "
+char247 584,548,42 0 0367 divide
+/o 611,560,29 0 0370 oslash
+char248 "
+`u 611,750,14 2 0371 ugrave
+char249 "
+'u 611,750,14 2 0372 uacute
+char250 "
+^u 611,750,14 2 0373 ucircumflex
+char251 "
+:u 611,729,14 2 0374 udieresis
+char252 "
+'y 556,750,214 3 0375 yacute
+char253 "
+Tp 611,718,208 3 0376 thorn
+char254 "
+:y 556,729,214 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/HBI b/gnu/usr.bin/groff/devices/devps/HBI
new file mode 100644
index 000000000000..595e58f90f32
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HBI
@@ -0,0 +1,547 @@
+name HBI
+internalname Helvetica-BoldOblique
+slant 12
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -30
+A w -30
+A v -40
+A u -30
+A Y -110
+A W -60
+A V -80
+A U -50
+A T -90
+A Q -40
+A O -40
+A G -50
+A C -40
+B U -10
+B A -30
+D . -30
+D , -30
+D Y -70
+D W -40
+D V -40
+D A -40
+F . -100
+F , -100
+F a -20
+F A -80
+J u -20
+J . -20
+J , -20
+J A -20
+K y -40
+K u -30
+K o -35
+K e -15
+K O -30
+L y -30
+L ' -140
+L rq -140
+L Y -120
+L W -80
+L V -110
+L T -90
+O . -40
+O , -40
+O Y -70
+O X -50
+O W -50
+O V -50
+O T -40
+O A -50
+P . -120
+P o -40
+P e -30
+P , -120
+P a -30
+P A -100
+Q . 20
+Q , 20
+Q U -10
+R Y -50
+R W -40
+R V -50
+R U -20
+R T -20
+R O -20
+T y -60
+T w -60
+T u -90
+T ; -40
+T r -80
+T . -80
+T o -80
+T - -120
+T hy -120
+T char173 -120
+T e -60
+T , -80
+T : -40
+T a -80
+T O -40
+T A -90
+U . -30
+U , -30
+U A -50
+V u -60
+V ; -40
+V . -120
+V o -90
+V - -80
+V hy -80
+V char173 -80
+V e -50
+V , -120
+V : -40
+V a -60
+V O -50
+V G -50
+V A -80
+W y -20
+W u -45
+W ; -10
+W . -80
+W o -60
+W - -40
+W hy -40
+W char173 -40
+W e -35
+W , -80
+W : -10
+W a -40
+W O -20
+W A -60
+Y u -100
+Y ; -50
+Y . -100
+Y o -100
+Y e -80
+Y , -100
+Y : -50
+Y a -90
+Y O -70
+Y A -110
+a y -20
+a w -15
+a v -15
+a g -10
+b y -20
+b v -20
+b u -20
+b l -10
+c y -10
+c l -20
+c k -20
+c h -10
+, ' -120
+, rq -120
+d y -15
+d w -15
+d v -15
+d d -10
+e y -15
+e x -15
+e w -15
+e v -15
+e . 20
+e , 10
+f ' 30
+f rq 30
+f . -10
+f o -20
+f e -10
+f , -10
+g g -10
+g e 10
+h y -20
+k o -15
+l y -15
+l w -15
+m y -30
+m u -20
+n y -20
+n v -40
+n u -10
+o y -20
+o x -30
+o w -15
+o v -20
+p y -15
+. ' -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+' s -60
+' r -40
+' ' -46
+' l -20
+' d -80
+r y 10
+r v 10
+r t 20
+r s -15
+r q -20
+r . -60
+r o -20
+r - -20
+r hy -20
+r char173 -20
+r g -15
+r d -20
+r , -60
+r c -20
+s w -15
+v . -80
+v o -30
+v , -80
+v a -20
+w . -40
+w o -20
+w , -40
+x e -10
+y . -80
+y o -25
+y e -10
+y , -80
+y a -30
+z e 10
+charset
+ha 584,698,0,57,-81,57 2 0000 asciicircum
+ti 584,343,0,43,-65,43 0 0001 asciitilde
+vS 667,936,19,101,-31,90 2 0002 Scaron
+vZ 611,936,0,176,25,90 2 0003 Zcaron
+vs 556,750,14,108,-13,90 2 0004 scaron
+vz 500,750,0,136,30,90 2 0005 zcaron
+:Y 667,915,0,189,-118,90 2 0006 Ydieresis
+tm 1000,718,0,159,-129,90 2 0007 trademark
+aq 238,718,0,133,-115,90 2 0010 quotesingle
+space 278 0 0040
+! 333,718,0,114,-44,90 2 0041 exclam
+" 474,718,0,105,-143,90 2 0042 quotedbl
+# 556,698,0,138,-10,90 2 0043 numbersign
+sh "
+$ 556,775,115,116,-17,90 2 0044 dollar
+Do "
+% 889,710,19,62,-86,62 2 0045 percent
+& 722,718,19,60,-39,60 2 0046 ampersand
+' 278,718,0,134,-117,90 2 0047 quoteright
+( 333,734,208,187,-26,90 3 0050 parenleft
+) 333,734,208,86,75,86 3 0051 parenright
+* 389,718,0,142,-96,90 2 0052 asterisk
++ 584,506,0,76,-32,76 0 0053 plus
+, 278,146,168,17,22,17 0 0054 comma
+- 333,345,0,96,-23,90 0 0055 hyphen
+hy "
+char173 "
+. 278,146,0,17,-14,17 0 0056 period
+/ 278,737,19,240,87,90 2 0057 slash
+sl "
+0 556,710,19,111,-36,90 2 0060 zero
+1 556,710,0,23,-123,23 2 0061 one
+2 556,710,0,113,24,90 2 0062 two
+3 556,710,19,102,-15,90 2 0063 three
+4 556,710,0,92,-10,90 2 0064 four
+5 556,698,19,130,-14,90 2 0065 five
+6 556,710,19,113,-35,90 2 0066 six
+7 556,698,0,170,-75,90 2 0067 seven
+8 556,710,19,110,-19,90 2 0070 eight
+9 556,710,19,109,-28,90 2 0071 nine
+: 333,512,0,68,-42,68 0 0072 colon
+; 333,512,168,68,-6,68 0 0073 semicolon
+< 584,514,8,121,-32,90 0 0074 less
+= 584,419,0,99,-8,90 0 0075 equal
+> 584,514,8,75,14,75 0 0076 greater
+? 611,727,0,110,-115,90 2 0077 question
+@ 975,737,19,29,-136,29 2 0100 at
+at "
+A 722,718,0,30,30,30 2 0101 A
+B 722,718,0,92,-26,90 2 0102 B
+C 722,737,19,117,-57,90 2 0103 C
+D 722,718,0,105,-26,90 2 0104 D
+E 667,718,0,140,-26,90 2 0105 E
+F 611,718,0,179,-26,90 2 0106 F
+G 778,737,19,89,-58,89 2 0107 G
+H 722,718,0,132,-21,90 2 0110 H
+I 278,718,0,139,-14,90 2 0111 I
+J 556,718,18,131,-10,90 2 0112 J
+K 722,718,0,186,-37,90 2 0113 K
+L 611,718,0,50,-26,50 2 0114 L
+M 833,718,0,135,-19,90 2 0115 M
+N 722,718,0,135,-19,90 2 0116 N
+O 778,737,19,95,-57,90 2 0117 O
+P 667,718,0,121,-26,90 2 0120 P
+Q 778,737,52,95,-57,90 2 0121 Q
+R 722,718,0,106,-26,90 2 0122 R
+S 667,737,19,101,-31,90 2 0123 S
+T 611,718,0,190,-90,90 2 0124 T
+U 722,718,19,132,-66,90 2 0125 U
+V 667,718,0,184,-122,90 2 0126 V
+W 944,718,0,188,-119,90 2 0127 W
+X 667,718,0,174,36,90 2 0130 X
+Y 667,718,0,189,-118,90 2 0131 Y
+Z 611,718,0,176,25,90 2 0132 Z
+[ 333,722,196,179,29,90 2 0133 bracketleft
+lB "
+\ 278,737,19,79,-74,79 2 0134 backslash
+rs "
+] 333,722,196,140,68,90 2 0135 bracketright
+rB "
+a^ 333,750,0,188,-68,90 2 0136 circumflex
+^ "
+_ 556,0,125,34,77,34 0 0137 underscore
+` 278,727,0,133,-115,90 2 0140 quoteleft
+oq "
+a 556,546,14,77,-5,77 0 0141 a
+b 611,718,14,84,-11,84 2 0142 b
+c 556,546,14,93,-29,90 0 0143 c
+d 611,718,14,143,-32,90 2 0144 d
+e 556,546,14,87,-20,87 0 0145 e
+f 333,727,0,186,-37,90 2 0146 f
+g 611,546,217,105,12,90 1 0147 g
+h 611,718,0,68,-15,68 2 0150 h
+i 278,725,0,135,-19,90 2 0151 i
+j 278,725,214,135,92,90 3 0152 j
+k 556,718,0,164,-19,90 2 0153 k
+l 278,718,0,134,-19,90 2 0154 l
+m 889,546,0,70,-14,70 0 0155 m
+n 611,546,0,68,-15,68 0 0156 n
+o 611,546,14,82,-32,82 0 0157 o
+p 611,546,207,84,32,84 1 0160 p
+q 611,546,207,104,-30,90 1 0161 q
+r 389,546,0,150,-14,90 0 0162 r
+s 556,546,14,78,-13,78 0 0163 s
+t 333,676,6,139,-50,90 2 0164 t
+u 611,532,14,97,-48,90 0 0165 u
+v 556,532,0,150,-76,90 0 0166 v
+w 778,532,0,154,-73,90 0 0167 w
+x 556,532,0,142,35,90 0 0170 x
+y 556,532,214,146,8,90 1 0171 y
+z 500,532,0,133,30,90 0 0172 z
+lC 389,722,196,179,-44,90 2 0173 braceleft
+{ "
+ba 280,737,19,123,-30,90 2 0174 bar
+| "
+rC 389,722,196,68,68,68 2 0175 braceright
+} "
+a~ 333,737,0,224,-63,90 2 0176 tilde
+~ "
+bq 278,127,146,8,9,8 0 0200 quotesinglbase
+Fo 556,484,0,65,-85,65 0 0201 guillemotleft
+char171 "
+Fc 556,484,0,34,-54,34 0 0202 guillemotright
+char187 "
+bu 350,524,0,120,-33,90 0 0203 bullet
+Fn 556,737,210,163,100,90 3 0204 florin
+f/ 167,710,19,370,224,90 2 0205 fraction
+%0 1000,710,19,88,-26,88 2 0206 perthousand
+dg 556,718,171,120,-68,90 2 0207 dagger
+dd 556,718,171,122,4,90 2 0210 daggerdbl
+en 556,333,0,121,2,90 0 0211 endash
+em 1000,333,0,121,2,90 0 0212 emdash
+fi 611,727,0,135,-37,90 2 0214 fi
+fl 611,727,0,134,-37,90 2 0215 fl
+.i 278,532,0,94,-19,90 0 0220 dotlessi
+ga 333,750,0,70,-86,70 2 0222 grave
+a" 333,750,0,362,-87,90 2 0223 hungarumlaut
+a. 333,729,0,102,-185,90 2 0224 dotaccent
+ab 333,750,0,211,-106,90 2 0225 breve
+ah 333,750,0,219,-99,90 2 0226 caron
+ao 333,776,0,137,-150,90 2 0227 ring
+ho 333,0,228,0,9 1 0230 ogonek
+lq 500,727,0,138,-110,90 2 0231 quotedblleft
+rq 500,718,0,139,-112,90 2 0232 quotedblright
+oe 944,546,14,83,-32,83 0 0233 oe
+/l 278,718,0,179,10,90 2 0234 lslash
+Bq 500,127,146,13,14,13 0 0235 quotedblbase
+OE 1000,737,19,164,-49,90 2 0236 OE
+/L 611,718,0,50,16,50 2 0237 Lslash
+r! 333,532,186,70,0,70 0 0241 exclamdown
+char161 "
+ct 556,628,118,93,-29,90 0 0242 cent
+char162 "
+Po 556,718,16,129,0,90 2 0243 sterling
+char163 "
+Cs 556,636,0,174,23,90 0 0244 currency
+char164 "
+Ye 556,698,0,207,-10,90 2 0245 yen
+char165 "
+bb 280,737,19,123,-30,90 2 0246 brokenbar
+char166 "
+sc 556,727,184,92,-11,90 2 0247 section
+char167 "
+ad 333,729,0,199,-87,90 2 0250 dieresis
+char168 "
+co 737,737,19,148,-6,90 2 0251 copyright
+char169 "
+Of 370,737,0,145,-42,90 2 0252 ordfeminine
+char170 "
+fo 333,484,0,70,-80,70 0 0253 guilsinglleft
+no 584,419,0,99,-55,90 0 0254 logicalnot
+char172 "
+\- 584,309,0,76,-32,76 0 0255 minus
+rg 737,737,19,147,-5,90 2 0256 registered
+char174 "
+a- 333,678,0,200,-72,90 2 0257 macron
+char175 "
+de 400,712,0,117,-125,90 2 0260 degree
+char176 "
+char177 584,506,0,91,10,90 0 0261 plusminus
+S2 333,710,0,166,-19,90 2 0262 twosuperior
+char178 "
+S3 333,710,0,158,-41,90 2 0263 threesuperior
+char179 "
+aa 333,750,0,232,-186,90 2 0264 acute
+char180 "
+char181 611,532,207,97,28,90 1 0265 mu
+ps 556,700,191,182,-48,90 2 0266 paragraph
+char182 "
+char183 278,334,0,48,-60,48 0 0267 periodcentered
+ac 333,0,228,0,87 1 0270 cedilla
+char184 "
+S1 333,710,0,105,-98,90 2 0271 onesuperior
+char185 "
+Om 365,737,0,170,-42,90 2 0272 ordmasculine
+char186 "
+fc 333,484,0,39,-49,39 0 0273 guilsinglright
+14 834,710,19,22,-82,22 2 0274 onequarter
+char188 "
+12 834,710,19,74,-82,74 2 0275 onehalf
+char189 "
+34 834,710,19,55,-49,55 2 0276 threequarters
+char190 "
+r? 611,532,195,0,-3 0 0277 questiondown
+char191 "
+`A 722,936,0,30,30,30 2 0300 Agrave
+char192 "
+'A 722,936,0,78,30,78 2 0301 Aacute
+char193 "
+^A 722,936,0,34,30,34 2 0302 Acircumflex
+char194 "
+~A 722,923,0,69,30,69 2 0303 Atilde
+char195 "
+:A 722,915,0,44,30,44 2 0304 Adieresis
+char196 "
+oA 722,962,0,30,30,30 2 0305 Aring
+char197 "
+AE 1000,718,0,150,45,90 2 0306 AE
+char198 "
+,C 722,737,228,117,-57,90 3 0307 Ccedilla
+char199 "
+`E 667,936,0,140,-26,90 2 0310 Egrave
+char200 "
+'E 667,936,0,140,-26,90 2 0311 Eacute
+char201 "
+^E 667,936,0,140,-26,90 2 0312 Ecircumflex
+char202 "
+:E 667,915,0,140,-26,90 2 0313 Edieresis
+char203 "
+`I 278,936,0,139,-14,90 2 0314 Igrave
+char204 "
+'I 278,936,0,300,-14,90 2 0315 Iacute
+char205 "
+^I 278,936,0,256,-14,90 2 0316 Icircumflex
+char206 "
+:I 278,915,0,266,-14,90 2 0317 Idieresis
+char207 "
+-D 722,718,0,105,-12,90 2 0320 Eth
+char208 "
+~N 722,923,0,135,-19,90 2 0321 Ntilde
+char209 "
+`O 778,936,19,95,-57,90 2 0322 Ograve
+char210 "
+'O 778,936,19,95,-57,90 2 0323 Oacute
+char211 "
+^O 778,936,19,95,-57,90 2 0324 Ocircumflex
+char212 "
+~O 778,923,19,95,-57,90 2 0325 Otilde
+char213 "
+:O 778,915,19,95,-57,90 2 0326 Odieresis
+char214 "
+char215 584,505,0,101,-7,90 0 0327 multiply
+/O 778,745,27,166,15,90 2 0330 Oslash
+char216 "
+`U 722,936,19,132,-66,90 2 0331 Ugrave
+char217 "
+'U 722,936,19,132,-66,90 2 0332 Uacute
+char218 "
+^U 722,936,19,132,-66,90 2 0333 Ucircumflex
+char219 "
+:U 722,915,19,132,-66,90 2 0334 Udieresis
+char220 "
+'Y 667,936,0,189,-118,90 2 0335 Yacute
+char221 "
+TP 667,718,0,99,-26,90 2 0336 Thorn
+char222 "
+ss 611,731,14,96,-19,90 2 0337 germandbls
+char223 "
+`a 556,750,14,77,-5,77 2 0340 agrave
+char224 "
+'a 556,750,14,121,-5,90 2 0341 aacute
+char225 "
+^a 556,750,14,77,-5,77 2 0342 acircumflex
+char226 "
+~a 556,737,14,113,-5,90 2 0343 atilde
+char227 "
+:a 556,729,14,88,-5,88 2 0344 adieresis
+char228 "
+oa 556,776,14,77,-5,77 2 0345 aring
+char229 "
+ae 889,546,14,84,-6,84 0 0346 ae
+char230 "
+,c 556,546,228,93,-29,90 1 0347 ccedilla
+char231 "
+`e 556,750,14,87,-20,87 2 0350 egrave
+char232 "
+'e 556,750,14,121,-20,90 2 0351 eacute
+char233 "
+^e 556,750,14,87,-20,87 2 0352 ecircumflex
+char234 "
+:e 556,729,14,88,-20,88 2 0353 edieresis
+char235 "
+`i 278,750,0,98,-19,90 2 0354 igrave
+char236 "
+'i 278,750,0,260,-19,90 2 0355 iacute
+char237 "
+^i 278,750,0,216,-19,90 2 0356 icircumflex
+char238 "
+:i 278,729,0,227,-19,90 2 0357 idieresis
+char239 "
+Sd 611,737,14,109,-32,90 2 0360 eth
+char240 "
+~n 611,737,0,85,-15,85 2 0361 ntilde
+char241 "
+`o 611,750,14,82,-32,82 2 0362 ograve
+char242 "
+'o 611,750,14,93,-32,90 2 0363 oacute
+char243 "
+^o 611,750,14,82,-32,82 2 0364 ocircumflex
+char244 "
+~o 611,737,14,85,-32,85 2 0365 otilde
+char245 "
+:o 611,729,14,82,-32,82 2 0366 odieresis
+char246 "
+char247 584,548,42,76,-32,76 0 0367 divide
+/o 611,560,29,140,28,90 0 0370 oslash
+char248 "
+`u 611,750,14,97,-48,90 2 0371 ugrave
+char249 "
+'u 611,750,14,97,-48,90 2 0372 uacute
+char250 "
+^u 611,750,14,97,-48,90 2 0373 ucircumflex
+char251 "
+:u 611,729,14,97,-48,90 2 0374 udieresis
+char252 "
+'y 556,750,214,146,8,90 3 0375 yacute
+char253 "
+Tp 611,718,208,84,32,84 3 0376 thorn
+char254 "
+:y 556,729,214,146,8,90 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/HI b/gnu/usr.bin/groff/devices/devps/HI
new file mode 100644
index 000000000000..bfdcb3280887
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HI
@@ -0,0 +1,617 @@
+name HI
+internalname Helvetica-Oblique
+slant 12
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -40
+A w -40
+A v -40
+A u -30
+A Y -100
+A W -50
+A V -70
+A U -50
+A T -120
+A Q -30
+A O -30
+A G -30
+A C -30
+B . -20
+B , -20
+B U -10
+C . -30
+C , -30
+D . -70
+D , -70
+D Y -90
+D W -40
+D V -70
+D A -40
+F r -45
+F . -150
+F o -30
+F e -30
+F , -150
+F a -50
+F A -80
+J u -20
+J . -30
+J , -30
+J a -20
+J A -20
+K y -50
+K u -30
+K o -40
+K e -40
+K O -50
+L y -30
+L ' -160
+L rq -140
+L Y -140
+L W -70
+L V -110
+L T -110
+O . -40
+O , -40
+O Y -70
+O X -60
+O W -30
+O V -50
+O T -40
+O A -20
+P . -180
+P o -50
+P e -50
+P , -180
+P a -40
+P A -120
+Q U -10
+R Y -50
+R W -30
+R V -50
+R U -40
+R T -30
+R O -20
+S . -20
+S , -20
+T y -120
+T w -120
+T u -120
+T ; -20
+T r -120
+T . -120
+T o -120
+T - -140
+T hy -140
+T char173 -140
+T e -120
+T , -120
+T : -20
+T a -120
+T O -40
+T A -120
+U . -40
+U , -40
+U A -40
+V u -70
+V ; -40
+V . -125
+V o -80
+V - -80
+V hy -80
+V char173 -80
+V e -80
+V , -125
+V : -40
+V a -70
+V O -40
+V G -40
+V A -80
+W y -20
+W u -30
+W . -80
+W o -30
+W - -40
+W hy -40
+W char173 -40
+W e -30
+W , -80
+W a -40
+W O -20
+W A -50
+Y u -110
+Y ; -60
+Y . -140
+Y o -140
+Y i -20
+Y - -140
+Y hy -140
+Y char173 -140
+Y e -140
+Y , -140
+Y : -60
+Y a -140
+Y O -85
+Y A -110
+a y -30
+a w -20
+a v -20
+b y -20
+b v -20
+b u -20
+b . -40
+b l -20
+b , -40
+b b -10
+c k -20
+c , -15
+, ' -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f rq 60
+f . -30
+f o -30
+f e -30
+f .i -28
+f , -30
+f a -30
+g r -10
+h y -30
+k o -20
+k e -20
+m y -15
+m u -10
+n y -15
+n v -20
+n u -10
+o y -30
+o x -30
+o w -15
+o v -15
+o . -40
+o , -40
+/o z -55
+char248 z -55
+/o y -70
+char248 y -70
+/o x -85
+char248 x -85
+/o w -70
+char248 w -70
+/o v -70
+char248 v -70
+/o u -55
+char248 u -55
+/o t -55
+char248 t -55
+/o s -55
+char248 s -55
+/o r -55
+char248 r -55
+/o q -55
+char248 q -55
+/o . -95
+char248 . -95
+/o p -55
+char248 p -55
+/o o -55
+char248 o -55
+/o n -55
+char248 n -55
+/o m -55
+char248 m -55
+/o l -55
+char248 l -55
+/o k -55
+char248 k -55
+/o j -55
+char248 j -55
+/o i -55
+char248 i -55
+/o h -55
+char248 h -55
+/o g -55
+char248 g -55
+/o f -55
+char248 f -55
+/o e -55
+char248 e -55
+/o d -55
+char248 d -55
+/o , -95
+char248 , -95
+/o c -55
+char248 c -55
+/o b -55
+char248 b -55
+/o a -55
+char248 a -55
+p y -30
+p . -35
+p , -35
+. ' -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+' r -50
+' ' -57
+' d -50
+r y 30
+r v 30
+r u 15
+r t 40
+r ; 30
+r . -50
+r p 30
+r n 25
+r m 25
+r l 15
+r k 15
+r i 15
+r , -50
+r : 30
+r a -10
+s w -30
+s . -15
+s , -15
+v . -80
+v o -25
+v e -25
+v , -80
+v a -25
+w . -60
+w o -10
+w e -10
+w , -60
+w a -15
+x e -30
+y . -100
+y o -20
+y e -20
+y , -100
+y a -20
+z o -15
+z e -15
+charset
+ha 469,688,0,120,8,89 2 0000 asciicircum
+ti 584,326,0,46,-61,46 0 0001 asciitilde
+vS 667,929,19,96,-40,89 2 0002 Scaron
+vZ 611,929,0,180,27,89 2 0003 Zcaron
+vs 500,734,15,102,-13,89 2 0004 scaron
+vz 500,734,0,121,19,89 2 0005 zcaron
+:Y 667,901,0,189,-117,89 2 0006 Ydieresis
+tm 1000,718,0,106,-136,89 2 0007 trademark
+aq 191,718,0,144,-107,89 2 0010 quotesingle
+space 278 0 0040
+! 278,718,0,112,-40,89 2 0041 exclam
+" 355,718,0,133,-118,89 2 0042 quotedbl
+# 556,688,0,125,-23,89 2 0043 numbersign
+sh "
+$ 556,775,115,111,-19,89 2 0044 dollar
+Do "
+% 889,703,19,50,-97,50 2 0045 percent
+& 667,718,15,30,-27,30 2 0046 ampersand
+' 222,718,0,138,-101,89 2 0047 quoteright
+( 333,733,207,171,-58,89 3 0050 parenleft
+) 333,733,207,54,59,54 3 0051 parenright
+* 389,718,0,136,-115,89 2 0052 asterisk
++ 584,505,0,72,-35,72 0 0053 plus
+, 278,106,147,0,-6 0 0054 comma
+- 333,322,0,74,-43,74 0 0055 hyphen
+hy "
+char173 "
+. 278,106,0,0,-37 0 0056 period
+/ 278,737,19,224,71,89 2 0057 slash
+sl "
+0 556,703,19,102,-43,89 2 0060 zero
+1 556,703,0,2,-157,2 2 0061 one
+2 556,703,0,111,24,89 2 0062 two
+3 556,703,19,104,-25,89 2 0063 three
+4 556,703,0,70,-11,70 2 0064 four
+5 556,688,19,115,-18,89 2 0065 five
+6 556,703,19,109,-41,89 2 0066 six
+7 556,688,0,163,-87,89 2 0067 seven
+8 556,703,19,101,-24,89 2 0070 eight
+9 556,703,19,103,-32,89 2 0071 nine
+: 278,516,0,73,-37,73 0 0072 colon
+; 278,516,147,73,-6,73 0 0073 semicolon
+< 584,495,0,107,-44,89 0 0074 less
+= 584,390,0,94,-13,89 0 0075 equal
+> 584,495,0,63,0,63 0 0076 greater
+? 556,727,0,104,-111,89 2 0077 question
+@ 1015,737,19,0,-165 2 0100 at
+at "
+A 667,718,0,37,36,37 2 0101 A
+B 667,718,0,95,-24,89 2 0102 B
+C 722,737,19,110,-58,89 2 0103 C
+D 722,718,0,92,-31,89 2 0104 D
+E 667,718,0,145,-36,89 2 0105 E
+F 611,718,0,175,-36,89 2 0106 F
+G 778,737,19,71,-61,71 2 0107 G
+H 722,718,0,127,-27,89 2 0110 H
+I 278,718,0,113,-41,89 2 0111 I
+J 500,718,19,131,3,89 2 0112 J
+K 667,718,0,191,-26,89 2 0113 K
+L 556,718,0,49,-26,49 2 0114 L
+M 833,718,0,131,-23,89 2 0115 M
+N 722,718,0,127,-26,89 2 0116 N
+O 778,737,19,98,-55,89 2 0117 O
+P 667,718,0,120,-36,89 2 0120 P
+Q 778,737,56,98,-55,89 2 0121 Q
+R 722,718,0,101,-38,89 2 0122 R
+S 667,737,19,96,-40,89 2 0123 S
+T 611,718,0,189,-98,89 2 0124 T
+U 722,718,19,125,-73,89 2 0125 U
+V 667,718,0,183,-123,89 2 0126 V
+W 944,718,0,187,-119,89 2 0127 W
+X 667,718,0,173,31,89 2 0130 X
+Y 667,718,0,189,-117,89 2 0131 Y
+Z 611,718,0,180,27,89 2 0132 Z
+[ 278,722,196,175,29,89 2 0133 bracketleft
+lB "
+\ 278,737,19,63,-90,63 2 0134 backslash
+rs "
+] 278,722,196,140,64,89 2 0135 bracketright
+rB "
+a^ 333,734,0,155,-97,89 2 0136 circumflex
+^ "
+_ 556,0,125,34,77,34 0 0137 underscore
+` 222,725,0,151,-115,89 2 0140 quoteleft
+oq "
+a 556,538,15,53,-11,53 0 0141 a
+b 556,718,15,78,-8,78 2 0142 b
+c 500,538,15,103,-24,89 0 0143 c
+d 556,718,15,146,-34,89 2 0144 d
+e 556,538,15,72,-34,72 0 0145 e
+f 278,728,0,188,-36,89 2 0146 f
+g 556,538,220,104,8,89 1 0147 g
+h 556,718,0,67,-15,67 2 0150 h
+i 222,718,0,136,-17,89 2 0151 i
+j 222,718,210,136,110,89 3 0152 j
+k 500,718,0,150,-17,89 2 0153 k
+l 222,718,0,136,-17,89 2 0154 l
+m 833,538,0,69,-15,69 0 0155 m
+n 556,538,0,67,-15,67 0 0156 n
+o 556,538,14,79,-33,79 0 0157 o
+p 556,538,207,78,36,78 1 0160 p
+q 556,538,207,99,-34,89 1 0161 q
+r 333,538,0,163,-27,89 0 0162 r
+s 500,538,15,79,-13,79 0 0163 s
+t 278,669,7,140,-52,89 2 0164 t
+u 556,523,15,94,-44,89 0 0165 u
+v 500,523,0,153,-69,89 0 0166 v
+w 722,523,0,148,-75,89 0 0167 w
+x 500,523,0,144,39,89 0 0170 x
+y 500,523,214,150,35,89 1 0171 y
+z 500,523,0,121,19,89 0 0172 z
+lC 334,722,196,161,-42,89 2 0173 braceleft
+{ "
+ba 260,737,19,114,-40,89 2 0174 bar
+| "
+rC 334,722,196,70,50,70 2 0175 braceright
+} "
+a~ 333,722,0,207,-75,89 2 0176 tilde
+~ "
+bq 222,106,149,8,29,8 0 0200 quotesinglbase
+Fo 556,446,0,48,-96,48 0 0201 guillemotleft
+char171 "
+Fc 556,446,0,22,-70,22 0 0202 guillemotright
+char187 "
+bu 350,517,0,113,-41,89 0 0203 bullet
+Fn 556,737,207,148,102,89 3 0204 florin
+f/ 167,703,19,365,220,89 2 0205 fraction
+%0 1000,703,19,79,-38,79 2 0206 perthousand
+dg 556,718,159,116,-85,89 2 0207 dagger
+dd 556,718,159,117,-2,89 2 0210 daggerdbl
+en 556,313,0,117,-1,89 0 0211 endash
+em 1000,313,0,117,-1,89 0 0212 emdash
+fi 500,728,0,137,-36,89 2 0214 fi
+fl 500,728,0,135,-36,89 2 0215 fl
+.i 278,523,0,66,-45,66 0 0220 dotlessi
+ga 333,734,0,54,-120,54 2 0222 grave
+a" 333,734,0,282,-107,89 2 0223 hungarumlaut
+a. 333,706,0,79,-199,79 2 0224 dotaccent
+ab 333,731,0,193,-117,89 2 0225 breve
+ah 333,734,0,185,-127,89 2 0226 caron
+ao 333,756,0,119,-164,89 2 0227 ring
+ho 333,0,225,0,7 1 0230 ogonek
+lq 333,725,0,178,-88,89 2 0231 quotedblleft
+rq 333,718,0,165,-74,89 2 0232 quotedblright
+oe 944,538,15,70,-33,70 0 0233 oe
+/l 222,718,0,175,9,89 2 0234 lslash
+Bq 333,106,149,35,56,35 0 0235 quotedblbase
+OE 1000,737,19,166,-48,89 2 0236 OE
+/L 556,718,0,49,9,49 2 0237 Lslash
+r! 333,523,195,43,-27,43 0 0241 exclamdown
+char161 "
+ct 556,623,115,78,-45,78 0 0242 cent
+char162 "
+Po 556,718,16,128,1,89 2 0243 sterling
+char163 "
+Cs 556,603,0,140,-10,89 0 0244 currency
+char164 "
+Ye 556,688,0,193,-31,89 2 0245 yen
+char165 "
+bb 260,737,19,114,-40,89 2 0246 brokenbar
+char166 "
+sc 556,737,191,78,-26,78 2 0247 section
+char167 "
+ad 333,706,0,160,-118,89 2 0250 dieresis
+char168 "
+co 737,737,19,150,-4,89 2 0251 copyright
+char169 "
+Of 370,737,0,129,-50,89 2 0252 ordfeminine
+char170 "
+fo 333,446,0,57,-87,57 0 0253 guilsinglleft
+no 584,390,0,94,-56,89 0 0254 logicalnot
+char172 "
+\- 584,289,0,72,-35,72 0 0255 minus
+rg 737,737,19,150,-4,89 2 0256 registered
+char174 "
+a- 333,684,0,185,-93,89 2 0257 macron
+char175 "
+de 400,703,0,118,-119,89 2 0260 degree
+char176 "
+char177 584,506,0,84,11,84 0 0261 plusminus
+S2 333,703,0,166,-14,89 2 0262 twosuperior
+char178 "
+S3 333,703,0,153,-40,89 2 0263 threesuperior
+char179 "
+aa 333,734,0,192,-198,89 2 0264 acute
+char180 "
+char181 556,523,207,94,26,89 1 0265 mu
+ps 537,718,173,163,-76,89 2 0266 paragraph
+char182 "
+char183 278,315,0,29,-79,29 0 0267 periodcentered
+ac 333,0,225,0,48 1 0270 cedilla
+char184 "
+S1 333,703,0,88,-116,88 2 0271 onesuperior
+char185 "
+Om 365,737,0,153,-50,89 2 0272 ordmasculine
+char186 "
+fc 333,446,0,31,-61,31 0 0273 guilsinglright
+14 834,703,19,18,-100,18 2 0274 onequarter
+char188 "
+12 834,703,19,55,-64,55 2 0275 onehalf
+char189 "
+34 834,703,19,77,-80,77 2 0276 threequarters
+char190 "
+r? 611,525,201,0,-35 0 0277 questiondown
+char191 "
+`A 667,929,0,37,36,37 2 0300 Agrave
+char192 "
+'A 667,929,0,66,36,66 2 0301 Aacute
+char193 "
+^A 667,929,0,37,36,37 2 0302 Acircumflex
+char194 "
+~A 667,917,0,82,36,82 2 0303 Atilde
+char195 "
+:A 667,901,0,37,36,37 2 0304 Adieresis
+char196 "
+oA 667,931,0,37,36,37 2 0305 Aring
+char197 "
+AE 1000,718,0,147,42,89 2 0306 AE
+char198 "
+,C 722,737,225,110,-58,89 3 0307 Ccedilla
+char199 "
+`E 667,929,0,145,-36,89 2 0310 Egrave
+char200 "
+'E 667,929,0,145,-36,89 2 0311 Eacute
+char201 "
+^E 667,929,0,145,-36,89 2 0312 Ecircumflex
+char202 "
+:E 667,901,0,145,-36,89 2 0313 Edieresis
+char203 "
+`I 278,929,0,123,-41,89 2 0314 Igrave
+char204 "
+'I 278,929,0,261,-41,89 2 0315 Iacute
+char205 "
+^I 278,929,0,224,-41,89 2 0316 Icircumflex
+char206 "
+:I 278,901,0,230,-41,89 2 0317 Idieresis
+char207 "
+-D 722,718,0,92,-19,89 2 0320 Eth
+char208 "
+~N 722,917,0,127,-26,89 2 0321 Ntilde
+char209 "
+`O 778,929,19,98,-55,89 2 0322 Ograve
+char210 "
+'O 778,929,19,98,-55,89 2 0323 Oacute
+char211 "
+^O 778,929,19,98,-55,89 2 0324 Ocircumflex
+char212 "
+~O 778,917,19,98,-55,89 2 0325 Otilde
+char213 "
+:O 778,901,19,98,-55,89 2 0326 Odieresis
+char214 "
+char215 584,506,0,108,0,89 0 0327 multiply
+/O 778,737,19,162,7,89 2 0330 Oslash
+char216 "
+`U 722,929,19,125,-73,89 2 0331 Ugrave
+char217 "
+'U 722,929,19,125,-73,89 2 0332 Uacute
+char218 "
+^U 722,929,19,125,-73,89 2 0333 Ucircumflex
+char219 "
+:U 722,901,19,125,-73,89 2 0334 Udieresis
+char220 "
+'Y 667,929,0,189,-117,89 2 0335 Yacute
+char221 "
+TP 667,718,0,95,-36,89 2 0336 Thorn
+char222 "
+ss 611,728,15,97,-17,89 2 0337 germandbls
+char223 "
+`a 556,734,15,53,-11,53 2 0340 agrave
+char224 "
+'a 556,734,15,81,-11,81 2 0341 aacute
+char225 "
+^a 556,734,15,53,-11,53 2 0342 acircumflex
+char226 "
+~a 556,722,15,86,-11,86 2 0343 atilde
+char227 "
+:a 556,706,15,53,-11,53 2 0344 adieresis
+char228 "
+oa 556,756,15,53,-11,53 2 0345 aring
+char229 "
+ae 889,538,15,70,-11,70 0 0346 ae
+char230 "
+,c 500,538,225,103,-24,89 1 0347 ccedilla
+char231 "
+`e 556,734,15,72,-34,72 2 0350 egrave
+char232 "
+'e 556,734,15,81,-34,81 2 0351 eacute
+char233 "
+^e 556,734,15,72,-34,72 2 0352 ecircumflex
+char234 "
+:e 556,706,15,72,-34,72 2 0353 edieresis
+char235 "
+`i 278,734,0,82,-45,82 2 0354 igrave
+char236 "
+'i 278,734,0,220,-45,89 2 0355 iacute
+char237 "
+^i 278,734,0,183,-45,89 2 0356 icircumflex
+char238 "
+:i 278,706,0,188,-45,89 2 0357 idieresis
+char239 "
+Sd 556,737,15,111,-31,89 2 0360 eth
+char240 "
+~n 556,722,0,86,-15,86 2 0361 ntilde
+char241 "
+`o 556,734,14,79,-33,79 2 0362 ograve
+char242 "
+'o 556,734,14,81,-33,81 2 0363 oacute
+char243 "
+^o 556,734,14,79,-33,79 2 0364 ocircumflex
+char244 "
+~o 556,722,14,96,-33,89 2 0365 otilde
+char245 "
+:o 556,706,14,79,-33,79 2 0366 odieresis
+char246 "
+char247 584,524,19,72,-35,72 0 0367 divide
+/o 611,545,22,86,21,86 0 0370 oslash
+char248 "
+`u 556,734,15,94,-44,89 2 0371 ugrave
+char249 "
+'u 556,734,15,94,-44,89 2 0372 uacute
+char250 "
+^u 556,734,15,94,-44,89 2 0373 ucircumflex
+char251 "
+:u 556,706,15,94,-44,89 2 0374 udieresis
+char252 "
+'y 500,734,214,150,35,89 3 0375 yacute
+char253 "
+Tp 556,718,207,78,36,78 3 0376 thorn
+char254 "
+:y 500,706,214,150,35,89 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/HNB b/gnu/usr.bin/groff/devices/devps/HNB
new file mode 100644
index 000000000000..6e6467427749
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HNB
@@ -0,0 +1,546 @@
+name HNB
+internalname Helvetica-Narrow-Bold
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -24
+A w -24
+A v -32
+A u -24
+A Y -89
+A W -48
+A V -65
+A U -40
+A T -73
+A Q -32
+A O -32
+A G -40
+A C -32
+B U -7
+B A -24
+D . -24
+D , -24
+D Y -56
+D W -32
+D V -32
+D A -32
+F . -81
+F , -81
+F a -15
+F A -65
+J u -15
+J . -15
+J , -15
+J A -15
+K y -32
+K u -24
+K o -28
+K e -11
+K O -24
+L y -24
+L ' -114
+L rq -114
+L Y -97
+L W -65
+L V -89
+L T -73
+O . -32
+O , -32
+O Y -56
+O X -40
+O W -40
+O V -40
+O T -32
+O A -40
+P . -97
+P o -32
+P e -24
+P , -97
+P a -24
+P A -81
+Q . 16
+Q , 16
+Q U -7
+R Y -40
+R W -32
+R V -40
+R U -15
+R T -15
+R O -15
+T y -48
+T w -48
+T u -73
+T ; -32
+T r -65
+T . -65
+T o -65
+T - -97
+T hy -97
+T char173 -97
+T e -48
+T , -65
+T : -32
+T a -65
+T O -32
+T A -73
+U . -24
+U , -24
+U A -40
+V u -48
+V ; -32
+V . -97
+V o -73
+V - -65
+V hy -65
+V char173 -65
+V e -40
+V , -97
+V : -32
+V a -48
+V O -40
+V G -40
+V A -65
+W y -15
+W u -36
+W ; -7
+W . -65
+W o -48
+W - -32
+W hy -32
+W char173 -32
+W e -28
+W , -65
+W : -7
+W a -32
+W O -15
+W A -48
+Y u -81
+Y ; -40
+Y . -81
+Y o -81
+Y e -65
+Y , -81
+Y : -40
+Y a -73
+Y O -56
+Y A -89
+a y -15
+a w -11
+a v -11
+a g -7
+b y -15
+b v -15
+b u -15
+b l -7
+c y -7
+c l -15
+c k -15
+c h -7
+, ' -97
+, rq -97
+d y -11
+d w -11
+d v -11
+d d -7
+e y -11
+e x -11
+e w -11
+e v -11
+e . 16
+e , 8
+f ' 25
+f rq 25
+f . -7
+f o -15
+f e -7
+f , -7
+g g -7
+g e 8
+h y -15
+k o -11
+l y -11
+l w -11
+m y -24
+m u -15
+n y -15
+n v -32
+n u -7
+o y -15
+o x -24
+o w -11
+o v -15
+p y -11
+. ' -97
+. rq -97
+` ` -37
+` oq -37
+oq ` -37
+oq oq -37
+' v -15
+' s -48
+' r -32
+' ' -37
+' l -15
+' d -65
+r y 8
+r v 8
+r t 16
+r s -11
+r q -15
+r . -48
+r o -15
+r - -15
+r hy -15
+r char173 -15
+r g -11
+r d -15
+r , -48
+r c -15
+s w -11
+v . -65
+v o -24
+v , -65
+v a -15
+w . -32
+w o -15
+w , -32
+x e -7
+y . -65
+y o -20
+y e -7
+y , -65
+y a -24
+z e 8
+charset
+ha 479,698 2 0000 asciicircum
+ti 479,343 0 0001 asciitilde
+vS 547,936,19 2 0002 Scaron
+vZ 501,936 2 0003 Zcaron
+vs 456,750,14 2 0004 scaron
+vz 410,750 2 0005 zcaron
+:Y 547,915 2 0006 Ydieresis
+tm 820,718 2 0007 trademark
+aq 195,718 2 0010 quotesingle
+space 228 0 0040
+! 273,718 2 0041 exclam
+" 389,718 2 0042 quotedbl
+# 456,698 2 0043 numbersign
+sh "
+$ 456,775,115 2 0044 dollar
+Do "
+% 729,710,19 2 0045 percent
+& 592,718,19 2 0046 ampersand
+' 228,718 2 0047 quoteright
+( 273,734,208 3 0050 parenleft
+) 273,734,208 3 0051 parenright
+* 319,718 2 0052 asterisk
++ 479,506 0 0053 plus
+, 228,146,168 0 0054 comma
+- 273,345 0 0055 hyphen
+hy "
+char173 "
+. 228,146 0 0056 period
+/ 228,737,19 2 0057 slash
+sl "
+0 456,710,19 2 0060 zero
+1 456,710 2 0061 one
+2 456,710 2 0062 two
+3 456,710,19 2 0063 three
+4 456,710 2 0064 four
+5 456,698,19 2 0065 five
+6 456,710,19 2 0066 six
+7 456,698 2 0067 seven
+8 456,710,19 2 0070 eight
+9 456,710,19 2 0071 nine
+: 273,512 0 0072 colon
+; 273,512,168 0 0073 semicolon
+< 479,514,8 0 0074 less
+= 479,419 0 0075 equal
+> 479,514,8 0 0076 greater
+? 501,727 2 0077 question
+@ 800,737,19 2 0100 at
+at "
+A 592,718 2 0101 A
+B 592,718 2 0102 B
+C 592,737,19 2 0103 C
+D 592,718 2 0104 D
+E 547,718 2 0105 E
+F 501,718 2 0106 F
+G 638,737,19 2 0107 G
+H 592,718 2 0110 H
+I 228,718 2 0111 I
+J 456,718,18 2 0112 J
+K 592,718 2 0113 K
+L 501,718 2 0114 L
+M 683,718 2 0115 M
+N 592,718 2 0116 N
+O 638,737,19 2 0117 O
+P 547,718 2 0120 P
+Q 638,737,52 2 0121 Q
+R 592,718 2 0122 R
+S 547,737,19 2 0123 S
+T 501,718 2 0124 T
+U 592,718,19 2 0125 U
+V 547,718 2 0126 V
+W 774,718 2 0127 W
+X 547,718 2 0130 X
+Y 547,718 2 0131 Y
+Z 501,718 2 0132 Z
+[ 273,722,196 2 0133 bracketleft
+lB "
+\ 228,737,19 2 0134 backslash
+rs "
+] 273,722,196 2 0135 bracketright
+rB "
+a^ 273,750 2 0136 circumflex
+^ "
+_ 456,0,125 0 0137 underscore
+` 228,727 2 0140 quoteleft
+oq "
+a 456,546,14 0 0141 a
+b 501,718,14 2 0142 b
+c 456,546,14 0 0143 c
+d 501,718,14 2 0144 d
+e 456,546,14 0 0145 e
+f 273,727 2 0146 f
+g 501,546,217 1 0147 g
+h 501,718 2 0150 h
+i 228,725 2 0151 i
+j 228,725,214 3 0152 j
+k 456,718 2 0153 k
+l 228,718 2 0154 l
+m 729,546 0 0155 m
+n 501,546 0 0156 n
+o 501,546,14 0 0157 o
+p 501,546,207 1 0160 p
+q 501,546,207 1 0161 q
+r 319,546 0 0162 r
+s 456,546,14 0 0163 s
+t 273,676,6 2 0164 t
+u 501,532,14 0 0165 u
+v 456,532 0 0166 v
+w 638,532 0 0167 w
+x 456,532 0 0170 x
+y 456,532,214 1 0171 y
+z 410,532 0 0172 z
+lC 319,722,196 2 0173 braceleft
+{ "
+ba 230,737,19 2 0174 bar
+| "
+rC 319,722,196 2 0175 braceright
+} "
+a~ 273,737 2 0176 tilde
+~ "
+bq 228,127,146 0 0200 quotesinglbase
+Fo 456,484 0 0201 guillemotleft
+char171 "
+Fc 456,484 0 0202 guillemotright
+char187 "
+bu 287,524 0 0203 bullet
+Fn 456,737,210 3 0204 florin
+f/ 137,710,19 2 0205 fraction
+%0 820,710,19 2 0206 perthousand
+dg 456,718,171 2 0207 dagger
+dd 456,718,171 2 0210 daggerdbl
+en 456,333 0 0211 endash
+em 820,333 0 0212 emdash
+fi 501,727 2 0214 fi
+fl 501,727 2 0215 fl
+.i 228,532 0 0220 dotlessi
+ga 273,750 2 0222 grave
+a" 273,750 2 0223 hungarumlaut
+a. 273,729 2 0224 dotaccent
+ab 273,750 2 0225 breve
+ah 273,750 2 0226 caron
+ao 273,776 2 0227 ring
+ho 273,0,228 1 0230 ogonek
+lq 410,727 2 0231 quotedblleft
+rq 410,718 2 0232 quotedblright
+oe 774,546,14 0 0233 oe
+/l 228,718 2 0234 lslash
+Bq 410,127,146 0 0235 quotedblbase
+OE 820,737,19 2 0236 OE
+/L 501,718 2 0237 Lslash
+r! 273,532,186 0 0241 exclamdown
+char161 "
+ct 456,628,118 0 0242 cent
+char162 "
+Po 456,718,16 2 0243 sterling
+char163 "
+Cs 456,636 0 0244 currency
+char164 "
+Ye 456,698 2 0245 yen
+char165 "
+bb 230,737,19 2 0246 brokenbar
+char166 "
+sc 456,727,184 2 0247 section
+char167 "
+ad 273,729 2 0250 dieresis
+char168 "
+co 604,737,19 2 0251 copyright
+char169 "
+Of 303,737 2 0252 ordfeminine
+char170 "
+fo 273,484 0 0253 guilsinglleft
+no 479,419 0 0254 logicalnot
+char172 "
+\- 479,309 0 0255 minus
+rg 604,737,19 2 0256 registered
+char174 "
+a- 273,678 2 0257 macron
+char175 "
+de 328,712 2 0260 degree
+char176 "
+char177 479,506 0 0261 plusminus
+S2 273,710 2 0262 twosuperior
+char178 "
+S3 273,710 2 0263 threesuperior
+char179 "
+aa 273,750 2 0264 acute
+char180 "
+char181 501,532,207 1 0265 mu
+ps 456,700,191 2 0266 paragraph
+char182 "
+char183 228,334 0 0267 periodcentered
+ac 273,0,228 1 0270 cedilla
+char184 "
+S1 273,710 2 0271 onesuperior
+char185 "
+Om 299,737 2 0272 ordmasculine
+char186 "
+fc 273,484 0 0273 guilsinglright
+14 684,710,19 2 0274 onequarter
+char188 "
+12 684,710,19 2 0275 onehalf
+char189 "
+34 684,710,19 2 0276 threequarters
+char190 "
+r? 501,532,195 0 0277 questiondown
+char191 "
+`A 592,936 2 0300 Agrave
+char192 "
+'A 592,936 2 0301 Aacute
+char193 "
+^A 592,936 2 0302 Acircumflex
+char194 "
+~A 592,923 2 0303 Atilde
+char195 "
+:A 592,915 2 0304 Adieresis
+char196 "
+oA 592,962 2 0305 Aring
+char197 "
+AE 820,718 2 0306 AE
+char198 "
+,C 592,737,228 3 0307 Ccedilla
+char199 "
+`E 547,936 2 0310 Egrave
+char200 "
+'E 547,936 2 0311 Eacute
+char201 "
+^E 547,936 2 0312 Ecircumflex
+char202 "
+:E 547,915 2 0313 Edieresis
+char203 "
+`I 228,936 2 0314 Igrave
+char204 "
+'I 228,936 2 0315 Iacute
+char205 "
+^I 228,936 2 0316 Icircumflex
+char206 "
+:I 228,915 2 0317 Idieresis
+char207 "
+-D 592,718 2 0320 Eth
+char208 "
+~N 592,923 2 0321 Ntilde
+char209 "
+`O 638,936,19 2 0322 Ograve
+char210 "
+'O 638,936,19 2 0323 Oacute
+char211 "
+^O 638,936,19 2 0324 Ocircumflex
+char212 "
+~O 638,923,19 2 0325 Otilde
+char213 "
+:O 638,915,19 2 0326 Odieresis
+char214 "
+char215 479,505 0 0327 multiply
+/O 638,745,27 2 0330 Oslash
+char216 "
+`U 592,936,19 2 0331 Ugrave
+char217 "
+'U 592,936,19 2 0332 Uacute
+char218 "
+^U 592,936,19 2 0333 Ucircumflex
+char219 "
+:U 592,915,19 2 0334 Udieresis
+char220 "
+'Y 547,936 2 0335 Yacute
+char221 "
+TP 547,718 2 0336 Thorn
+char222 "
+ss 501,731,14 2 0337 germandbls
+char223 "
+`a 456,750,14 2 0340 agrave
+char224 "
+'a 456,750,14 2 0341 aacute
+char225 "
+^a 456,750,14 2 0342 acircumflex
+char226 "
+~a 456,737,14 2 0343 atilde
+char227 "
+:a 456,729,14 2 0344 adieresis
+char228 "
+oa 456,776,14 2 0345 aring
+char229 "
+ae 729,546,14 0 0346 ae
+char230 "
+,c 456,546,228 1 0347 ccedilla
+char231 "
+`e 456,750,14 2 0350 egrave
+char232 "
+'e 456,750,14 2 0351 eacute
+char233 "
+^e 456,750,14 2 0352 ecircumflex
+char234 "
+:e 456,729,14 2 0353 edieresis
+char235 "
+`i 228,750 2 0354 igrave
+char236 "
+'i 228,750 2 0355 iacute
+char237 "
+^i 228,750 2 0356 icircumflex
+char238 "
+:i 228,729 2 0357 idieresis
+char239 "
+Sd 501,737,14 2 0360 eth
+char240 "
+~n 501,737 2 0361 ntilde
+char241 "
+`o 501,750,14 2 0362 ograve
+char242 "
+'o 501,750,14 2 0363 oacute
+char243 "
+^o 501,750,14 2 0364 ocircumflex
+char244 "
+~o 501,737,14 2 0365 otilde
+char245 "
+:o 501,729,14 2 0366 odieresis
+char246 "
+char247 479,548,42 0 0367 divide
+/o 501,560,29 0 0370 oslash
+char248 "
+`u 501,750,14 2 0371 ugrave
+char249 "
+'u 501,750,14 2 0372 uacute
+char250 "
+^u 501,750,14 2 0373 ucircumflex
+char251 "
+:u 501,729,14 2 0374 udieresis
+char252 "
+'y 456,750,214 3 0375 yacute
+char253 "
+Tp 501,718,208 3 0376 thorn
+char254 "
+:y 456,729,214 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/HNBI b/gnu/usr.bin/groff/devices/devps/HNBI
new file mode 100644
index 000000000000..c0bb37eea4f8
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HNBI
@@ -0,0 +1,547 @@
+name HNBI
+internalname Helvetica-Narrow-BoldOblique
+slant 12
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -30
+A w -30
+A v -40
+A u -30
+A Y -110
+A W -60
+A V -80
+A U -50
+A T -90
+A Q -40
+A O -40
+A G -50
+A C -40
+B U -10
+B A -30
+D . -30
+D , -30
+D Y -70
+D W -40
+D V -40
+D A -40
+F . -100
+F , -100
+F a -20
+F A -80
+J u -20
+J . -20
+J , -20
+J A -20
+K y -40
+K u -30
+K o -35
+K e -15
+K O -30
+L y -30
+L ' -140
+L rq -140
+L Y -120
+L W -80
+L V -110
+L T -90
+O . -40
+O , -40
+O Y -70
+O X -50
+O W -50
+O V -50
+O T -40
+O A -50
+P . -120
+P o -40
+P e -30
+P , -120
+P a -30
+P A -100
+Q . 20
+Q , 20
+Q U -10
+R Y -50
+R W -40
+R V -50
+R U -20
+R T -20
+R O -20
+T y -60
+T w -60
+T u -90
+T ; -40
+T r -80
+T . -80
+T o -80
+T - -120
+T hy -120
+T char173 -120
+T e -60
+T , -80
+T : -40
+T a -80
+T O -40
+T A -90
+U . -30
+U , -30
+U A -50
+V u -60
+V ; -40
+V . -120
+V o -90
+V - -80
+V hy -80
+V char173 -80
+V e -50
+V , -120
+V : -40
+V a -60
+V O -50
+V G -50
+V A -80
+W y -20
+W u -45
+W ; -10
+W . -80
+W o -60
+W - -40
+W hy -40
+W char173 -40
+W e -35
+W , -80
+W : -10
+W a -40
+W O -20
+W A -60
+Y u -100
+Y ; -50
+Y . -100
+Y o -100
+Y e -80
+Y , -100
+Y : -50
+Y a -90
+Y O -70
+Y A -110
+a y -20
+a w -15
+a v -15
+a g -10
+b y -20
+b v -20
+b u -20
+b l -10
+c y -10
+c l -20
+c k -20
+c h -10
+, ' -120
+, rq -120
+d y -15
+d w -15
+d v -15
+d d -10
+e y -15
+e x -15
+e w -15
+e v -15
+e . 20
+e , 10
+f ' 30
+f rq 30
+f . -10
+f o -20
+f e -10
+f , -10
+g g -10
+g e 10
+h y -20
+k o -15
+l y -15
+l w -15
+m y -30
+m u -20
+n y -20
+n v -40
+n u -10
+o y -20
+o x -30
+o w -15
+o v -20
+p y -15
+. ' -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+' s -60
+' r -40
+' ' -46
+' l -20
+' d -80
+r y 10
+r v 10
+r t 20
+r s -15
+r q -20
+r . -60
+r o -20
+r - -20
+r hy -20
+r char173 -20
+r g -15
+r d -20
+r , -60
+r c -20
+s w -15
+v . -80
+v o -30
+v , -80
+v a -20
+w . -40
+w o -20
+w , -40
+x e -10
+y . -80
+y o -25
+y e -10
+y , -80
+y a -30
+z e 10
+charset
+ha 479,698,0,55,-57,55 2 0000 asciicircum
+ti 479,343,0,44,-44,44 0 0001 asciitilde
+vS 547,936,19,91,-16,90 2 0002 Scaron
+vZ 501,936,0,153,30,90 2 0003 Zcaron
+vs 456,750,14,98,-2,90 2 0004 scaron
+vz 410,750,0,121,34,90 2 0005 zcaron
+:Y 547,915,0,164,-87,90 2 0006 Ydieresis
+tm 820,718,0,139,-96,90 2 0007 trademark
+aq 195,718,0,118,-85,90 2 0010 quotesingle
+space 228 0 0040
+! 273,718,0,102,-27,90 2 0041 exclam
+" 389,718,0,94,-108,90 2 0042 quotedbl
+# 456,698,0,122,1,90 2 0043 numbersign
+sh "
+$ 456,775,115,104,-5,90 2 0044 dollar
+Do "
+% 729,710,19,60,-62,60 2 0045 percent
+& 592,718,19,58,-23,58 2 0046 ampersand
+' 228,718,0,119,-87,90 2 0047 quoteright
+( 273,734,208,162,-12,90 3 0050 parenleft
+) 273,734,208,79,71,79 3 0051 parenright
+* 319,718,0,125,-70,90 2 0052 asterisk
++ 479,506,0,71,-17,71 0 0053 plus
+, 228,146,168,23,27,23 0 0054 comma
+- 273,345,0,88,-10,88 0 0055 hyphen
+hy "
+char173 "
+. 228,146,0,23,-2,23 0 0056 period
+/ 228,737,19,205,80,90 2 0057 slash
+sl "
+0 456,710,19,100,-21,90 2 0060 zero
+1 456,710,0,28,-92,28 2 0061 one
+2 456,710,0,102,29,90 2 0062 two
+3 456,710,19,93,-4,90 2 0063 three
+4 456,710,0,84,0,84 2 0064 four
+5 456,698,19,116,-3,90 2 0065 five
+6 456,710,19,101,-20,90 2 0066 six
+7 456,698,0,149,-52,90 2 0067 seven
+8 456,710,19,99,-7,90 2 0070 eight
+9 456,710,19,98,-14,90 2 0071 nine
+: 273,512,0,65,-25,65 0 0072 colon
+; 273,512,168,65,4,65 0 0073 semicolon
+< 479,514,8,108,-17,90 0 0074 less
+= 479,419,0,90,2,90 0 0075 equal
+> 479,514,8,71,20,71 0 0076 greater
+? 501,727,0,99,-85,90 2 0077 question
+@ 800,737,19,32,-102,32 2 0100 at
+at "
+A 592,718,0,34,34,34 2 0101 A
+B 592,718,0,84,-12,84 2 0102 B
+C 592,737,19,105,-38,90 2 0103 C
+D 592,718,0,95,-12,90 2 0104 D
+E 547,718,0,123,-12,90 2 0105 E
+F 501,718,0,155,-12,90 2 0106 F
+G 638,737,19,82,-39,82 2 0107 G
+H 592,718,0,117,-8,90 2 0110 H
+I 228,718,0,123,-2,90 2 0111 I
+J 456,718,18,116,1,90 2 0112 J
+K 592,718,0,161,-21,90 2 0113 K
+L 501,718,0,50,-12,50 2 0114 L
+M 683,718,0,119,-7,90 2 0115 M
+N 592,718,0,119,-7,90 2 0116 N
+O 638,737,19,87,-38,87 2 0117 O
+P 547,718,0,108,-12,90 2 0120 P
+Q 638,737,52,87,-38,87 2 0121 Q
+R 592,718,0,96,-12,90 2 0122 R
+S 547,737,19,91,-16,90 2 0123 S
+T 501,718,0,164,-64,90 2 0124 T
+U 592,718,19,117,-46,90 2 0125 U
+V 547,718,0,159,-91,90 2 0126 V
+W 774,718,0,163,-88,90 2 0127 W
+X 547,718,0,151,39,90 2 0130 X
+Y 547,718,0,164,-87,90 2 0131 Y
+Z 501,718,0,153,30,90 2 0132 Z
+[ 273,722,196,156,33,90 2 0133 bracketleft
+lB "
+\ 228,737,19,74,-51,74 2 0134 backslash
+rs "
+] 273,722,196,124,64,90 2 0135 bracketright
+rB "
+a^ 273,750,0,164,-47,90 2 0136 circumflex
+^ "
+_ 456,0,125,37,72,37 0 0137 underscore
+` 228,727,0,118,-86,90 2 0140 quoteleft
+oq "
+a 456,546,14,72,5,72 0 0141 a
+b 501,718,14,78,0,78 2 0142 b
+c 456,546,14,85,-15,85 0 0143 c
+d 501,718,14,126,-17,90 2 0144 d
+e 456,546,14,80,-8,80 0 0145 e
+f 273,727,0,162,-21,90 2 0146 f
+g 501,546,217,95,19,90 1 0147 g
+h 501,718,0,65,-3,65 2 0150 h
+i 228,725,0,120,-7,90 2 0151 i
+j 228,725,214,120,85,90 3 0152 j
+k 456,718,0,143,-7,90 2 0153 k
+l 228,718,0,119,-7,90 2 0154 l
+m 729,546,0,67,-2,67 0 0155 m
+n 501,546,0,65,-3,65 0 0156 n
+o 501,546,14,76,-17,76 0 0157 o
+p 501,546,207,78,35,78 1 0160 p
+q 501,546,207,94,-16,90 1 0161 q
+r 319,546,0,132,-2,90 0 0162 r
+s 456,546,14,73,-2,73 0 0163 s
+t 273,676,6,123,-32,90 2 0164 t
+u 501,532,14,89,-30,89 0 0165 u
+v 456,532,0,132,-53,90 0 0166 v
+w 638,532,0,135,-51,90 0 0167 w
+x 456,532,0,125,38,90 0 0170 x
+y 456,532,214,129,16,90 1 0171 y
+z 410,532,0,118,34,90 0 0172 z
+lC 319,722,196,156,-27,90 2 0173 braceleft
+{ "
+ba 230,737,19,109,-16,90 2 0174 bar
+| "
+rC 319,722,196,64,64,64 2 0175 braceright
+} "
+a~ 273,737,0,192,-42,90 2 0176 tilde
+~ "
+bq 228,127,146,16,16,16 0 0200 quotesinglbase
+Fo 456,484,0,62,-61,62 0 0201 guillemotleft
+char171 "
+Fc 456,484,0,37,-35,37 0 0202 guillemotright
+char187 "
+bu 287,524,0,108,-18,90 0 0203 bullet
+Fn 456,737,210,142,91,90 3 0204 florin
+f/ 137,710,19,312,193,90 2 0205 fraction
+%0 820,710,19,81,-12,81 2 0206 perthousand
+dg 456,718,171,107,-47,90 2 0207 dagger
+dd 456,718,171,109,12,90 2 0210 daggerdbl
+en 456,333,0,108,10,90 0 0211 endash
+em 820,333,0,108,10,90 0 0212 emdash
+fi 501,727,0,120,-21,90 2 0214 fi
+fl 501,727,0,119,-21,90 2 0215 fl
+.i 228,532,0,86,-7,86 0 0220 dotlessi
+ga 273,750,0,67,-62,67 2 0222 grave
+a" 273,750,0,306,-63,90 2 0223 hungarumlaut
+a. 273,729,0,93,-142,90 2 0224 dotaccent
+ab 273,750,0,182,-78,90 2 0225 breve
+ah 273,750,0,189,-73,90 2 0226 caron
+ao 273,776,0,121,-114,90 2 0227 ring
+ho 273,0,228,0,17 1 0230 ogonek
+lq 410,727,0,122,-82,90 2 0231 quotedblleft
+rq 410,718,0,123,-82,90 2 0232 quotedblright
+oe 774,546,14,77,-17,77 0 0233 oe
+/l 228,718,0,156,17,90 2 0234 lslash
+Bq 410,127,146,20,21,20 0 0235 quotedblbase
+OE 820,737,19,143,-31,90 2 0236 OE
+/L 501,718,0,50,22,50 2 0237 Lslash
+r! 273,532,186,67,9,67 0 0241 exclamdown
+char161 "
+ct 456,628,118,85,-15,85 0 0242 cent
+char162 "
+Po 456,718,16,114,9,90 2 0243 sterling
+char163 "
+Cs 456,636,0,152,28,90 0 0244 currency
+char164 "
+Ye 456,698,0,179,1,90 2 0245 yen
+char165 "
+bb 230,737,19,109,-16,90 2 0246 brokenbar
+char166 "
+sc 456,727,184,85,0,85 2 0247 section
+char167 "
+ad 273,729,0,172,-62,90 2 0250 dieresis
+char168 "
+co 604,737,19,131,4,90 2 0251 copyright
+char169 "
+Of 303,737,0,128,-25,90 2 0252 ordfeminine
+char170 "
+fo 273,484,0,66,-56,66 0 0253 guilsinglleft
+no 479,419,0,90,-36,90 0 0254 logicalnot
+char172 "
+\- 479,309,0,71,-17,71 0 0255 minus
+rg 604,737,19,130,5,90 2 0256 registered
+char174 "
+a- 273,678,0,173,-50,90 2 0257 macron
+char175 "
+de 328,712,0,105,-93,90 2 0260 degree
+char176 "
+char177 479,506,0,83,17,83 0 0261 plusminus
+S2 273,710,0,145,-7,90 2 0262 twosuperior
+char178 "
+S3 273,710,0,138,-25,90 2 0263 threesuperior
+char179 "
+aa 273,750,0,200,-144,90 2 0264 acute
+char180 "
+char181 501,532,207,89,32,89 1 0265 mu
+ps 456,700,191,158,-30,90 2 0266 paragraph
+char182 "
+char183 228,334,0,48,-40,48 0 0267 periodcentered
+ac 273,0,228,0,80 1 0270 cedilla
+char184 "
+S1 273,710,0,95,-71,90 2 0271 onesuperior
+char185 "
+Om 299,737,0,149,-25,90 2 0272 ordmasculine
+char186 "
+fc 273,484,0,41,-31,41 0 0273 guilsinglright
+14 684,710,19,27,-58,27 2 0274 onequarter
+char188 "
+12 684,710,19,70,-58,70 2 0275 onehalf
+char189 "
+34 684,710,19,54,-32,54 2 0276 threequarters
+char190 "
+r? 501,532,195,8,6,8 0 0277 questiondown
+char191 "
+`A 592,936,0,34,34,34 2 0300 Agrave
+char192 "
+'A 592,936,0,73,34,73 2 0301 Aacute
+char193 "
+^A 592,936,0,37,34,37 2 0302 Acircumflex
+char194 "
+~A 592,923,0,66,34,66 2 0303 Atilde
+char195 "
+:A 592,915,0,46,34,46 2 0304 Adieresis
+char196 "
+oA 592,962,0,34,34,34 2 0305 Aring
+char197 "
+AE 820,718,0,132,46,90 2 0306 AE
+char198 "
+,C 592,737,228,105,-38,90 3 0307 Ccedilla
+char199 "
+`E 547,936,0,123,-12,90 2 0310 Egrave
+char200 "
+'E 547,936,0,123,-12,90 2 0311 Eacute
+char201 "
+^E 547,936,0,123,-12,90 2 0312 Ecircumflex
+char202 "
+:E 547,915,0,123,-12,90 2 0313 Edieresis
+char203 "
+`I 228,936,0,123,-2,90 2 0314 Igrave
+char204 "
+'I 228,936,0,255,-2,90 2 0315 Iacute
+char205 "
+^I 228,936,0,219,-2,90 2 0316 Icircumflex
+char206 "
+:I 228,915,0,227,-2,90 2 0317 Idieresis
+char207 "
+-D 592,718,0,95,-1,90 2 0320 Eth
+char208 "
+~N 592,923,0,119,-7,90 2 0321 Ntilde
+char209 "
+`O 638,936,19,87,-38,87 2 0322 Ograve
+char210 "
+'O 638,936,19,87,-38,87 2 0323 Oacute
+char211 "
+^O 638,936,19,87,-38,87 2 0324 Ocircumflex
+char212 "
+~O 638,923,19,87,-38,87 2 0325 Otilde
+char213 "
+:O 638,915,19,87,-38,87 2 0326 Odieresis
+char214 "
+char215 479,505,0,91,3,90 0 0327 multiply
+/O 638,745,27,145,21,90 2 0330 Oslash
+char216 "
+`U 592,936,19,117,-46,90 2 0331 Ugrave
+char217 "
+'U 592,936,19,117,-46,90 2 0332 Uacute
+char218 "
+^U 592,936,19,117,-46,90 2 0333 Ucircumflex
+char219 "
+:U 592,915,19,117,-46,90 2 0334 Udieresis
+char220 "
+'Y 547,936,0,164,-87,90 2 0335 Yacute
+char221 "
+TP 547,718,0,91,-12,90 2 0336 Thorn
+char222 "
+ss 501,731,14,88,-7,88 2 0337 germandbls
+char223 "
+`a 456,750,14,72,5,72 2 0340 agrave
+char224 "
+'a 456,750,14,108,5,90 2 0341 aacute
+char225 "
+^a 456,750,14,72,5,72 2 0342 acircumflex
+char226 "
+~a 456,737,14,101,5,90 2 0343 atilde
+char227 "
+:a 456,729,14,81,5,81 2 0344 adieresis
+char228 "
+oa 456,776,14,72,5,72 2 0345 aring
+char229 "
+ae 729,546,14,78,4,78 0 0346 ae
+char230 "
+,c 456,546,228,85,-15,85 1 0347 ccedilla
+char231 "
+`e 456,750,14,80,-8,80 2 0350 egrave
+char232 "
+'e 456,750,14,108,-8,90 2 0351 eacute
+char233 "
+^e 456,750,14,80,-8,80 2 0352 ecircumflex
+char234 "
+:e 456,729,14,81,-8,81 2 0353 edieresis
+char235 "
+`i 228,750,0,90,-7,90 2 0354 igrave
+char236 "
+'i 228,750,0,222,-7,90 2 0355 iacute
+char237 "
+^i 228,750,0,186,-7,90 2 0356 icircumflex
+char238 "
+:i 228,729,0,195,-7,90 2 0357 idieresis
+char239 "
+Sd 501,737,14,98,-17,90 2 0360 eth
+char240 "
+~n 501,737,0,78,-3,78 2 0361 ntilde
+char241 "
+`o 501,750,14,76,-17,76 2 0362 ograve
+char242 "
+'o 501,750,14,86,-17,86 2 0363 oacute
+char243 "
+^o 501,750,14,76,-17,76 2 0364 ocircumflex
+char244 "
+~o 501,737,14,78,-17,78 2 0365 otilde
+char245 "
+:o 501,729,14,76,-17,76 2 0366 odieresis
+char246 "
+char247 479,548,42,71,-17,71 0 0367 divide
+/o 501,560,29,124,32,90 0 0370 oslash
+char248 "
+`u 501,750,14,89,-30,89 2 0371 ugrave
+char249 "
+'u 501,750,14,89,-30,89 2 0372 uacute
+char250 "
+^u 501,750,14,89,-30,89 2 0373 ucircumflex
+char251 "
+:u 501,729,14,89,-30,89 2 0374 udieresis
+char252 "
+'y 456,750,214,129,16,90 3 0375 yacute
+char253 "
+Tp 501,718,208,78,35,78 3 0376 thorn
+char254 "
+:y 456,729,214,129,16,90 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/HNI b/gnu/usr.bin/groff/devices/devps/HNI
new file mode 100644
index 000000000000..e9ded2f04d1d
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HNI
@@ -0,0 +1,617 @@
+name HNI
+internalname Helvetica-Narrow-Oblique
+slant 12
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -40
+A w -40
+A v -40
+A u -30
+A Y -100
+A W -50
+A V -70
+A U -50
+A T -120
+A Q -30
+A O -30
+A G -30
+A C -30
+B . -20
+B , -20
+B U -10
+C . -30
+C , -30
+D . -70
+D , -70
+D Y -90
+D W -40
+D V -70
+D A -40
+F r -45
+F . -150
+F o -30
+F e -30
+F , -150
+F a -50
+F A -80
+J u -20
+J . -30
+J , -30
+J a -20
+J A -20
+K y -50
+K u -30
+K o -40
+K e -40
+K O -50
+L y -30
+L ' -160
+L rq -140
+L Y -140
+L W -70
+L V -110
+L T -110
+O . -40
+O , -40
+O Y -70
+O X -60
+O W -30
+O V -50
+O T -40
+O A -20
+P . -180
+P o -50
+P e -50
+P , -180
+P a -40
+P A -120
+Q U -10
+R Y -50
+R W -30
+R V -50
+R U -40
+R T -30
+R O -20
+S . -20
+S , -20
+T y -120
+T w -120
+T u -120
+T ; -20
+T r -120
+T . -120
+T o -120
+T - -140
+T hy -140
+T char173 -140
+T e -120
+T , -120
+T : -20
+T a -120
+T O -40
+T A -120
+U . -40
+U , -40
+U A -40
+V u -70
+V ; -40
+V . -125
+V o -80
+V - -80
+V hy -80
+V char173 -80
+V e -80
+V , -125
+V : -40
+V a -70
+V O -40
+V G -40
+V A -80
+W y -20
+W u -30
+W . -80
+W o -30
+W - -40
+W hy -40
+W char173 -40
+W e -30
+W , -80
+W a -40
+W O -20
+W A -50
+Y u -110
+Y ; -60
+Y . -140
+Y o -140
+Y i -20
+Y - -140
+Y hy -140
+Y char173 -140
+Y e -140
+Y , -140
+Y : -60
+Y a -140
+Y O -85
+Y A -110
+a y -30
+a w -20
+a v -20
+b y -20
+b v -20
+b u -20
+b . -40
+b l -20
+b , -40
+b b -10
+c k -20
+c , -15
+, ' -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f rq 60
+f . -30
+f o -30
+f e -30
+f .i -28
+f , -30
+f a -30
+g r -10
+h y -30
+k o -20
+k e -20
+m y -15
+m u -10
+n y -15
+n v -20
+n u -10
+o y -30
+o x -30
+o w -15
+o v -15
+o . -40
+o , -40
+/o z -55
+char248 z -55
+/o y -70
+char248 y -70
+/o x -85
+char248 x -85
+/o w -70
+char248 w -70
+/o v -70
+char248 v -70
+/o u -55
+char248 u -55
+/o t -55
+char248 t -55
+/o s -55
+char248 s -55
+/o r -55
+char248 r -55
+/o q -55
+char248 q -55
+/o . -95
+char248 . -95
+/o p -55
+char248 p -55
+/o o -55
+char248 o -55
+/o n -55
+char248 n -55
+/o m -55
+char248 m -55
+/o l -55
+char248 l -55
+/o k -55
+char248 k -55
+/o j -55
+char248 j -55
+/o i -55
+char248 i -55
+/o h -55
+char248 h -55
+/o g -55
+char248 g -55
+/o f -55
+char248 f -55
+/o e -55
+char248 e -55
+/o d -55
+char248 d -55
+/o , -95
+char248 , -95
+/o c -55
+char248 c -55
+/o b -55
+char248 b -55
+/o a -55
+char248 a -55
+p y -30
+p . -35
+p , -35
+. ' -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+' r -50
+' ' -57
+' d -50
+r y 30
+r v 30
+r u 15
+r t 40
+r ; 30
+r . -50
+r p 30
+r n 25
+r m 25
+r l 15
+r k 15
+r i 15
+r , -50
+r : 30
+r a -10
+s w -30
+s . -15
+s , -15
+v . -80
+v o -25
+v e -25
+v , -80
+v a -25
+w . -60
+w o -10
+w e -10
+w , -60
+w a -15
+x e -30
+y . -100
+y o -20
+y e -20
+y , -100
+y a -20
+z o -15
+z e -15
+charset
+ha 385,688,0,107,15,89 2 0000 asciicircum
+ti 479,326,0,47,-41,47 0 0001 asciitilde
+vS 547,929,19,87,-24,87 2 0002 Scaron
+vZ 501,929,0,156,31,89 2 0003 Zcaron
+vs 410,734,15,93,-2,89 2 0004 scaron
+vz 410,734,0,108,25,89 2 0005 zcaron
+:Y 547,901,0,164,-87,89 2 0006 Ydieresis
+tm 820,718,0,96,-102,89 2 0007 trademark
+aq 157,718,0,126,-79,89 2 0010 quotesingle
+space 228 0 0040
+! 228,718,0,100,-24,89 2 0041 exclam
+" 291,718,0,118,-88,89 2 0042 quotedbl
+# 456,688,0,111,-10,89 2 0043 numbersign
+sh "
+$ 456,775,115,100,-7,89 2 0044 dollar
+Do "
+% 729,703,19,50,-70,50 2 0045 percent
+& 547,718,15,33,-13,33 2 0046 ampersand
+' 182,718,0,122,-74,89 2 0047 quoteright
+( 273,733,207,149,-39,89 3 0050 parenleft
+) 273,733,207,53,57,53 3 0051 parenright
+* 319,718,0,120,-85,89 2 0052 asterisk
++ 479,505,0,68,-20,68 0 0053 plus
+, 228,106,147,0,4 0 0054 comma
+- 273,322,0,70,-27,70 0 0055 hyphen
+hy "
+char173 "
+. 228,106,0,0,-21 0 0056 period
+/ 228,737,19,192,67,89 2 0057 slash
+sl "
+0 456,703,19,93,-27,89 2 0060 zero
+1 456,703,0,11,-120,11 2 0061 one
+2 456,703,0,100,29,89 2 0062 two
+3 456,703,19,94,-11,89 2 0063 three
+4 456,703,0,66,0,66 2 0064 four
+5 456,688,19,103,-5,89 2 0065 five
+6 456,703,19,98,-24,89 2 0066 six
+7 456,688,0,143,-62,89 2 0067 seven
+8 456,703,19,91,-10,89 2 0070 eight
+9 456,703,19,93,-17,89 2 0071 nine
+: 228,516,0,69,-21,69 0 0072 colon
+; 228,516,147,69,4,69 0 0073 semicolon
+< 479,495,0,97,-27,89 0 0074 less
+= 479,390,0,86,-2,86 0 0075 equal
+> 479,495,0,61,9,61 0 0076 greater
+? 456,727,0,94,-82,89 2 0077 question
+@ 832,737,19,9,-126,9 2 0100 at
+at "
+A 547,718,0,39,39,39 2 0101 A
+B 547,718,0,86,-11,86 2 0102 B
+C 592,737,19,98,-38,89 2 0103 C
+D 592,718,0,84,-16,84 2 0104 D
+E 547,718,0,128,-21,89 2 0105 E
+F 501,718,0,152,-21,89 2 0106 F
+G 638,737,19,67,-41,67 2 0107 G
+H 592,718,0,113,-13,89 2 0110 H
+I 228,718,0,101,-25,89 2 0111 I
+J 410,718,19,116,11,89 2 0112 J
+K 547,718,0,165,-12,89 2 0113 K
+L 456,718,0,49,-12,49 2 0114 L
+M 683,718,0,116,-10,89 2 0115 M
+N 592,718,0,113,-12,89 2 0116 N
+O 638,737,19,89,-36,89 2 0117 O
+P 547,718,0,107,-21,89 2 0120 P
+Q 638,737,56,89,-36,89 2 0121 Q
+R 592,718,0,92,-22,89 2 0122 R
+S 547,737,19,87,-24,87 2 0123 S
+T 501,718,0,164,-72,89 2 0124 T
+U 592,718,19,111,-51,89 2 0125 U
+V 547,718,0,159,-92,89 2 0126 V
+W 774,718,0,162,-88,89 2 0127 W
+X 547,718,0,150,34,89 2 0130 X
+Y 547,718,0,164,-87,89 2 0131 Y
+Z 501,718,0,156,31,89 2 0132 Z
+[ 228,722,196,153,33,89 2 0133 bracketleft
+lB "
+\ 228,737,19,61,-65,61 2 0134 backslash
+rs "
+] 228,722,196,124,61,89 2 0135 bracketright
+rB "
+a^ 273,734,0,136,-71,89 2 0136 circumflex
+^ "
+_ 456,0,125,37,72,37 0 0137 underscore
+` 182,725,0,133,-85,89 2 0140 quoteleft
+oq "
+a 456,538,15,52,0,52 0 0141 a
+b 456,718,15,73,2,73 2 0142 b
+c 410,538,15,94,-11,89 0 0143 c
+d 456,718,15,128,-19,89 2 0144 d
+e 456,538,15,68,-19,68 0 0145 e
+f 228,728,0,163,-21,89 2 0146 f
+g 456,538,220,94,16,89 1 0147 g
+h 456,718,0,64,-3,64 2 0150 h
+i 182,718,0,120,-5,89 2 0151 i
+j 182,718,210,120,99,89 3 0152 j
+k 410,718,0,132,-5,89 2 0153 k
+l 182,718,0,120,-5,89 2 0154 l
+m 683,538,0,66,-3,66 0 0155 m
+n 456,538,0,64,-3,64 0 0156 n
+o 456,538,14,73,-18,73 0 0157 o
+p 456,538,207,73,39,73 1 0160 p
+q 456,538,207,90,-19,89 1 0161 q
+r 273,538,0,142,-13,89 0 0162 r
+s 410,538,15,74,-2,74 0 0163 s
+t 228,669,7,124,-34,89 2 0164 t
+u 456,523,15,86,-27,86 0 0165 u
+v 410,523,0,135,-48,89 0 0166 v
+w 592,523,0,131,-53,89 0 0167 w
+x 410,523,0,127,41,89 0 0170 x
+y 410,523,214,132,38,89 1 0171 y
+z 410,523,0,108,25,89 0 0172 z
+lC 274,722,196,141,-25,89 2 0173 braceleft
+{ "
+ba 213,737,19,102,-24,89 2 0174 bar
+| "
+rC 274,722,196,67,50,67 2 0175 braceright
+} "
+a~ 273,722,0,179,-52,89 2 0176 tilde
+~ "
+bq 182,106,149,15,33,15 0 0200 quotesinglbase
+Fo 456,446,0,48,-70,48 0 0201 guillemotleft
+char171 "
+Fc 456,446,0,27,-48,27 0 0202 guillemotright
+char187 "
+bu 287,517,0,102,-24,89 0 0203 bullet
+Fn 456,737,207,131,93,89 3 0204 florin
+f/ 137,703,19,309,189,89 2 0205 fraction
+%0 820,703,19,74,-22,74 2 0206 perthousand
+dg 456,718,159,104,-60,89 2 0207 dagger
+dd 456,718,159,105,7,89 2 0210 daggerdbl
+en 456,313,0,104,8,89 0 0211 endash
+em 820,313,0,105,8,89 0 0212 emdash
+fi 410,728,0,121,-21,89 2 0214 fi
+fl 410,728,0,119,-21,89 2 0215 fl
+.i 228,523,0,63,-28,63 0 0220 dotlessi
+ga 273,734,0,53,-89,53 2 0222 grave
+a" 273,734,0,240,-79,89 2 0223 hungarumlaut
+a. 273,706,0,74,-154,74 2 0224 dotaccent
+ab 273,731,0,168,-87,89 2 0225 breve
+ah 273,734,0,161,-95,89 2 0226 caron
+ao 273,756,0,107,-125,89 2 0227 ring
+ho 273,0,225,0,15 1 0230 ogonek
+lq 273,725,0,155,-63,89 2 0231 quotedblleft
+rq 273,718,0,144,-52,89 2 0232 quotedblright
+oe 774,538,15,67,-18,67 0 0233 oe
+/l 182,718,0,152,16,89 2 0234 lslash
+Bq 273,106,149,37,55,37 0 0235 quotedblbase
+OE 820,737,19,145,-30,89 2 0236 OE
+/L 456,718,0,49,16,49 2 0237 Lslash
+r! 273,523,195,44,-13,44 0 0241 exclamdown
+char161 "
+ct 456,623,115,73,-28,73 0 0242 cent
+char162 "
+Po 456,718,16,114,10,89 2 0243 sterling
+char163 "
+Cs 456,603,0,124,1,89 0 0244 currency
+char164 "
+Ye 456,688,0,167,-17,89 2 0245 yen
+char165 "
+bb 213,737,19,102,-24,89 2 0246 brokenbar
+char166 "
+sc 456,737,191,73,-13,73 2 0247 section
+char167 "
+ad 273,706,0,140,-88,89 2 0250 dieresis
+char168 "
+co 604,737,19,133,6,89 2 0251 copyright
+char169 "
+Of 303,737,0,115,-32,89 2 0252 ordfeminine
+char170 "
+fo 273,446,0,56,-62,56 0 0253 guilsinglleft
+no 479,390,0,86,-37,86 0 0254 logicalnot
+char172 "
+\- 479,289,0,68,-20,68 0 0255 minus
+rg 604,737,19,133,6,89 2 0256 registered
+char174 "
+a- 273,684,0,161,-67,89 2 0257 macron
+char175 "
+de 328,703,0,106,-88,89 2 0260 degree
+char176 "
+char177 479,506,0,78,18,78 0 0261 plusminus
+S2 273,703,0,145,-2,89 2 0262 twosuperior
+char178 "
+S3 273,703,0,135,-24,89 2 0263 threesuperior
+char179 "
+aa 273,734,0,167,-153,89 2 0264 acute
+char180 "
+char181 456,523,207,86,30,86 1 0265 mu
+ps 440,718,173,143,-53,89 2 0266 paragraph
+char182 "
+char183 228,315,0,33,-56,33 0 0267 periodcentered
+ac 273,0,225,0,48 1 0270 cedilla
+char184 "
+S1 273,703,0,82,-86,82 2 0271 onesuperior
+char185 "
+Om 299,737,0,135,-32,89 2 0272 ordmasculine
+char186 "
+fc 273,446,0,34,-41,34 0 0273 guilsinglright
+14 684,703,19,24,-73,24 2 0274 onequarter
+char188 "
+12 684,703,19,54,-43,54 2 0275 onehalf
+char189 "
+34 684,703,19,72,-56,72 2 0276 threequarters
+char190 "
+r? 501,525,201,0,-20 0 0277 questiondown
+char191 "
+`A 547,929,0,39,39,39 2 0300 Agrave
+char192 "
+'A 547,929,0,63,39,63 2 0301 Aacute
+char193 "
+^A 547,929,0,39,39,39 2 0302 Acircumflex
+char194 "
+~A 547,917,0,76,39,76 2 0303 Atilde
+char195 "
+:A 547,901,0,39,39,39 2 0304 Adieresis
+char196 "
+oA 547,931,0,39,39,39 2 0305 Aring
+char197 "
+AE 820,718,0,129,43,89 2 0306 AE
+char198 "
+,C 592,737,225,98,-38,89 3 0307 Ccedilla
+char199 "
+`E 547,929,0,128,-21,89 2 0310 Egrave
+char200 "
+'E 547,929,0,128,-21,89 2 0311 Eacute
+char201 "
+^E 547,929,0,128,-21,89 2 0312 Ecircumflex
+char202 "
+:E 547,901,0,128,-21,89 2 0313 Edieresis
+char203 "
+`I 228,929,0,110,-25,89 2 0314 Igrave
+char204 "
+'I 228,929,0,223,-25,89 2 0315 Iacute
+char205 "
+^I 228,929,0,193,-25,89 2 0316 Icircumflex
+char206 "
+:I 228,901,0,197,-25,89 2 0317 Idieresis
+char207 "
+-D 592,718,0,84,-7,84 2 0320 Eth
+char208 "
+~N 592,917,0,113,-12,89 2 0321 Ntilde
+char209 "
+`O 638,929,19,89,-36,89 2 0322 Ograve
+char210 "
+'O 638,929,19,89,-36,89 2 0323 Oacute
+char211 "
+^O 638,929,19,89,-36,89 2 0324 Ocircumflex
+char212 "
+~O 638,917,19,89,-36,89 2 0325 Otilde
+char213 "
+:O 638,901,19,89,-36,89 2 0326 Odieresis
+char214 "
+char215 479,506,0,97,9,89 0 0327 multiply
+/O 638,737,19,142,15,89 2 0330 Oslash
+char216 "
+`U 592,929,19,111,-51,89 2 0331 Ugrave
+char217 "
+'U 592,929,19,111,-51,89 2 0332 Uacute
+char218 "
+^U 592,929,19,111,-51,89 2 0333 Ucircumflex
+char219 "
+:U 592,901,19,111,-51,89 2 0334 Udieresis
+char220 "
+'Y 547,929,0,164,-87,89 2 0335 Yacute
+char221 "
+TP 547,718,0,87,-21,87 2 0336 Thorn
+char222 "
+ss 501,728,15,88,-5,88 2 0337 germandbls
+char223 "
+`a 456,734,15,52,0,52 2 0340 agrave
+char224 "
+'a 456,734,15,75,0,75 2 0341 aacute
+char225 "
+^a 456,734,15,52,0,52 2 0342 acircumflex
+char226 "
+~a 456,722,15,80,0,80 2 0343 atilde
+char227 "
+:a 456,706,15,52,0,52 2 0344 adieresis
+char228 "
+oa 456,756,15,52,0,52 2 0345 aring
+char229 "
+ae 729,538,15,67,0,67 0 0346 ae
+char230 "
+,c 410,538,225,94,-11,89 1 0347 ccedilla
+char231 "
+`e 456,734,15,68,-19,68 2 0350 egrave
+char232 "
+'e 456,734,15,75,-19,75 2 0351 eacute
+char233 "
+^e 456,734,15,68,-19,68 2 0352 ecircumflex
+char234 "
+:e 456,706,15,68,-19,68 2 0353 edieresis
+char235 "
+`i 228,734,0,76,-28,76 2 0354 igrave
+char236 "
+'i 228,734,0,189,-28,89 2 0355 iacute
+char237 "
+^i 228,734,0,159,-28,89 2 0356 icircumflex
+char238 "
+:i 228,706,0,163,-28,89 2 0357 idieresis
+char239 "
+Sd 456,737,15,100,-17,89 2 0360 eth
+char240 "
+~n 456,722,0,80,-3,80 2 0361 ntilde
+char241 "
+`o 456,734,14,73,-18,73 2 0362 ograve
+char242 "
+'o 456,734,14,75,-18,75 2 0363 oacute
+char243 "
+^o 456,734,14,73,-18,73 2 0364 ocircumflex
+char244 "
+~o 456,722,14,88,-18,88 2 0365 otilde
+char245 "
+:o 456,706,14,73,-18,73 2 0366 odieresis
+char246 "
+char247 479,524,19,68,-20,68 0 0367 divide
+/o 501,545,22,80,26,80 0 0370 oslash
+char248 "
+`u 456,734,15,86,-27,86 2 0371 ugrave
+char249 "
+'u 456,734,15,86,-27,86 2 0372 uacute
+char250 "
+^u 456,734,15,86,-27,86 2 0373 ucircumflex
+char251 "
+:u 456,706,15,86,-27,86 2 0374 udieresis
+char252 "
+'y 410,734,214,132,38,89 3 0375 yacute
+char253 "
+Tp 456,718,207,73,39,73 3 0376 thorn
+char254 "
+:y 410,706,214,132,38,89 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/HNR b/gnu/usr.bin/groff/devices/devps/HNR
new file mode 100644
index 000000000000..ecd911561f23
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HNR
@@ -0,0 +1,616 @@
+name HNR
+internalname Helvetica-Narrow
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -32
+A w -32
+A v -32
+A u -24
+A Y -81
+A W -40
+A V -56
+A U -40
+A T -97
+A Q -24
+A O -24
+A G -24
+A C -24
+B . -15
+B , -15
+B U -7
+C . -24
+C , -24
+D . -56
+D , -56
+D Y -73
+D W -32
+D V -56
+D A -32
+F r -36
+F . -122
+F o -24
+F e -24
+F , -122
+F a -40
+F A -65
+J u -15
+J . -24
+J , -24
+J a -15
+J A -15
+K y -40
+K u -24
+K o -32
+K e -32
+K O -40
+L y -24
+L ' -130
+L rq -114
+L Y -114
+L W -56
+L V -89
+L T -89
+O . -32
+O , -32
+O Y -56
+O X -48
+O W -24
+O V -40
+O T -32
+O A -15
+P . -147
+P o -40
+P e -40
+P , -147
+P a -32
+P A -97
+Q U -7
+R Y -40
+R W -24
+R V -40
+R U -32
+R T -24
+R O -15
+S . -15
+S , -15
+T y -97
+T w -97
+T u -97
+T ; -15
+T r -97
+T . -97
+T o -97
+T - -114
+T hy -114
+T char173 -114
+T e -97
+T , -97
+T : -15
+T a -97
+T O -32
+T A -97
+U . -32
+U , -32
+U A -32
+V u -56
+V ; -32
+V . -102
+V o -65
+V - -65
+V hy -65
+V char173 -65
+V e -65
+V , -102
+V : -32
+V a -56
+V O -32
+V G -32
+V A -65
+W y -15
+W u -24
+W . -65
+W o -24
+W - -32
+W hy -32
+W char173 -32
+W e -24
+W , -65
+W a -32
+W O -15
+W A -40
+Y u -89
+Y ; -48
+Y . -114
+Y o -114
+Y i -15
+Y - -114
+Y hy -114
+Y char173 -114
+Y e -114
+Y , -114
+Y : -48
+Y a -114
+Y O -69
+Y A -89
+a y -24
+a w -15
+a v -15
+b y -15
+b v -15
+b u -15
+b . -32
+b l -15
+b , -32
+b b -7
+c k -15
+c , -11
+, ' -81
+, rq -81
+e y -15
+e x -24
+e w -15
+e v -24
+e . -11
+e , -11
+f ' 41
+f rq 49
+f . -24
+f o -24
+f e -24
+f .i -22
+f , -24
+f a -24
+g r -7
+h y -24
+k o -15
+k e -15
+m y -11
+m u -7
+n y -11
+n v -15
+n u -7
+o y -24
+o x -24
+o w -11
+o v -11
+o . -32
+o , -32
+/o z -44
+char248 z -44
+/o y -56
+char248 y -56
+/o x -69
+char248 x -69
+/o w -56
+char248 w -56
+/o v -56
+char248 v -56
+/o u -44
+char248 u -44
+/o t -44
+char248 t -44
+/o s -44
+char248 s -44
+/o r -44
+char248 r -44
+/o q -44
+char248 q -44
+/o . -77
+char248 . -77
+/o p -44
+char248 p -44
+/o o -44
+char248 o -44
+/o n -44
+char248 n -44
+/o m -44
+char248 m -44
+/o l -44
+char248 l -44
+/o k -44
+char248 k -44
+/o j -44
+char248 j -44
+/o i -44
+char248 i -44
+/o h -44
+char248 h -44
+/o g -44
+char248 g -44
+/o f -44
+char248 f -44
+/o e -44
+char248 e -44
+/o d -44
+char248 d -44
+/o , -77
+char248 , -77
+/o c -44
+char248 c -44
+/o b -44
+char248 b -44
+/o a -44
+char248 a -44
+p y -24
+p . -28
+p , -28
+. ' -81
+. rq -81
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' s -40
+' r -40
+' ' -46
+' d -40
+r y 25
+r v 25
+r u 12
+r t 33
+r ; 25
+r . -40
+r p 25
+r n 21
+r m 21
+r l 12
+r k 12
+r i 12
+r , -40
+r : 25
+r a -7
+s w -24
+s . -11
+s , -11
+v . -65
+v o -20
+v e -20
+v , -65
+v a -20
+w . -48
+w o -7
+w e -7
+w , -48
+w a -11
+x e -24
+y . -81
+y o -15
+y e -15
+y , -81
+y a -15
+z o -11
+z e -11
+charset
+ha 385,688 2 0000 asciicircum
+ti 479,326 0 0001 asciitilde
+vS 547,929,19 2 0002 Scaron
+vZ 501,929 2 0003 Zcaron
+vs 410,734,15 2 0004 scaron
+vz 410,734 2 0005 zcaron
+:Y 547,901 2 0006 Ydieresis
+tm 820,718 2 0007 trademark
+aq 157,718 2 0010 quotesingle
+space 228 0 0040
+! 228,718 2 0041 exclam
+" 291,718 2 0042 quotedbl
+# 456,688 2 0043 numbersign
+sh "
+$ 456,775,115 2 0044 dollar
+Do "
+% 729,703,19 2 0045 percent
+& 547,718,15 2 0046 ampersand
+' 182,718 2 0047 quoteright
+( 273,733,207 3 0050 parenleft
+) 273,733,207 3 0051 parenright
+* 319,718 2 0052 asterisk
++ 479,505 0 0053 plus
+, 228,106,147 0 0054 comma
+- 273,322 0 0055 hyphen
+hy "
+char173 "
+. 228,106 0 0056 period
+/ 228,737,19 2 0057 slash
+sl "
+0 456,703,19 2 0060 zero
+1 456,703 2 0061 one
+2 456,703 2 0062 two
+3 456,703,19 2 0063 three
+4 456,703 2 0064 four
+5 456,688,19 2 0065 five
+6 456,703,19 2 0066 six
+7 456,688 2 0067 seven
+8 456,703,19 2 0070 eight
+9 456,703,19 2 0071 nine
+: 228,516 0 0072 colon
+; 228,516,147 0 0073 semicolon
+< 479,495 0 0074 less
+= 479,390 0 0075 equal
+> 479,495 0 0076 greater
+? 456,727 2 0077 question
+@ 832,737,19 2 0100 at
+at "
+A 547,718 2 0101 A
+B 547,718 2 0102 B
+C 592,737,19 2 0103 C
+D 592,718 2 0104 D
+E 547,718 2 0105 E
+F 501,718 2 0106 F
+G 638,737,19 2 0107 G
+H 592,718 2 0110 H
+I 228,718 2 0111 I
+J 410,718,19 2 0112 J
+K 547,718 2 0113 K
+L 456,718 2 0114 L
+M 683,718 2 0115 M
+N 592,718 2 0116 N
+O 638,737,19 2 0117 O
+P 547,718 2 0120 P
+Q 638,737,56 2 0121 Q
+R 592,718 2 0122 R
+S 547,737,19 2 0123 S
+T 501,718 2 0124 T
+U 592,718,19 2 0125 U
+V 547,718 2 0126 V
+W 774,718 2 0127 W
+X 547,718 2 0130 X
+Y 547,718 2 0131 Y
+Z 501,718 2 0132 Z
+[ 228,722,196 2 0133 bracketleft
+lB "
+\ 228,737,19 2 0134 backslash
+rs "
+] 228,722,196 2 0135 bracketright
+rB "
+a^ 273,734 2 0136 circumflex
+^ "
+_ 456,0,125 0 0137 underscore
+` 182,725 2 0140 quoteleft
+oq "
+a 456,538,15 0 0141 a
+b 456,718,15 2 0142 b
+c 410,538,15 0 0143 c
+d 456,718,15 2 0144 d
+e 456,538,15 0 0145 e
+f 228,728 2 0146 f
+g 456,538,220 1 0147 g
+h 456,718 2 0150 h
+i 182,718 2 0151 i
+j 182,718,210 3 0152 j
+k 410,718 2 0153 k
+l 182,718 2 0154 l
+m 683,538 0 0155 m
+n 456,538 0 0156 n
+o 456,538,14 0 0157 o
+p 456,538,207 1 0160 p
+q 456,538,207 1 0161 q
+r 273,538 0 0162 r
+s 410,538,15 0 0163 s
+t 228,669,7 2 0164 t
+u 456,523,15 0 0165 u
+v 410,523 0 0166 v
+w 592,523 0 0167 w
+x 410,523 0 0170 x
+y 410,523,214 1 0171 y
+z 410,523 0 0172 z
+lC 274,722,196 2 0173 braceleft
+{ "
+ba 213,737,19 2 0174 bar
+| "
+rC 274,722,196 2 0175 braceright
+} "
+a~ 273,722 2 0176 tilde
+~ "
+bq 182,106,149 0 0200 quotesinglbase
+Fo 456,446 0 0201 guillemotleft
+char171 "
+Fc 456,446 0 0202 guillemotright
+char187 "
+bu 287,517 0 0203 bullet
+Fn 456,737,207 3 0204 florin
+f/ 137,703,19 2 0205 fraction
+%0 820,703,19 2 0206 perthousand
+dg 456,718,159 2 0207 dagger
+dd 456,718,159 2 0210 daggerdbl
+en 456,313 0 0211 endash
+em 820,313 0 0212 emdash
+fi 410,728 2 0214 fi
+fl 410,728 2 0215 fl
+.i 228,523 0 0220 dotlessi
+ga 273,734 2 0222 grave
+a" 273,734 2 0223 hungarumlaut
+a. 273,706 2 0224 dotaccent
+ab 273,731 2 0225 breve
+ah 273,734 2 0226 caron
+ao 273,756 2 0227 ring
+ho 273,0,225 1 0230 ogonek
+lq 273,725 2 0231 quotedblleft
+rq 273,718 2 0232 quotedblright
+oe 774,538,15 0 0233 oe
+/l 182,718 2 0234 lslash
+Bq 273,106,149 0 0235 quotedblbase
+OE 820,737,19 2 0236 OE
+/L 456,718 2 0237 Lslash
+r! 273,523,195 0 0241 exclamdown
+char161 "
+ct 456,623,115 0 0242 cent
+char162 "
+Po 456,718,16 2 0243 sterling
+char163 "
+Cs 456,603 0 0244 currency
+char164 "
+Ye 456,688 2 0245 yen
+char165 "
+bb 213,737,19 2 0246 brokenbar
+char166 "
+sc 456,737,191 2 0247 section
+char167 "
+ad 273,706 2 0250 dieresis
+char168 "
+co 604,737,19 2 0251 copyright
+char169 "
+Of 303,737 2 0252 ordfeminine
+char170 "
+fo 273,446 0 0253 guilsinglleft
+no 479,390 0 0254 logicalnot
+char172 "
+\- 479,289 0 0255 minus
+rg 604,737,19 2 0256 registered
+char174 "
+a- 273,684 2 0257 macron
+char175 "
+de 328,703 2 0260 degree
+char176 "
+char177 479,506 0 0261 plusminus
+S2 273,703 2 0262 twosuperior
+char178 "
+S3 273,703 2 0263 threesuperior
+char179 "
+aa 273,734 2 0264 acute
+char180 "
+char181 456,523,207 1 0265 mu
+ps 440,718,173 2 0266 paragraph
+char182 "
+char183 228,315 0 0267 periodcentered
+ac 273,0,225 1 0270 cedilla
+char184 "
+S1 273,703 2 0271 onesuperior
+char185 "
+Om 299,737 2 0272 ordmasculine
+char186 "
+fc 273,446 0 0273 guilsinglright
+14 684,703,19 2 0274 onequarter
+char188 "
+12 684,703,19 2 0275 onehalf
+char189 "
+34 684,703,19 2 0276 threequarters
+char190 "
+r? 501,525,201 0 0277 questiondown
+char191 "
+`A 547,929 2 0300 Agrave
+char192 "
+'A 547,929 2 0301 Aacute
+char193 "
+^A 547,929 2 0302 Acircumflex
+char194 "
+~A 547,917 2 0303 Atilde
+char195 "
+:A 547,901 2 0304 Adieresis
+char196 "
+oA 547,931 2 0305 Aring
+char197 "
+AE 820,718 2 0306 AE
+char198 "
+,C 592,737,225 3 0307 Ccedilla
+char199 "
+`E 547,929 2 0310 Egrave
+char200 "
+'E 547,929 2 0311 Eacute
+char201 "
+^E 547,929 2 0312 Ecircumflex
+char202 "
+:E 547,901 2 0313 Edieresis
+char203 "
+`I 228,929 2 0314 Igrave
+char204 "
+'I 228,929 2 0315 Iacute
+char205 "
+^I 228,929 2 0316 Icircumflex
+char206 "
+:I 228,901 2 0317 Idieresis
+char207 "
+-D 592,718 2 0320 Eth
+char208 "
+~N 592,917 2 0321 Ntilde
+char209 "
+`O 638,929,19 2 0322 Ograve
+char210 "
+'O 638,929,19 2 0323 Oacute
+char211 "
+^O 638,929,19 2 0324 Ocircumflex
+char212 "
+~O 638,917,19 2 0325 Otilde
+char213 "
+:O 638,901,19 2 0326 Odieresis
+char214 "
+char215 479,506 0 0327 multiply
+/O 638,737,19 2 0330 Oslash
+char216 "
+`U 592,929,19 2 0331 Ugrave
+char217 "
+'U 592,929,19 2 0332 Uacute
+char218 "
+^U 592,929,19 2 0333 Ucircumflex
+char219 "
+:U 592,901,19 2 0334 Udieresis
+char220 "
+'Y 547,929 2 0335 Yacute
+char221 "
+TP 547,718 2 0336 Thorn
+char222 "
+ss 501,728,15 2 0337 germandbls
+char223 "
+`a 456,734,15 2 0340 agrave
+char224 "
+'a 456,734,15 2 0341 aacute
+char225 "
+^a 456,734,15 2 0342 acircumflex
+char226 "
+~a 456,722,15 2 0343 atilde
+char227 "
+:a 456,706,15 2 0344 adieresis
+char228 "
+oa 456,756,15 2 0345 aring
+char229 "
+ae 729,538,15 0 0346 ae
+char230 "
+,c 410,538,225 1 0347 ccedilla
+char231 "
+`e 456,734,15 2 0350 egrave
+char232 "
+'e 456,734,15 2 0351 eacute
+char233 "
+^e 456,734,15 2 0352 ecircumflex
+char234 "
+:e 456,706,15 2 0353 edieresis
+char235 "
+`i 228,734 2 0354 igrave
+char236 "
+'i 228,734 2 0355 iacute
+char237 "
+^i 228,734 2 0356 icircumflex
+char238 "
+:i 228,706 2 0357 idieresis
+char239 "
+Sd 456,737,15 2 0360 eth
+char240 "
+~n 456,722 2 0361 ntilde
+char241 "
+`o 456,734,14 2 0362 ograve
+char242 "
+'o 456,734,14 2 0363 oacute
+char243 "
+^o 456,734,14 2 0364 ocircumflex
+char244 "
+~o 456,722,14 2 0365 otilde
+char245 "
+:o 456,706,14 2 0366 odieresis
+char246 "
+char247 479,524,19 0 0367 divide
+/o 501,545,22 0 0370 oslash
+char248 "
+`u 456,734,15 2 0371 ugrave
+char249 "
+'u 456,734,15 2 0372 uacute
+char250 "
+^u 456,734,15 2 0373 ucircumflex
+char251 "
+:u 456,706,15 2 0374 udieresis
+char252 "
+'y 410,734,214 3 0375 yacute
+char253 "
+Tp 456,718,207 3 0376 thorn
+char254 "
+:y 410,706,214 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/HR b/gnu/usr.bin/groff/devices/devps/HR
new file mode 100644
index 000000000000..9dd2687e390e
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/HR
@@ -0,0 +1,616 @@
+name HR
+internalname Helvetica
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -40
+A w -40
+A v -40
+A u -30
+A Y -100
+A W -50
+A V -70
+A U -50
+A T -120
+A Q -30
+A O -30
+A G -30
+A C -30
+B . -20
+B , -20
+B U -10
+C . -30
+C , -30
+D . -70
+D , -70
+D Y -90
+D W -40
+D V -70
+D A -40
+F r -45
+F . -150
+F o -30
+F e -30
+F , -150
+F a -50
+F A -80
+J u -20
+J . -30
+J , -30
+J a -20
+J A -20
+K y -50
+K u -30
+K o -40
+K e -40
+K O -50
+L y -30
+L ' -160
+L rq -140
+L Y -140
+L W -70
+L V -110
+L T -110
+O . -40
+O , -40
+O Y -70
+O X -60
+O W -30
+O V -50
+O T -40
+O A -20
+P . -180
+P o -50
+P e -50
+P , -180
+P a -40
+P A -120
+Q U -10
+R Y -50
+R W -30
+R V -50
+R U -40
+R T -30
+R O -20
+S . -20
+S , -20
+T y -120
+T w -120
+T u -120
+T ; -20
+T r -120
+T . -120
+T o -120
+T - -140
+T hy -140
+T char173 -140
+T e -120
+T , -120
+T : -20
+T a -120
+T O -40
+T A -120
+U . -40
+U , -40
+U A -40
+V u -70
+V ; -40
+V . -125
+V o -80
+V - -80
+V hy -80
+V char173 -80
+V e -80
+V , -125
+V : -40
+V a -70
+V O -40
+V G -40
+V A -80
+W y -20
+W u -30
+W . -80
+W o -30
+W - -40
+W hy -40
+W char173 -40
+W e -30
+W , -80
+W a -40
+W O -20
+W A -50
+Y u -110
+Y ; -60
+Y . -140
+Y o -140
+Y i -20
+Y - -140
+Y hy -140
+Y char173 -140
+Y e -140
+Y , -140
+Y : -60
+Y a -140
+Y O -85
+Y A -110
+a y -30
+a w -20
+a v -20
+b y -20
+b v -20
+b u -20
+b . -40
+b l -20
+b , -40
+b b -10
+c k -20
+c , -15
+, ' -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f rq 60
+f . -30
+f o -30
+f e -30
+f .i -28
+f , -30
+f a -30
+g r -10
+h y -30
+k o -20
+k e -20
+m y -15
+m u -10
+n y -15
+n v -20
+n u -10
+o y -30
+o x -30
+o w -15
+o v -15
+o . -40
+o , -40
+/o z -55
+char248 z -55
+/o y -70
+char248 y -70
+/o x -85
+char248 x -85
+/o w -70
+char248 w -70
+/o v -70
+char248 v -70
+/o u -55
+char248 u -55
+/o t -55
+char248 t -55
+/o s -55
+char248 s -55
+/o r -55
+char248 r -55
+/o q -55
+char248 q -55
+/o . -95
+char248 . -95
+/o p -55
+char248 p -55
+/o o -55
+char248 o -55
+/o n -55
+char248 n -55
+/o m -55
+char248 m -55
+/o l -55
+char248 l -55
+/o k -55
+char248 k -55
+/o j -55
+char248 j -55
+/o i -55
+char248 i -55
+/o h -55
+char248 h -55
+/o g -55
+char248 g -55
+/o f -55
+char248 f -55
+/o e -55
+char248 e -55
+/o d -55
+char248 d -55
+/o , -95
+char248 , -95
+/o c -55
+char248 c -55
+/o b -55
+char248 b -55
+/o a -55
+char248 a -55
+p y -30
+p . -35
+p , -35
+. ' -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+' r -50
+' ' -57
+' d -50
+r y 30
+r v 30
+r u 15
+r t 40
+r ; 30
+r . -50
+r p 30
+r n 25
+r m 25
+r l 15
+r k 15
+r i 15
+r , -50
+r : 30
+r a -10
+s w -30
+s . -15
+s , -15
+v . -80
+v o -25
+v e -25
+v , -80
+v a -25
+w . -60
+w o -10
+w e -10
+w , -60
+w a -15
+x e -30
+y . -100
+y o -20
+y e -20
+y , -100
+y a -20
+z o -15
+z e -15
+charset
+ha 469,688 2 0000 asciicircum
+ti 584,326 0 0001 asciitilde
+vS 667,929,19 2 0002 Scaron
+vZ 611,929 2 0003 Zcaron
+vs 500,734,15 2 0004 scaron
+vz 500,734 2 0005 zcaron
+:Y 667,901 2 0006 Ydieresis
+tm 1000,718 2 0007 trademark
+aq 191,718 2 0010 quotesingle
+space 278 0 0040
+! 278,718 2 0041 exclam
+" 355,718 2 0042 quotedbl
+# 556,688 2 0043 numbersign
+sh "
+$ 556,775,115 2 0044 dollar
+Do "
+% 889,703,19 2 0045 percent
+& 667,718,15 2 0046 ampersand
+' 222,718 2 0047 quoteright
+( 333,733,207 3 0050 parenleft
+) 333,733,207 3 0051 parenright
+* 389,718 2 0052 asterisk
++ 584,505 0 0053 plus
+, 278,106,147 0 0054 comma
+- 333,322 0 0055 hyphen
+hy "
+char173 "
+. 278,106 0 0056 period
+/ 278,737,19 2 0057 slash
+sl "
+0 556,703,19 2 0060 zero
+1 556,703 2 0061 one
+2 556,703 2 0062 two
+3 556,703,19 2 0063 three
+4 556,703 2 0064 four
+5 556,688,19 2 0065 five
+6 556,703,19 2 0066 six
+7 556,688 2 0067 seven
+8 556,703,19 2 0070 eight
+9 556,703,19 2 0071 nine
+: 278,516 0 0072 colon
+; 278,516,147 0 0073 semicolon
+< 584,495 0 0074 less
+= 584,390 0 0075 equal
+> 584,495 0 0076 greater
+? 556,727 2 0077 question
+@ 1015,737,19 2 0100 at
+at "
+A 667,718 2 0101 A
+B 667,718 2 0102 B
+C 722,737,19 2 0103 C
+D 722,718 2 0104 D
+E 667,718 2 0105 E
+F 611,718 2 0106 F
+G 778,737,19 2 0107 G
+H 722,718 2 0110 H
+I 278,718 2 0111 I
+J 500,718,19 2 0112 J
+K 667,718 2 0113 K
+L 556,718 2 0114 L
+M 833,718 2 0115 M
+N 722,718 2 0116 N
+O 778,737,19 2 0117 O
+P 667,718 2 0120 P
+Q 778,737,56 2 0121 Q
+R 722,718 2 0122 R
+S 667,737,19 2 0123 S
+T 611,718 2 0124 T
+U 722,718,19 2 0125 U
+V 667,718 2 0126 V
+W 944,718 2 0127 W
+X 667,718 2 0130 X
+Y 667,718 2 0131 Y
+Z 611,718 2 0132 Z
+[ 278,722,196 2 0133 bracketleft
+lB "
+\ 278,737,19 2 0134 backslash
+rs "
+] 278,722,196 2 0135 bracketright
+rB "
+a^ 333,734 2 0136 circumflex
+^ "
+_ 556,0,125 0 0137 underscore
+` 222,725 2 0140 quoteleft
+oq "
+a 556,538,15 0 0141 a
+b 556,718,15 2 0142 b
+c 500,538,15 0 0143 c
+d 556,718,15 2 0144 d
+e 556,538,15 0 0145 e
+f 278,728 2 0146 f
+g 556,538,220 1 0147 g
+h 556,718 2 0150 h
+i 222,718 2 0151 i
+j 222,718,210 3 0152 j
+k 500,718 2 0153 k
+l 222,718 2 0154 l
+m 833,538 0 0155 m
+n 556,538 0 0156 n
+o 556,538,14 0 0157 o
+p 556,538,207 1 0160 p
+q 556,538,207 1 0161 q
+r 333,538 0 0162 r
+s 500,538,15 0 0163 s
+t 278,669,7 2 0164 t
+u 556,523,15 0 0165 u
+v 500,523 0 0166 v
+w 722,523 0 0167 w
+x 500,523 0 0170 x
+y 500,523,214 1 0171 y
+z 500,523 0 0172 z
+lC 334,722,196 2 0173 braceleft
+{ "
+ba 260,737,19 2 0174 bar
+| "
+rC 334,722,196 2 0175 braceright
+} "
+a~ 333,722 2 0176 tilde
+~ "
+bq 222,106,149 0 0200 quotesinglbase
+Fo 556,446 0 0201 guillemotleft
+char171 "
+Fc 556,446 0 0202 guillemotright
+char187 "
+bu 350,517 0 0203 bullet
+Fn 556,737,207 3 0204 florin
+f/ 167,703,19 2 0205 fraction
+%0 1000,703,19 2 0206 perthousand
+dg 556,718,159 2 0207 dagger
+dd 556,718,159 2 0210 daggerdbl
+en 556,313 0 0211 endash
+em 1000,313 0 0212 emdash
+fi 500,728 2 0214 fi
+fl 500,728 2 0215 fl
+.i 278,523 0 0220 dotlessi
+ga 333,734 2 0222 grave
+a" 333,734 2 0223 hungarumlaut
+a. 333,706 2 0224 dotaccent
+ab 333,731 2 0225 breve
+ah 333,734 2 0226 caron
+ao 333,756 2 0227 ring
+ho 333,0,225 1 0230 ogonek
+lq 333,725 2 0231 quotedblleft
+rq 333,718 2 0232 quotedblright
+oe 944,538,15 0 0233 oe
+/l 222,718 2 0234 lslash
+Bq 333,106,149 0 0235 quotedblbase
+OE 1000,737,19 2 0236 OE
+/L 556,718 2 0237 Lslash
+r! 333,523,195 0 0241 exclamdown
+char161 "
+ct 556,623,115 0 0242 cent
+char162 "
+Po 556,718,16 2 0243 sterling
+char163 "
+Cs 556,603 0 0244 currency
+char164 "
+Ye 556,688 2 0245 yen
+char165 "
+bb 260,737,19 2 0246 brokenbar
+char166 "
+sc 556,737,191 2 0247 section
+char167 "
+ad 333,706 2 0250 dieresis
+char168 "
+co 737,737,19 2 0251 copyright
+char169 "
+Of 370,737 2 0252 ordfeminine
+char170 "
+fo 333,446 0 0253 guilsinglleft
+no 584,390 0 0254 logicalnot
+char172 "
+\- 584,289 0 0255 minus
+rg 737,737,19 2 0256 registered
+char174 "
+a- 333,684 2 0257 macron
+char175 "
+de 400,703 2 0260 degree
+char176 "
+char177 584,506 0 0261 plusminus
+S2 333,703 2 0262 twosuperior
+char178 "
+S3 333,703 2 0263 threesuperior
+char179 "
+aa 333,734 2 0264 acute
+char180 "
+char181 556,523,207 1 0265 mu
+ps 537,718,173 2 0266 paragraph
+char182 "
+char183 278,315 0 0267 periodcentered
+ac 333,0,225 1 0270 cedilla
+char184 "
+S1 333,703 2 0271 onesuperior
+char185 "
+Om 365,737 2 0272 ordmasculine
+char186 "
+fc 333,446 0 0273 guilsinglright
+14 834,703,19 2 0274 onequarter
+char188 "
+12 834,703,19 2 0275 onehalf
+char189 "
+34 834,703,19 2 0276 threequarters
+char190 "
+r? 611,525,201 0 0277 questiondown
+char191 "
+`A 667,929 2 0300 Agrave
+char192 "
+'A 667,929 2 0301 Aacute
+char193 "
+^A 667,929 2 0302 Acircumflex
+char194 "
+~A 667,917 2 0303 Atilde
+char195 "
+:A 667,901 2 0304 Adieresis
+char196 "
+oA 667,931 2 0305 Aring
+char197 "
+AE 1000,718 2 0306 AE
+char198 "
+,C 722,737,225 3 0307 Ccedilla
+char199 "
+`E 667,929 2 0310 Egrave
+char200 "
+'E 667,929 2 0311 Eacute
+char201 "
+^E 667,929 2 0312 Ecircumflex
+char202 "
+:E 667,901 2 0313 Edieresis
+char203 "
+`I 278,929 2 0314 Igrave
+char204 "
+'I 278,929 2 0315 Iacute
+char205 "
+^I 278,929 2 0316 Icircumflex
+char206 "
+:I 278,901 2 0317 Idieresis
+char207 "
+-D 722,718 2 0320 Eth
+char208 "
+~N 722,917 2 0321 Ntilde
+char209 "
+`O 778,929,19 2 0322 Ograve
+char210 "
+'O 778,929,19 2 0323 Oacute
+char211 "
+^O 778,929,19 2 0324 Ocircumflex
+char212 "
+~O 778,917,19 2 0325 Otilde
+char213 "
+:O 778,901,19 2 0326 Odieresis
+char214 "
+char215 584,506 0 0327 multiply
+/O 778,737,19 2 0330 Oslash
+char216 "
+`U 722,929,19 2 0331 Ugrave
+char217 "
+'U 722,929,19 2 0332 Uacute
+char218 "
+^U 722,929,19 2 0333 Ucircumflex
+char219 "
+:U 722,901,19 2 0334 Udieresis
+char220 "
+'Y 667,929 2 0335 Yacute
+char221 "
+TP 667,718 2 0336 Thorn
+char222 "
+ss 611,728,15 2 0337 germandbls
+char223 "
+`a 556,734,15 2 0340 agrave
+char224 "
+'a 556,734,15 2 0341 aacute
+char225 "
+^a 556,734,15 2 0342 acircumflex
+char226 "
+~a 556,722,15 2 0343 atilde
+char227 "
+:a 556,706,15 2 0344 adieresis
+char228 "
+oa 556,756,15 2 0345 aring
+char229 "
+ae 889,538,15 0 0346 ae
+char230 "
+,c 500,538,225 1 0347 ccedilla
+char231 "
+`e 556,734,15 2 0350 egrave
+char232 "
+'e 556,734,15 2 0351 eacute
+char233 "
+^e 556,734,15 2 0352 ecircumflex
+char234 "
+:e 556,706,15 2 0353 edieresis
+char235 "
+`i 278,734 2 0354 igrave
+char236 "
+'i 278,734 2 0355 iacute
+char237 "
+^i 278,734 2 0356 icircumflex
+char238 "
+:i 278,706 2 0357 idieresis
+char239 "
+Sd 556,737,15 2 0360 eth
+char240 "
+~n 556,722 2 0361 ntilde
+char241 "
+`o 556,734,14 2 0362 ograve
+char242 "
+'o 556,734,14 2 0363 oacute
+char243 "
+^o 556,734,14 2 0364 ocircumflex
+char244 "
+~o 556,722,14 2 0365 otilde
+char245 "
+:o 556,706,14 2 0366 odieresis
+char246 "
+char247 584,524,19 0 0367 divide
+/o 611,545,22 0 0370 oslash
+char248 "
+`u 556,734,15 2 0371 ugrave
+char249 "
+'u 556,734,15 2 0372 uacute
+char250 "
+^u 556,734,15 2 0373 ucircumflex
+char251 "
+:u 556,706,15 2 0374 udieresis
+char252 "
+'y 500,734,214 3 0375 yacute
+char253 "
+Tp 556,718,207 3 0376 thorn
+char254 "
+:y 500,706,214 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/Makefile b/gnu/usr.bin/groff/devices/devps/Makefile
new file mode 100644
index 000000000000..7e47f06bb8c0
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/Makefile
@@ -0,0 +1,15 @@
+DEVICE= ps
+FONTFILES= $(FONTS) $(SUPPORT) $(DEVGENFILES) DESC
+FONTS= 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
+SUPPORT= download prologue symbolsl.pfa text.enc zapfdr.pfa
+DEVGENFILES= generate/Makefile generate/afmname generate/dingbatsmap \
+ generate/dingbatsrmap generate/lgreekmap generate/symbol.sed \
+ generate/symbolchars generate/symbolsl.afm generate/textmap
+
+NOOBJ= noobj
+
+clean cleandir:
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/devices/devps/NB b/gnu/usr.bin/groff/devices/devps/NB
new file mode 100644
index 000000000000..2805367abeeb
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/NB
@@ -0,0 +1,446 @@
+name NB
+internalname NewCenturySchlbk-Bold
+spacewidth 287
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -74
+A ' -74
+A Y -92
+A W -74
+A V -92
+A T -55
+F . -111
+F , -111
+F A -74
+L y -55
+L ' -55
+L Y -92
+L W -74
+L V -92
+L T -55
+P . -129
+P , -129
+P A -74
+R y -18
+R Y -37
+R W -37
+R V -37
+T y -52
+T w -71
+T u -71
+T ; -55
+T s -62
+T r -62
+T . -92
+T o -92
+T i -25
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -92
+T : -55
+T c -81
+T a -62
+T A -55
+V y -92
+V u -74
+V ; -74
+V r -74
+V . -129
+V o -92
+V i -44
+V - -92
+V hy -92
+V char173 -92
+V e -92
+V : -74
+V a -92
+V A -92
+W y -74
+W u -55
+W ; -37
+W r -55
+W . -111
+W o -55
+W i -37
+W - -37
+W hy -37
+W char173 -37
+W e -55
+W , -111
+W : -37
+W a -74
+W A -74
+Y v -81
+Y u -92
+Y ; -92
+Y q -111
+Y . -111
+Y p -81
+Y o -111
+Y i -44
+Y - -111
+Y hy -111
+Y char173 -111
+Y e -111
+Y , -111
+Y : -92
+Y a -111
+Y A -92
+f ' 94
+1 1 -55
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -18
+' s -37
+' ' -18
+r ' 55
+r . -74
+r - -18
+r hy -18
+r char173 -18
+r , -74
+v . -111
+v , -111
+w . -92
+w , -92
+y . -111
+y , -111
+charset
+ha 606,722 2 0000 asciicircum
+ti 606,347 0 0001 asciitilde
+vS 667,970,15 2 0002 Scaron
+vZ 667,970 2 0003 Zcaron
+vs 500,723,15 2 0004 scaron
+vz 537,723 2 0005 zcaron
+:Y 722,940 2 0006 Ydieresis
+tm 1000,722 2 0007 trademark
+aq 241,737 2 0010 quotesingle
+space 287 0 0040
+! 296,737,15 2 0041 exclam
+" 333,737 2 0042 quotedbl
+# 574,705 2 0043 numbersign
+sh "
+$ 574,801,140 2 0044 dollar
+Do "
+% 833,704,18 2 0045 percent
+& 852,737,15 2 0046 ampersand
+' 241,737 2 0047 quoteright
+( 389,737,122 2 0050 parenleft
+) 389,737,122 2 0051 parenright
+* 500,738 2 0052 asterisk
++ 606,514 0 0053 plus
+, 278,169,189 0 0054 comma
+- 333,309 0 0055 hyphen
+hy "
+char173 "
+. 278,172,15 0 0056 period
+/ 278,737,15 2 0057 slash
+sl "
+0 574,705,15 2 0060 zero
+1 574,705 2 0061 one
+2 574,705,4 2 0062 two
+3 574,705,15 2 0063 three
+4 574,705 2 0064 four
+5 574,705,15 2 0065 five
+6 574,705,15 2 0066 six
+7 574,705,15 2 0067 seven
+8 574,705,15 2 0070 eight
+9 574,705,15 2 0071 nine
+: 278,485,15 0 0072 colon
+; 278,485,189 0 0073 semicolon
+< 606,538,13 0 0074 less
+= 606,399 0 0075 equal
+> 606,538,13 0 0076 greater
+? 500,737,15 2 0077 question
+@ 747,737,15 2 0100 at
+at "
+A 759,737 2 0101 A
+B 778,722 2 0102 B
+C 778,737,15 2 0103 C
+D 833,722 2 0104 D
+E 759,722 2 0105 E
+F 722,722 2 0106 F
+G 833,737,15 2 0107 G
+H 870,722 2 0110 H
+I 444,722 2 0111 I
+J 648,722,15 2 0112 J
+K 815,722 2 0113 K
+L 722,722 2 0114 L
+M 981,722 2 0115 M
+N 833,722,8 2 0116 N
+O 833,737,15 2 0117 O
+P 759,722 2 0120 P
+Q 833,737,189 2 0121 Q
+R 815,722,15 2 0122 R
+S 667,737,15 2 0123 S
+T 722,722 2 0124 T
+U 833,722,15 2 0125 U
+V 759,722,15 2 0126 V
+W 981,722,15 2 0127 W
+X 722,722 2 0130 X
+Y 722,722 2 0131 Y
+Z 667,722 2 0132 Z
+[ 389,722,113 2 0133 bracketleft
+lB "
+\ 606,737 2 0134 backslash
+rs "
+] 389,722,113 2 0135 bracketright
+rB "
+a^ 333,723 2 0136 circumflex
+^ "
+_ 500,0,148 0 0137 underscore
+` 241,747 2 0140 quoteleft
+oq "
+a 611,485,15 0 0141 a
+b 648,737,15 2 0142 b
+c 556,485,15 0 0143 c
+d 667,737,15 2 0144 d
+e 574,485,15 0 0145 e
+f 389,737 2 0146 f
+g 611,536,205 1 0147 g
+h 685,737 2 0150 h
+i 370,737 2 0151 i
+j 352,737,205 3 0152 j
+k 667,737 2 0153 k
+l 352,737 2 0154 l
+m 963,485 0 0155 m
+n 685,485 0 0156 n
+o 611,485,15 0 0157 o
+p 667,485,205 1 0160 p
+q 648,485,205 1 0161 q
+r 519,485 0 0162 r
+s 500,485,15 0 0163 s
+t 426,675,15 2 0164 t
+u 685,475,15 0 0165 u
+v 611,475,8 0 0166 v
+w 889,475,8 0 0167 w
+x 611,475 0 0170 x
+y 611,475,207 1 0171 y
+z 537,475 0 0172 z
+lC 389,723,111 2 0173 braceleft
+{ "
+ba 606,737 2 0174 bar
+| "
+rC 389,723,111 2 0175 braceright
+} "
+a~ 333,704 2 0176 tilde
+~ "
+bq 241,169,189 0 0200 quotesinglbase
+Fo 500,405 0 0201 guillemotleft
+char171 "
+Fc 500,405 0 0202 guillemotright
+char187 "
+bu 606,511 0 0203 bullet
+Fn 574,737,205 3 0204 florin
+f/ 167,705 2 0205 fraction
+%0 1000,694,27 2 0206 perthousand
+dg 500,737,88 2 0207 dagger
+dd 500,736,89 2 0210 daggerdbl
+en 500,296 0 0211 endash
+em 1000,296 0 0212 emdash
+fi 685,737 2 0214 fi
+fl 685,737 2 0215 fl
+.i 370,475 0 0220 dotlessi
+ga 333,734 2 0222 grave
+a" 333,737 2 0223 hungarumlaut
+a. 333,693 2 0224 dotaccent
+ab 333,712 2 0225 breve
+ah 333,723 2 0226 caron
+ao 333,760 2 0227 ring
+ho 333,0,163 0 0230 ogonek
+lq 481,747 2 0231 quotedblleft
+rq 481,737 2 0232 quotedblright
+oe 907,485,15 0 0233 oe
+/l 352,737 2 0234 lslash
+Bq 481,169,189 0 0235 quotedblbase
+OE 1000,722 2 0236 OE
+/L 722,722 2 0237 Lslash
+r! 296,547,205 1 0241 exclamdown
+char161 "
+ct 574,566,108 0 0242 cent
+char162 "
+Po 574,705,15 2 0243 sterling
+char163 "
+Cs 574,591 0 0244 currency
+char164 "
+Ye 574,705 2 0245 yen
+char165 "
+bb 606,737 2 0246 brokenbar
+char166 "
+sc 500,737,86 2 0247 section
+char167 "
+ad 333,693 2 0250 dieresis
+char168 "
+co 747,737,15 2 0251 copyright
+char169 "
+Of 367,737 2 0252 ordfeminine
+char170 "
+fo 333,405 0 0253 guilsinglleft
+no 606,399 0 0254 logicalnot
+char172 "
+\- 606,302 0 0255 minus
+rg 747,737,15 2 0256 registered
+char174 "
+a- 333,663 0 0257 macron
+char175 "
+de 400,705 2 0260 degree
+char176 "
+char177 606,514 0 0261 plusminus
+S2 344,705 2 0262 twosuperior
+char178 "
+S3 344,705 2 0263 threesuperior
+char179 "
+aa 333,737 2 0264 acute
+char180 "
+char181 685,475,205 1 0265 mu
+ps 747,722 2 0266 paragraph
+char182 "
+char183 278,338 0 0267 periodcentered
+ac 333,0,221 1 0270 cedilla
+char184 "
+S1 344,705 2 0271 onesuperior
+char185 "
+Om 367,737 2 0272 ordmasculine
+char186 "
+fc 333,408 0 0273 guilsinglright
+14 861,705 2 0274 onequarter
+char188 "
+12 861,705,2 2 0275 onehalf
+char189 "
+34 861,705 2 0276 threequarters
+char190 "
+r? 500,547,205 1 0277 questiondown
+char191 "
+`A 759,981 2 0300 Agrave
+char192 "
+'A 759,984 2 0301 Aacute
+char193 "
+^A 759,970 2 0302 Acircumflex
+char194 "
+~A 759,951 2 0303 Atilde
+char195 "
+:A 759,940 2 0304 Adieresis
+char196 "
+oA 759,1007 2 0305 Aring
+char197 "
+AE 981,722 2 0306 AE
+char198 "
+,C 778,737,221 3 0307 Ccedilla
+char199 "
+`E 759,981 2 0310 Egrave
+char200 "
+'E 759,984 2 0311 Eacute
+char201 "
+^E 759,970 2 0312 Ecircumflex
+char202 "
+:E 759,940 2 0313 Edieresis
+char203 "
+`I 444,981 2 0314 Igrave
+char204 "
+'I 444,984 2 0315 Iacute
+char205 "
+^I 444,970 2 0316 Icircumflex
+char206 "
+:I 444,940 2 0317 Idieresis
+char207 "
+-D 833,722 2 0320 Eth
+char208 "
+~N 833,951,8 2 0321 Ntilde
+char209 "
+`O 833,981,15 2 0322 Ograve
+char210 "
+'O 833,984,15 2 0323 Oacute
+char211 "
+^O 833,970,15 2 0324 Ocircumflex
+char212 "
+~O 833,951,15 2 0325 Otilde
+char213 "
+:O 833,940,15 2 0326 Odieresis
+char214 "
+char215 606,504 0 0327 multiply
+/O 833,768,60 2 0330 Oslash
+char216 "
+`U 833,981,15 2 0331 Ugrave
+char217 "
+'U 833,984,15 2 0332 Uacute
+char218 "
+^U 833,970,15 2 0333 Ucircumflex
+char219 "
+:U 833,940,15 2 0334 Udieresis
+char220 "
+'Y 722,984 2 0335 Yacute
+char221 "
+TP 759,722 2 0336 Thorn
+char222 "
+ss 611,737,15 2 0337 germandbls
+char223 "
+`a 611,734,15 2 0340 agrave
+char224 "
+'a 611,737,15 2 0341 aacute
+char225 "
+^a 611,723,15 2 0342 acircumflex
+char226 "
+~a 611,704,15 2 0343 atilde
+char227 "
+:a 611,693,15 2 0344 adieresis
+char228 "
+oa 611,760,15 2 0345 aring
+char229 "
+ae 870,485,15 0 0346 ae
+char230 "
+,c 556,485,221 1 0347 ccedilla
+char231 "
+`e 574,734,15 2 0350 egrave
+char232 "
+'e 574,737,15 2 0351 eacute
+char233 "
+^e 574,723,15 2 0352 ecircumflex
+char234 "
+:e 574,693,15 2 0353 edieresis
+char235 "
+`i 370,734 2 0354 igrave
+char236 "
+'i 370,737 2 0355 iacute
+char237 "
+^i 370,723 2 0356 icircumflex
+char238 "
+:i 370,693 2 0357 idieresis
+char239 "
+Sd 611,737,15 2 0360 eth
+char240 "
+~n 685,704 2 0361 ntilde
+char241 "
+`o 611,734,15 2 0362 ograve
+char242 "
+'o 611,737,15 2 0363 oacute
+char243 "
+^o 611,723,15 2 0364 ocircumflex
+char244 "
+~o 611,704,15 2 0365 otilde
+char245 "
+:o 611,693,15 2 0366 odieresis
+char246 "
+char247 606,514 0 0367 divide
+/o 611,565,111 0 0370 oslash
+char248 "
+`u 685,734,15 2 0371 ugrave
+char249 "
+'u 685,737,15 2 0372 uacute
+char250 "
+^u 685,723,15 2 0373 ucircumflex
+char251 "
+:u 685,693,15 2 0374 udieresis
+char252 "
+'y 611,737,207 3 0375 yacute
+char253 "
+Tp 667,675,205 3 0376 thorn
+char254 "
+:y 611,693,207 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/NBI b/gnu/usr.bin/groff/devices/devps/NBI
new file mode 100644
index 000000000000..3471b41e757b
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/NBI
@@ -0,0 +1,447 @@
+name NBI
+internalname NewCenturySchlbk-BoldItalic
+slant 16
+spacewidth 287
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -50
+A w -20
+A v -20
+A ' -74
+A Y -74
+A W -92
+A V -111
+A T -74
+F . -129
+F f -18
+F , -129
+F A -74
+L y -55
+L ' -55
+L Y -55
+L W -55
+L V -74
+L T -55
+P . -129
+P , -129
+P A -92
+R y -50
+R Y -20
+R W -20
+R V -20
+R T -20
+T y -89
+T w -89
+T u -89
+T ; -72
+T s -89
+T r -89
+T . -111
+T o -109
+T i -71
+T - -129
+T hy -129
+T char173 -129
+T e -109
+T , -111
+T : -62
+T c -89
+T a -74
+T A -50
+V y -89
+V u -89
+V ; -74
+V r -109
+V . -111
+V o -129
+V i -72
+V - -74
+V hy -74
+V char173 -74
+V e -129
+V , -111
+V : -74
+V a -129
+V A -129
+W y -74
+W u -74
+W ; -37
+W r -74
+W . -55
+W o -74
+W i -74
+W - -37
+W hy -37
+W char173 -37
+W e -74
+W , -55
+W : -37
+W a -74
+W A -89
+Y v -129
+Y u -129
+Y ; -111
+Y q -129
+Y . -129
+Y p -129
+Y o -129
+Y i -90
+Y - -129
+Y hy -129
+Y char173 -129
+Y e -129
+Y , -129
+Y : -111
+Y a -129
+Y A -111
+f ' 74
+1 1 -74
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -37
+' s -37
+' ' -18
+r ' 55
+r . -129
+r , -129
+v . -37
+v , -37
+w . -37
+w , -37
+y . -55
+y , -55
+charset
+ha 606,722,0,0,-2 2 0000 asciicircum
+ti 606,353,0,0,-1 0 0001 asciitilde
+vS 685,954,15,31,49,31 2 0002 Scaron
+vZ 704,954,0,61,79,61 2 0003 Zcaron
+vs 481,709,15,46,48,46 2 0004 scaron
+vz 519,709,15,27,69,27 2 0005 zcaron
+:Y 704,930,0,123,35,109 2 0006 Ydieresis
+tm 950,722,0,82,8,82 2 0007 trademark
+aq 287,736,0,32,-50,32 2 0010 quotesingle
+space 287 0 0040
+! 333,737,15,53,47,53 2 0041 exclam
+" 400,737,0,157,-50,109 2 0042 quotedbl
+# 574,705,0,9,9,9 2 0043 numbersign
+sh "
+$ 574,799,143,35,47,35 2 0044 dollar
+Do "
+% 889,721,34,0,-1 2 0045 percent
+& 889,737,15,0,19 2 0046 ampersand
+' 259,739,0,92,-20,92 2 0047 quoteright
+( 407,740,123,95,-21,95 2 0050 parenleft
+) 407,740,123,0,120 2 0051 parenright
+* 500,704,0,22,18,22 2 0052 asterisk
++ 606,505,0,0,9 0 0053 plus
+, 287,159,190,0,98 0 0054 comma
+- 333,297,0,0,40 0 0055 hyphen
+hy "
+char173 "
+. 287,159,15,0,38 0 0056 period
+/ 278,737,15,83,75,83 2 0057 slash
+sl "
+0 574,705,15,29,29,29 2 0060 zero
+1 574,705,0,0,25 2 0061 one
+2 574,705,0,14,90,14 2 0062 two
+3 574,705,15,14,55,14 2 0063 three
+4 574,705,0,20,63,20 2 0064 four
+5 574,705,15,49,50,49 2 0065 five
+6 574,705,15,49,20,49 2 0066 six
+7 574,705,15,69,-14,69 2 0067 seven
+8 574,705,15,27,50,27 2 0070 eight
+9 574,705,15,20,49,20 2 0071 nine
+: 287,477,15,20,52,20 0 0072 colon
+; 287,477,190,20,89,20 0 0073 semicolon
+< 606,524,14,0,36 0 0074 less
+= 606,402,0,0,9 0 0075 equal
+> 606,524,14,0,12 0 0076 greater
+? 481,737,15,21,-29,21 2 0077 question
+@ 747,737,15,25,28,25 2 0100 at
+at "
+A 741,737,0,25,125,25 2 0101 A
+B 759,722,0,11,100,11 2 0102 B
+C 759,737,15,50,15,50 2 0103 C
+D 833,722,0,13,99,13 2 0104 D
+E 741,722,0,37,91,37 2 0105 E
+F 704,722,0,72,91,72 2 0106 F
+G 815,737,15,37,16,37 2 0107 G
+H 870,722,0,92,91,92 2 0110 H
+I 444,722,0,92,91,92 2 0111 I
+J 667,722,15,101,59,101 2 0112 J
+K 778,722,0,104,91,104 2 0113 K
+L 704,722,0,16,91,16 2 0114 L
+M 944,722,0,94,74,94 2 0115 M
+N 852,722,16,110,107,109 2 0116 N
+O 833,737,15,14,14,14 2 0117 O
+P 741,722,0,40,88,40 2 0120 P
+Q 833,737,186,13,15,13 2 0121 Q
+R 796,722,15,5,91,5 2 0122 R
+S 685,737,15,31,49,31 2 0123 S
+T 722,722,0,90,6,90 2 0124 T
+U 833,722,15,112,-38,109 2 0125 U
+V 741,722,15,111,18,109 2 0126 V
+W 944,722,15,100,10,100 2 0127 W
+X 741,722,0,120,122,109 2 0130 X
+Y 704,722,0,123,35,109 2 0131 Y
+Z 704,722,0,61,79,61 2 0132 Z
+[ 407,737,110,75,81,75 2 0133 bracketleft
+lB "
+\ 606,737,0,0,-31 2 0134 backslash
+rs "
+] 407,737,110,57,99,57 2 0135 bracketright
+rB "
+a^ 333,709,0,82,27,82 2 0136 circumflex
+^ "
+_ 500,0,129,50,50,50 0 0137 underscore
+` 259,747,0,61,11,61 2 0140 quoteleft
+oq "
+a 667,477,15,29,35,29 0 0141 a
+b 611,737,15,0,22 2 0142 b
+c 537,477,15,0,47 0 0143 c
+d 667,737,15,46,50,46 2 0144 d
+e 519,477,15,9,52,9 0 0145 e
+f 389,737,205,211,98,109 3 0146 f
+g 611,529,205,41,116,41 1 0147 g
+h 685,737,15,2,50,2 2 0150 h
+i 389,737,15,4,22,4 2 0151 i
+j 370,737,205,61,220,61 3 0152 j
+k 648,737,15,0,55 2 0153 k
+l 389,737,15,31,24,31 2 0154 l
+m 944,477,15,26,41,26 0 0155 m
+n 685,477,15,7,47,7 0 0156 n
+o 574,477,15,16,40,16 0 0157 o
+p 648,477,205,0,168 1 0160 p
+q 630,477,205,7,50,7 1 0161 q
+r 519,486,0,55,47,55 0 0162 r
+s 481,477,15,6,48,6 0 0163 s
+t 407,650,15,47,26,47 2 0164 t
+u 685,477,15,4,12,4 0 0165 u
+v 556,477,15,0,18 0 0166 v
+w 833,477,15,5,28,5 0 0167 w
+x 574,477,15,47,99,47 0 0170 x
+y 519,477,205,23,116,23 1 0171 y
+z 519,477,15,2,69,2 0 0172 z
+lC 407,738,115,45,-2,45 2 0173 braceleft
+{ "
+ba 606,737,0,0,-212 2 0174 bar
+| "
+rC 407,738,115,0,80 2 0175 braceright
+} "
+a~ 333,683,0,121,16,109 2 0176 tilde
+~ "
+bq 259,159,191,0,93 0 0200 quotesinglbase
+Fo 481,409,0,0,85 0 0201 guillemotleft
+char171 "
+Fc 481,408,0,25,56,25 0 0202 guillemotright
+char187 "
+bu 606,537,0,0,-59 0 0203 bullet
+Fn 574,737,205,64,77,64 3 0204 florin
+f/ 167,705,15,216,216,109 2 0205 fraction
+%0 1167,721,34,34,24,34 2 0206 perthousand
+dg 500,737,146,60,0,60 2 0207 dagger
+dd 500,737,147,64,98,64 2 0210 daggerdbl
+en 500,286,0,68,68,68 0 0211 endash
+em 1000,286,0,68,68,68 0 0212 emdash
+fi 685,737,205,11,120,11 3 0214 fi
+fl 685,737,205,46,120,46 3 0215 fl
+.i 389,477,15,14,12,14 0 0220 dotlessi
+ga 333,719,0,11,-24,11 2 0222 grave
+a" 333,719,0,189,27,109 2 0223 hungarumlaut
+a. 333,685,0,5,-95,5 2 0224 dotaccent
+ab 333,698,0,107,-17,107 2 0225 breve
+ah 333,709,0,120,-10,109 2 0226 caron
+ao 333,745,0,149,-167,109 2 0227 ring
+ho 333,0,155,0,-18 0 0230 ogonek
+lq 481,747,0,91,-2,91 2 0231 quotedblleft
+rq 481,739,0,102,-11,102 2 0232 quotedblright
+oe 852,477,15,8,55,8 0 0233 oe
+/l 389,737,15,58,24,58 2 0234 lslash
+Bq 481,159,191,0,120 0 0235 quotedblbase
+OE 963,722,0,67,31,67 2 0236 OE
+/L 704,722,0,16,91,16 2 0237 Lslash
+r! 333,544,205,6,89,6 1 0241 exclamdown
+char161 "
+ct 574,600,124,0,20 0 0242 cent
+char162 "
+Po 574,705,15,42,68,42 2 0243 sterling
+char163 "
+Cs 574,612,0,22,10,22 0 0244 currency
+char164 "
+Ye 574,705,0,111,27,109 2 0245 yen
+char165 "
+bb 606,737,0,0,-212 2 0246 brokenbar
+char166 "
+sc 500,737,145,55,90,55 2 0247 section
+char167 "
+ad 333,685,0,109,16,109 2 0250 dieresis
+char168 "
+co 747,737,15,26,27,26 2 0251 copyright
+char169 "
+Of 412,737,0,87,21,87 2 0252 ordfeminine
+char170 "
+fo 278,409,0,0,85 0 0253 guilsinglleft
+no 606,402,0,0,9 0 0254 logicalnot
+char172 "
+\- 606,304,0,0,9 0 0255 minus
+rg 747,737,15,26,27,26 2 0256 registered
+char174 "
+a- 333,649,0,104,18,104 2 0257 macron
+char175 "
+de 400,705,0,20,-20,20 2 0260 degree
+char176 "
+char177 606,505,0,0,9 0 0261 plusminus
+S2 344,705,0,66,66,66 2 0262 twosuperior
+char178 "
+S3 344,705,0,54,54,54 2 0263 threesuperior
+char179 "
+aa 333,719,0,88,-73,88 2 0264 acute
+char180 "
+char181 685,477,205,4,140,4 1 0265 mu
+ps 650,737,0,61,-17,61 2 0266 paragraph
+char182 "
+char183 287,342,0,0,9 0 0267 periodcentered
+ac 333,3,220,0,137 1 0270 cedilla
+char184 "
+S1 344,705,0,29,29,29 2 0271 onesuperior
+char185 "
+Om 356,737,0,77,21,77 2 0272 ordmasculine
+char186 "
+fc 278,408,0,25,56,25 0 0273 guilsinglright
+14 861,705,15,15,29,15 2 0274 onequarter
+char188 "
+12 861,705,15,46,29,46 2 0275 onehalf
+char189 "
+34 861,705,15,15,54,15 2 0276 threequarters
+char190 "
+r? 481,544,205,0,49 1 0277 questiondown
+char191 "
+`A 741,964,0,25,125,25 2 0300 Agrave
+char192 "
+'A 741,964,0,25,125,25 2 0301 Aacute
+char193 "
+^A 741,954,0,25,125,25 2 0302 Acircumflex
+char194 "
+~A 741,928,0,25,125,25 2 0303 Atilde
+char195 "
+:A 741,930,0,25,125,25 2 0304 Adieresis
+char196 "
+oA 741,990,0,25,125,25 2 0305 Aring
+char197 "
+AE 889,722,0,64,131,64 2 0306 AE
+char198 "
+,C 759,737,220,50,15,50 3 0307 Ccedilla
+char199 "
+`E 741,964,0,37,91,37 2 0310 Egrave
+char200 "
+'E 741,964,0,37,91,37 2 0311 Eacute
+char201 "
+^E 741,954,0,37,91,37 2 0312 Ecircumflex
+char202 "
+:E 741,930,0,37,91,37 2 0313 Edieresis
+char203 "
+`I 444,964,0,92,91,92 2 0314 Igrave
+char204 "
+'I 444,964,0,92,91,92 2 0315 Iacute
+char205 "
+^I 444,954,0,92,91,92 2 0316 Icircumflex
+char206 "
+:I 444,930,0,104,91,104 2 0317 Idieresis
+char207 "
+-D 833,722,0,13,99,13 2 0320 Eth
+char208 "
+~N 852,928,16,110,107,109 2 0321 Ntilde
+char209 "
+`O 833,964,15,14,14,14 2 0322 Ograve
+char210 "
+'O 833,964,15,14,14,14 2 0323 Oacute
+char211 "
+^O 833,954,15,14,14,14 2 0324 Ocircumflex
+char212 "
+~O 833,928,15,14,14,14 2 0325 Otilde
+char213 "
+:O 833,930,15,14,14,14 2 0326 Odieresis
+char214 "
+char215 606,507,0,0,9 0 0327 multiply
+/O 833,775,82,14,33,14 2 0330 Oslash
+char216 "
+`U 833,964,15,112,-38,109 2 0331 Ugrave
+char217 "
+'U 833,964,15,112,-38,109 2 0332 Uacute
+char218 "
+^U 833,954,15,112,-38,109 2 0333 Ucircumflex
+char219 "
+:U 833,930,15,112,-38,109 2 0334 Udieresis
+char220 "
+'Y 704,964,0,123,35,109 2 0335 Yacute
+char221 "
+TP 741,722,0,0,88 2 0336 Thorn
+char222 "
+ss 574,737,205,0,116 3 0337 germandbls
+char223 "
+`a 667,719,15,29,35,29 2 0340 agrave
+char224 "
+'a 667,719,15,29,35,29 2 0341 aacute
+char225 "
+^a 667,709,15,29,35,29 2 0342 acircumflex
+char226 "
+~a 667,683,15,29,35,29 2 0343 atilde
+char227 "
+:a 667,685,15,29,35,29 2 0344 adieresis
+char228 "
+oa 667,745,15,29,35,29 2 0345 aring
+char229 "
+ae 815,477,15,9,69,9 0 0346 ae
+char230 "
+,c 537,477,220,0,47 1 0347 ccedilla
+char231 "
+`e 519,719,15,9,52,9 2 0350 egrave
+char232 "
+'e 519,719,15,9,52,9 2 0351 eacute
+char233 "
+^e 519,709,15,9,52,9 2 0352 ecircumflex
+char234 "
+:e 519,685,15,26,52,26 2 0353 edieresis
+char235 "
+`i 389,719,15,14,12,14 2 0354 igrave
+char236 "
+'i 389,719,15,60,12,60 2 0355 iacute
+char237 "
+^i 389,709,15,44,12,44 2 0356 icircumflex
+char238 "
+:i 389,685,15,71,12,71 2 0357 idieresis
+char239 "
+Sd 574,737,15,16,40,16 2 0360 eth
+char240 "
+~n 685,683,15,7,47,7 2 0361 ntilde
+char241 "
+`o 574,719,15,16,40,16 2 0362 ograve
+char242 "
+'o 574,719,15,16,40,16 2 0363 oacute
+char243 "
+^o 574,709,15,16,40,16 2 0364 ocircumflex
+char244 "
+~o 574,683,15,16,40,16 2 0365 otilde
+char245 "
+:o 574,685,15,16,40,16 2 0366 odieresis
+char246 "
+char247 606,505,0,0,9 0 0367 divide
+/o 574,578,126,16,40,16 0 0370 oslash
+char248 "
+`u 685,719,15,4,12,4 2 0371 ugrave
+char249 "
+'u 685,719,15,4,12,4 2 0372 uacute
+char250 "
+^u 685,709,15,4,12,4 2 0373 ucircumflex
+char251 "
+:u 685,685,15,4,12,4 2 0374 udieresis
+char252 "
+'y 519,719,205,23,116,23 3 0375 yacute
+char253 "
+Tp 648,650,205,0,168 3 0376 thorn
+char254 "
+:y 519,685,205,23,116,23 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/NI b/gnu/usr.bin/groff/devices/devps/NI
new file mode 100644
index 000000000000..eb250d77d134
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/NI
@@ -0,0 +1,447 @@
+name NI
+internalname NewCenturySchlbk-Italic
+slant 16
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -54
+A w -20
+A v -20
+A ' -74
+A Y -74
+A W -92
+A V -111
+A T -74
+F . -129
+F f -18
+F , -129
+F A -74
+L y -55
+L ' -55
+L Y -55
+L W -55
+L V -74
+L T -55
+P . -129
+P , -129
+P A -92
+R y -54
+R Y -74
+R W -55
+R V -20
+R T -20
+T y -89
+T w -89
+T u -89
+T ; -92
+T s -89
+T r -89
+T . -111
+T o -89
+T i -71
+T - -129
+T hy -129
+T char173 -129
+T e -89
+T , -111
+T : -92
+T c -89
+T a -74
+T A -18
+V y -109
+V u -109
+V ; -74
+V r -109
+V . -111
+V o -129
+V i -62
+V - -74
+V hy -74
+V char173 -74
+V e -129
+V , -140
+V : -74
+V a -129
+V A -111
+W y -74
+W u -74
+W ; -37
+W r -74
+W . -55
+W o -74
+W i -74
+W - -37
+W hy -37
+W char173 -37
+W e -74
+W , -55
+W : -37
+W a -74
+W A -74
+Y v -99
+Y u -99
+Y ; -111
+Y q -129
+Y . -129
+Y p -129
+Y o -129
+Y i -70
+Y - -129
+Y hy -129
+Y char173 -129
+Y e -129
+Y , -129
+Y : -111
+Y a -129
+Y A -74
+f ' 94
+1 1 -74
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -37
+' s -37
+' ' -18
+r ' 55
+r . -129
+r , -129
+v . -37
+v , -37
+w . -37
+w , -37
+y . -55
+y , -55
+charset
+ha 606,722,0,0,-2 2 0000 asciicircum
+ti 606,335,0,0,9 0 0001 asciitilde
+vS 667,944,15,15,50,15 2 0002 Scaron
+vZ 667,944,0,50,75,50 2 0003 Zcaron
+vs 444,688,15,40,51,40 2 0004 scaron
+vz 463,688,15,30,83,30 2 0005 zcaron
+:Y 685,900,0,123,18,107 2 0006 Ydieresis
+tm 950,722,0,71,2,71 2 0007 trademark
+aq 278,737,0,34,-64,34 2 0010 quotesingle
+space 278 0 0040
+! 333,737,15,33,20,33 2 0041 exclam
+" 400,737,0,45,-50,45 2 0042 quotedbl
+# 556,705,0,18,17,18 2 0043 numbersign
+sh "
+$ 556,800,133,30,47,30 2 0044 dollar
+Do "
+% 833,705,17,9,4,9 2 0045 percent
+& 852,737,15,0,26 2 0046 ampersand
+' 204,737,0,76,11,76 2 0047 quoteright
+( 333,737,124,116,10,107 2 0050 parenleft
+) 333,737,124,0,143 2 0051 parenright
+* 500,705,0,2,16,2 2 0052 asterisk
++ 606,504,0,0,13 0 0053 plus
+, 278,109,165,0,89 0 0054 comma
+- 333,273,0,0,18 0 0055 hyphen
+hy "
+char173 "
+. 278,109,15,0,33 0 0056 period
+/ 606,737,102,0,-90 2 0057 slash
+sl "
+0 556,705,15,21,21,21 2 0060 zero
+1 556,705 2 0061 one
+2 556,705,0,2,85,2 2 0062 two
+3 556,705,15,0,52 2 0063 three
+4 556,705,0,6,58,6 2 0064 four
+5 556,705,15,34,46,34 2 0065 five
+6 556,705,15,41,14,41 2 0066 six
+7 556,705,15,55,-19,55 2 0067 seven
+8 556,705,15,21,42,21 2 0070 eight
+9 556,705,15,13,43,13 2 0071 nine
+: 278,466,15,26,8,26 0 0072 colon
+; 278,466,165,33,64,33 0 0073 semicolon
+< 606,518,10,0,16 0 0074 less
+= 606,381,0,0,14 0 0075 equal
+> 606,518,10,6,-3,6 0 0076 greater
+? 444,737,15,23,-52,23 2 0077 question
+@ 747,737,15,31,22,31 2 0100 at
+at "
+A 704,737,0,14,132,14 2 0101 A
+B 722,722,0,0,81 2 0102 B
+C 722,737,15,41,10,41 2 0103 C
+D 778,722,0,7,88,7 2 0104 D
+E 722,722,0,29,87,29 2 0105 E
+F 667,722,0,81,84,81 2 0106 F
+G 778,737,15,35,11,35 2 0107 G
+H 833,722,0,84,88,84 2 0110 H
+I 407,722,0,74,83,74 2 0111 I
+J 611,722,17,85,63,85 2 0112 J
+K 741,722,0,123,90,107 2 0113 K
+L 667,722,0,13,87,13 2 0114 L
+M 944,722,0,79,76,79 2 0115 M
+N 815,722,17,94,98,94 2 0116 N
+O 778,737,15,7,10,7 2 0117 O
+P 667,722,0,46,83,46 2 0120 P
+Q 778,737,190,7,10,7 2 0121 Q
+R 741,722,17,0,91 2 0122 R
+S 667,737,15,15,50,15 2 0123 S
+T 685,722,0,91,10,91 2 0124 T
+U 815,722,15,95,-43,95 2 0125 U
+V 704,722,15,118,14,107 2 0126 V
+W 926,722,15,97,-3,97 2 0127 W
+X 704,722,0,116,123,107 2 0130 X
+Y 685,722,0,123,18,107 2 0131 Y
+Z 667,722,0,50,75,50 2 0132 Z
+[ 333,737,109,127,83,107 2 0133 bracketleft
+lB "
+\ 606,737,0,0,-39 2 0134 backslash
+rs "
+] 333,737,109,76,133,76 2 0135 bracketright
+rB "
+a^ 333,688,0,48,13,48 2 0136 circumflex
+^ "
+_ 500,0,123,50,50,50 0 0137 underscore
+` 204,749,0,98,-11,98 2 0140 quoteleft
+oq "
+a 574,466,15,0,49 0 0141 a
+b 556,737,15,0,18 2 0142 b
+c 444,466,15,7,45,7 0 0143 c
+d 611,737,15,25,47,25 2 0144 d
+e 444,466,15,0,56 0 0145 e
+f 333,737,205,187,118,107 3 0146 f
+g 537,499,205,36,129,36 1 0147 g
+h 611,737,15,0,50 2 0150 h
+i 333,715,15,0,23 2 0151 i
+j 315,715,205,52,216,52 3 0152 j
+k 556,737,15,0,55 2 0153 k
+l 333,737,15,11,34,11 2 0154 l
+m 889,466,15,0,35 0 0155 m
+n 611,466,15,1,36,1 0 0156 n
+o 500,466,15,0,45 0 0157 o
+p 574,466,205,0,151 1 0160 p
+q 556,466,205,0,50 1 0161 q
+r 444,466,0,39,41,39 0 0162 r
+s 444,466,15,0,51 0 0163 s
+t 352,619,15,27,25,27 2 0164 t
+u 611,466,15,0,9 0 0165 u
+v 519,466,15,0,16 0 0166 v
+w 778,466,15,0,18 0 0167 w
+x 500,466,15,21,83,21 0 0170 x
+y 500,466,205,4,129,4 1 0171 y
+z 463,466,15,4,83,4 0 0172 z
+lC 333,737,116,98,-2,98 2 0173 braceleft
+{ "
+ba 606,737,0,0,-219 2 0174 bar
+| "
+rC 333,737,116,0,148 2 0175 braceright
+} "
+a~ 333,650,0,97,-2,97 2 0176 tilde
+~ "
+bq 204,109,167,0,129 0 0200 quotesinglbase
+Fo 426,399,0,26,65,26 0 0201 guillemotleft
+char171 "
+Fc 426,394,0,24,67,24 0 0202 guillemotright
+char187 "
+bu 606,537,0,0,-64 0 0203 bullet
+Fn 556,737,205,57,107,57 3 0204 florin
+f/ 167,705,17,216,154,107 2 0205 fraction
+%0 1000,705,15,53,56,53 2 0206 perthousand
+dg 500,737,147,68,-14,68 2 0207 dagger
+dd 500,737,148,78,80,78 2 0210 daggerdbl
+en 500,260,0,68,68,68 0 0211 endash
+em 1000,260,0,68,68,68 0 0212 emdash
+fi 611,737,205,3,110,3 3 0214 fi
+fl 611,737,205,33,110,33 3 0215 fl
+.i 333,466,15,0,23 0 0220 dotlessi
+ga 333,691,0,0,-23 2 0222 grave
+a" 333,689,0,237,-84,107 2 0223 hungarumlaut
+a. 333,644,0,0,-68 2 0224 dotaccent
+ab 333,677,0,87,-19,87 2 0225 breve
+ah 333,688,0,95,-23,95 2 0226 caron
+ao 333,712,0,146,-180,107 2 0227 ring
+ho 333,0,155,0,-18 0 0230 ogonek
+lq 389,749,0,93,-13,93 2 0231 quotedblleft
+rq 389,737,0,68,12,68 2 0232 quotedblright
+oe 778,466,17,0,50 0 0233 oe
+/l 333,737,15,59,34,59 2 0234 lslash
+Bq 389,109,167,0,129 0 0235 quotedblbase
+OE 981,722,0,32,14,32 2 0236 OE
+/L 667,722,0,13,87,13 2 0237 Lslash
+r! 333,542,205,0,57 1 0241 exclamdown
+char161 "
+ct 556,595,129,0,-11 0 0242 cent
+char162 "
+Po 556,705,15,39,58,39 2 0243 sterling
+char163 "
+Cs 556,603,0,24,25,24 0 0244 currency
+char164 "
+Ye 556,705,0,117,10,107 2 0245 yen
+char165 "
+bb 606,737,0,0,-219 2 0246 brokenbar
+char166 "
+sc 500,737,147,30,61,30 2 0247 section
+char167 "
+ad 333,644,0,76,-9,76 2 0250 dieresis
+char168 "
+co 747,737,15,27,26,27 2 0251 copyright
+char169 "
+Of 422,737,0,50,-33,50 2 0252 ordfeminine
+char170 "
+fo 333,399,0,0,8 0 0253 guilsinglleft
+no 606,381,0,0,9 0 0254 logicalnot
+char172 "
+\- 606,287,0,0,9 0 0255 minus
+rg 747,737,15,26,27,26 2 0256 registered
+char174 "
+a- 333,610,0,80,-1,80 0 0257 macron
+char175 "
+de 400,705,0,20,-20,20 2 0260 degree
+char176 "
+char177 606,504,0,0,13 0 0261 plusminus
+S2 333,705,0,70,50,70 2 0262 twosuperior
+char178 "
+S3 333,705,0,48,49,48 2 0263 threesuperior
+char179 "
+aa 333,689,0,72,-82,72 2 0264 acute
+char180 "
+char181 611,466,205,0,120 1 0265 mu
+ps 650,737,0,45,-38,45 2 0266 paragraph
+char182 "
+char183 278,316,0,0,-27 0 0267 periodcentered
+ac 333,0,227,0,47 1 0270 cedilla
+char184 "
+S1 333,705,0,26,7,26 2 0271 onesuperior
+char185 "
+Om 372,738,0,50,-33,50 2 0272 ordmasculine
+char186 "
+fc 333,394,0,0,10 0 0273 guilsinglright
+14 834,705,17,49,17,49 2 0274 onequarter
+char188 "
+12 834,705,17,60,17,60 2 0275 onehalf
+char189 "
+34 834,705,17,49,49,49 2 0276 threequarters
+char190 "
+r? 444,542,205,0,43 1 0277 questiondown
+char191 "
+`A 704,947,0,14,132,14 2 0300 Agrave
+char192 "
+'A 704,945,0,14,132,14 2 0301 Aacute
+char193 "
+^A 704,944,0,14,132,14 2 0302 Acircumflex
+char194 "
+~A 704,906,0,14,132,14 2 0303 Atilde
+char195 "
+:A 704,900,0,14,132,14 2 0304 Adieresis
+char196 "
+oA 704,968,0,14,132,14 2 0305 Aring
+char197 "
+AE 870,722,0,50,142,50 2 0306 AE
+char198 "
+,C 722,737,227,41,10,41 3 0307 Ccedilla
+char199 "
+`E 722,947,0,29,87,29 2 0310 Egrave
+char200 "
+'E 722,945,0,29,87,29 2 0311 Eacute
+char201 "
+^E 722,944,0,29,87,29 2 0312 Ecircumflex
+char202 "
+:E 722,900,0,29,87,29 2 0313 Edieresis
+char203 "
+`I 407,947,0,74,83,74 2 0314 Igrave
+char204 "
+'I 407,945,0,74,83,74 2 0315 Iacute
+char205 "
+^I 407,944,0,74,83,74 2 0316 Icircumflex
+char206 "
+:I 407,900,0,89,83,89 2 0317 Idieresis
+char207 "
+-D 778,722,0,7,88,7 2 0320 Eth
+char208 "
+~N 815,906,17,94,98,94 2 0321 Ntilde
+char209 "
+`O 778,947,15,7,10,7 2 0322 Ograve
+char210 "
+'O 778,945,15,7,10,7 2 0323 Oacute
+char211 "
+^O 778,944,15,7,10,7 2 0324 Ocircumflex
+char212 "
+~O 778,906,15,7,10,7 2 0325 Otilde
+char213 "
+:O 778,900,15,7,10,7 2 0326 Odieresis
+char214 "
+char215 606,504,0,0,13 0 0327 multiply
+/O 778,755,87,7,49,7 2 0330 Oslash
+char216 "
+`U 815,947,15,95,-43,95 2 0331 Ugrave
+char217 "
+'U 815,945,15,95,-43,95 2 0332 Uacute
+char218 "
+^U 815,944,15,95,-43,95 2 0333 Ucircumflex
+char219 "
+:U 815,900,15,95,-43,95 2 0334 Udieresis
+char220 "
+'Y 685,945,0,123,18,107 2 0335 Yacute
+char221 "
+TP 667,722,0,7,83,7 2 0336 Thorn
+char222 "
+ss 556,737,205,19,126,19 3 0337 germandbls
+char223 "
+`a 574,691,15,0,49 2 0340 agrave
+char224 "
+'a 574,689,15,0,49 2 0341 aacute
+char225 "
+^a 574,688,15,0,49 2 0342 acircumflex
+char226 "
+~a 574,650,15,0,49 2 0343 atilde
+char227 "
+:a 574,644,15,0,49 2 0344 adieresis
+char228 "
+oa 574,712,15,0,49 2 0345 aring
+char229 "
+ae 722,466,15,0,68 0 0346 ae
+char230 "
+,c 444,466,227,7,45,7 1 0347 ccedilla
+char231 "
+`e 444,691,15,0,56 2 0350 egrave
+char232 "
+'e 444,689,15,17,56,17 2 0351 eacute
+char233 "
+^e 444,688,15,0,56 2 0352 ecircumflex
+char234 "
+:e 444,644,15,11,56,11 2 0353 edieresis
+char235 "
+`i 333,691,15,0,23 2 0354 igrave
+char236 "
+'i 333,689,15,72,23,72 2 0355 iacute
+char237 "
+^i 333,688,15,8,53,8 2 0356 icircumflex
+char238 "
+:i 333,644,15,66,23,66 2 0357 idieresis
+char239 "
+Sd 500,737,15,0,45 2 0360 eth
+char240 "
+~n 611,650,15,1,36,1 2 0361 ntilde
+char241 "
+`o 500,691,15,0,45 2 0362 ograve
+char242 "
+'o 500,689,15,0,45 2 0363 oacute
+char243 "
+^o 500,688,15,0,45 2 0364 ocircumflex
+char244 "
+~o 500,650,15,4,45,4 2 0365 otilde
+char245 "
+:o 500,644,15,0,45 2 0366 odieresis
+char246 "
+char247 606,504,0,0,13 0 0367 divide
+/o 500,549,121,0,55 0 0370 oslash
+char248 "
+`u 611,691,15,0,9 2 0371 ugrave
+char249 "
+'u 611,689,15,0,9 2 0372 uacute
+char250 "
+^u 611,688,15,0,9 2 0373 ucircumflex
+char251 "
+:u 611,644,15,0,9 2 0374 udieresis
+char252 "
+'y 500,689,205,4,129,4 3 0375 yacute
+char253 "
+Tp 574,656,205,0,151 3 0376 thorn
+char254 "
+:y 500,644,205,4,129,4 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/NR b/gnu/usr.bin/groff/devices/devps/NR
new file mode 100644
index 000000000000..d545b2ab8237
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/NR
@@ -0,0 +1,447 @@
+name NR
+internalname NewCenturySchlbk-Roman
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -74
+A ' -74
+A Y -92
+A W -92
+A V -111
+A T -55
+F . -111
+F , -111
+F A -74
+L y -55
+L ' -55
+L Y -92
+L W -74
+L V -92
+L T -55
+P . -129
+P , -129
+P A -74
+R y -18
+R Y -37
+R W -37
+R V -37
+T y -52
+T w -71
+T u -71
+T ; -55
+T s -62
+T r -62
+T . -92
+T o -92
+T i -25
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -92
+T : -55
+T c -81
+T a -62
+T A -55
+V y -92
+V u -74
+V ; -74
+V r -74
+V . -129
+V o -92
+V i -44
+V - -92
+V hy -92
+V char173 -92
+V e -92
+V , -129
+V : -74
+V a -92
+V A -111
+W y -74
+W u -55
+W ; -37
+W r -55
+W . -111
+W o -55
+W i -37
+W - -37
+W hy -37
+W char173 -37
+W e -55
+W , -111
+W : -37
+W a -74
+W A -92
+Y v -111
+Y u -92
+Y ; -92
+Y q -111
+Y . -111
+Y p -111
+Y o -111
+Y i -44
+Y - -111
+Y hy -111
+Y char173 -111
+Y e -111
+Y , -111
+Y : -92
+Y a -111
+Y A -92
+f ' 114
+1 1 -55
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -18
+' s -37
+' ' -18
+r ' 55
+r . -74
+r - -18
+r hy -18
+r char173 -18
+r , -74
+v . -111
+v , -111
+w . -92
+w , -92
+y . -111
+y , -111
+charset
+ha 606,722 2 0000 asciicircum
+ti 606,329 0 0001 asciitilde
+vS 630,952,15 2 0002 Scaron
+vZ 611,952 2 0003 Zcaron
+vs 463,694,15 2 0004 scaron
+vz 481,694 2 0005 zcaron
+:Y 704,902 2 0006 Ydieresis
+tm 1000,737 2 0007 trademark
+aq 204,737 2 0010 quotesingle
+space 278 0 0040
+! 296,737,15 2 0041 exclam
+" 389,737 2 0042 quotedbl
+# 556,690 2 0043 numbersign
+sh "
+$ 556,804,129 2 0044 dollar
+Do "
+% 833,707,18 2 0045 percent
+& 815,737,15 2 0046 ampersand
+' 204,737 2 0047 quoteright
+( 333,737,124 2 0050 parenleft
+) 333,737,124 2 0051 parenright
+* 500,737 2 0052 asterisk
++ 606,492,13 0 0053 plus
+, 278,109,184 0 0054 comma
+- 333,279 0 0055 hyphen
+hy "
+char173 "
+. 278,109,15 0 0056 period
+/ 278,737,15 2 0057 slash
+sl "
+0 556,705,15 2 0060 zero
+1 556,705 2 0061 one
+2 556,705,4 2 0062 two
+3 556,705,15 2 0063 three
+4 556,705 2 0064 four
+5 556,705,15 2 0065 five
+6 556,705,15 2 0066 six
+7 556,705,15 2 0067 seven
+8 556,705,15 2 0070 eight
+9 556,705,15 2 0071 nine
+: 278,475,15 0 0072 colon
+; 278,475,189 0 0073 semicolon
+< 606,503,25 0 0074 less
+= 606,374 0 0075 equal
+> 606,503,25 0 0076 greater
+? 444,737,15 2 0077 question
+@ 737,737,15 2 0100 at
+at "
+A 722,737 2 0101 A
+B 722,722 2 0102 B
+C 722,737,15 2 0103 C
+D 778,722 2 0104 D
+E 722,722 2 0105 E
+F 667,722 2 0106 F
+G 778,737,15 2 0107 G
+H 833,722 2 0110 H
+I 407,722 2 0111 I
+J 556,722,15 2 0112 J
+K 778,722 2 0113 K
+L 667,722 2 0114 L
+M 944,722 2 0115 M
+N 815,722,15 2 0116 N
+O 778,737,15 2 0117 O
+P 667,722 2 0120 P
+Q 778,737,189 2 0121 Q
+R 722,722,15 2 0122 R
+S 630,737,15 2 0123 S
+T 667,722 2 0124 T
+U 815,722,15 2 0125 U
+V 722,722,15 2 0126 V
+W 981,722,15 2 0127 W
+X 704,722 2 0130 X
+Y 704,722 2 0131 Y
+Z 611,722 2 0132 Z
+[ 333,722,109 2 0133 bracketleft
+lB "
+\ 606,737 2 0134 backslash
+rs "
+] 333,723,108 2 0135 bracketright
+rB "
+a^ 333,694 2 0136 circumflex
+^ "
+_ 500,0,134 0 0137 underscore
+` 204,737 2 0140 quoteleft
+oq "
+a 556,479,15 0 0141 a
+b 556,737,15 2 0142 b
+c 444,479,15 0 0143 c
+d 574,737,15 2 0144 d
+e 500,479,15 0 0145 e
+f 333,737 2 0146 f
+g 537,494,205 1 0147 g
+h 611,737 2 0150 h
+i 315,716 2 0151 i
+j 296,716,205 3 0152 j
+k 593,737 2 0153 k
+l 315,737 2 0154 l
+m 889,479 0 0155 m
+n 611,479 0 0156 n
+o 500,479,15 0 0157 o
+p 574,479,205 1 0160 p
+q 556,479,205 1 0161 q
+r 444,479 0 0162 r
+s 463,479,15 0 0163 s
+t 389,666,15 2 0164 t
+u 611,464,15 0 0165 u
+v 537,464,15 0 0166 v
+w 778,464,15 0 0167 w
+x 537,464 0 0170 x
+y 537,464,205 1 0171 y
+z 481,464 0 0172 z
+lC 333,722,109 2 0173 braceleft
+{ "
+ba 606,737 2 0174 bar
+| "
+rC 333,722,109 2 0175 braceright
+} "
+a~ 333,659 0 0176 tilde
+~ "
+bq 204,104,189 0 0200 quotesinglbase
+Fo 426,397 0 0201 guillemotleft
+char171 "
+Fc 426,399 0 0202 guillemotright
+char187 "
+bu 606,554 0 0203 bullet
+Fn 556,737,205 3 0204 florin
+f/ 167,705 2 0205 fraction
+%0 1000,699,1 2 0206 perthousand
+dg 500,737,147 2 0207 dagger
+dd 500,737,151 2 0210 daggerdbl
+en 556,269 0 0211 endash
+em 1000,269 0 0212 emdash
+fi 611,737 2 0214 fi
+fl 611,737 2 0215 fl
+.i 315,464 0 0220 dotlessi
+ga 333,699 2 0222 grave
+a" 333,714 2 0223 hungarumlaut
+a. 333,644 0 0224 dotaccent
+ab 333,685 2 0225 breve
+ah 333,694 2 0226 caron
+ao 333,722 2 0227 ring
+ho 333,0,163 0 0230 ogonek
+lq 389,737 2 0231 quotedblleft
+rq 389,737 2 0232 quotedblright
+oe 833,479,15 0 0233 oe
+/l 315,737 2 0234 lslash
+Bq 389,104,189 0 0235 quotedblbase
+OE 1000,722 2 0236 OE
+/L 667,722 2 0237 Lslash
+r! 296,547,205 1 0241 exclamdown
+char161 "
+ct 556,584,141 0 0242 cent
+char162 "
+Po 556,705,15 2 0243 sterling
+char163 "
+Cs 556,603 0 0244 currency
+char164 "
+Ye 556,705 2 0245 yen
+char165 "
+bb 606,737 2 0246 brokenbar
+char166 "
+sc 500,737,147 2 0247 section
+char167 "
+ad 333,644 0 0250 dieresis
+char168 "
+co 737,737,15 2 0251 copyright
+char169 "
+Of 334,722 2 0252 ordfeminine
+char170 "
+fo 259,397 0 0253 guilsinglleft
+no 606,374 0 0254 logicalnot
+char172 "
+\- 606,277 0 0255 minus
+rg 737,737,15 2 0256 registered
+char174 "
+a- 333,622 0 0257 macron
+char175 "
+de 400,705 2 0260 degree
+char176 "
+char177 606,492 0 0261 plusminus
+S2 333,705 2 0262 twosuperior
+char178 "
+S3 333,705 2 0263 threesuperior
+char179 "
+aa 333,699 2 0264 acute
+char180 "
+char181 611,464,205 1 0265 mu
+ps 606,722,147 2 0266 paragraph
+char182 "
+char183 278,302 0 0267 periodcentered
+ac 333,0,215 1 0270 cedilla
+char184 "
+S1 333,705 2 0271 onesuperior
+char185 "
+Om 300,722 2 0272 ordmasculine
+char186 "
+fc 259,399 0 0273 guilsinglright
+14 834,705 2 0274 onequarter
+char188 "
+12 834,705,2 2 0275 onehalf
+char189 "
+34 834,705 2 0276 threequarters
+char190 "
+r? 444,547,205 1 0277 questiondown
+char191 "
+`A 722,957 2 0300 Agrave
+char192 "
+'A 722,957 2 0301 Aacute
+char193 "
+^A 722,952 2 0302 Acircumflex
+char194 "
+~A 722,917 2 0303 Atilde
+char195 "
+:A 722,902 2 0304 Adieresis
+char196 "
+oA 722,980 2 0305 Aring
+char197 "
+AE 1000,722 2 0306 AE
+char198 "
+,C 722,737,215 3 0307 Ccedilla
+char199 "
+`E 722,957 2 0310 Egrave
+char200 "
+'E 722,957 2 0311 Eacute
+char201 "
+^E 722,952 2 0312 Ecircumflex
+char202 "
+:E 722,902 2 0313 Edieresis
+char203 "
+`I 407,957 2 0314 Igrave
+char204 "
+'I 407,957 2 0315 Iacute
+char205 "
+^I 407,952 2 0316 Icircumflex
+char206 "
+:I 407,902 2 0317 Idieresis
+char207 "
+-D 778,722 2 0320 Eth
+char208 "
+~N 815,917,15 2 0321 Ntilde
+char209 "
+`O 778,957,15 2 0322 Ograve
+char210 "
+'O 778,957,15 2 0323 Oacute
+char211 "
+^O 778,952,15 2 0324 Ocircumflex
+char212 "
+~O 778,917,15 2 0325 Otilde
+char213 "
+:O 778,902,15 2 0326 Odieresis
+char214 "
+char215 606,491,13 0 0327 multiply
+/O 778,760,74 2 0330 Oslash
+char216 "
+`U 815,957,15 2 0331 Ugrave
+char217 "
+'U 815,957,15 2 0332 Uacute
+char218 "
+^U 815,952,15 2 0333 Ucircumflex
+char219 "
+:U 815,902,15 2 0334 Udieresis
+char220 "
+'Y 704,957 2 0335 Yacute
+char221 "
+TP 667,722 2 0336 Thorn
+char222 "
+ss 574,737,15 2 0337 germandbls
+char223 "
+`a 556,699,15 2 0340 agrave
+char224 "
+'a 556,699,15 2 0341 aacute
+char225 "
+^a 556,694,15 2 0342 acircumflex
+char226 "
+~a 556,659,15 0 0343 atilde
+char227 "
+:a 556,644,15 0 0344 adieresis
+char228 "
+oa 556,722,15 2 0345 aring
+char229 "
+ae 796,479,15 0 0346 ae
+char230 "
+,c 444,479,215 1 0347 ccedilla
+char231 "
+`e 500,699,15 2 0350 egrave
+char232 "
+'e 500,699,15 2 0351 eacute
+char233 "
+^e 500,694,15 2 0352 ecircumflex
+char234 "
+:e 500,644,15 0 0353 edieresis
+char235 "
+`i 315,699 2 0354 igrave
+char236 "
+'i 315,699 2 0355 iacute
+char237 "
+^i 315,694 2 0356 icircumflex
+char238 "
+:i 315,644 0 0357 idieresis
+char239 "
+Sd 500,740,15 2 0360 eth
+char240 "
+~n 611,659 0 0361 ntilde
+char241 "
+`o 500,699,15 2 0362 ograve
+char242 "
+'o 500,699,15 2 0363 oacute
+char243 "
+^o 500,694,15 2 0364 ocircumflex
+char244 "
+~o 500,659,15 0 0365 otilde
+char245 "
+:o 500,644,15 0 0366 odieresis
+char246 "
+char247 606,493,11 0 0367 divide
+/o 500,556,102 0 0370 oslash
+char248 "
+`u 611,699,15 2 0371 ugrave
+char249 "
+'u 611,699,15 2 0372 uacute
+char250 "
+^u 611,694,15 2 0373 ucircumflex
+char251 "
+:u 611,644,15 0 0374 udieresis
+char252 "
+'y 537,699,205 3 0375 yacute
+char253 "
+Tp 574,737,205 3 0376 thorn
+char254 "
+:y 537,644,205 1 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/PB b/gnu/usr.bin/groff/devices/devps/PB
new file mode 100644
index 000000000000..348281ad3ddb
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/PB
@@ -0,0 +1,449 @@
+name PB
+internalname Palatino-Bold
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -70
+A w -70
+A v -70
+A ' -92
+A Y -111
+A W -90
+A V -129
+A T -92
+F . -111
+F , -111
+F A -55
+L y -74
+L ' -74
+L Y -92
+L W -92
+L V -92
+L T -74
+P . -129
+P , -129
+P A -74
+R y -30
+R Y -55
+R W -37
+R V -74
+R T -55
+T y -90
+T w -90
+T u -129
+T ; -74
+T s -111
+T r -111
+T . -92
+T o -111
+T i -55
+T - -92
+T hy -92
+T char173 -92
+T e -111
+T , -92
+T : -74
+T c -129
+T a -111
+T A -92
+V y -90
+V u -92
+V ; -74
+V r -111
+V . -129
+V o -111
+V i -55
+V - -92
+V hy -92
+V char173 -92
+V e -111
+V , -129
+V : -74
+V a -111
+V A -129
+W y -74
+W u -74
+W ; -37
+W r -74
+W . -37
+W o -74
+W i -37
+W - -37
+W hy -37
+W char173 -37
+W e -74
+W , -92
+W : -37
+W a -74
+W A -90
+Y v -74
+Y u -74
+Y ; -55
+Y q -92
+Y . -74
+Y p -74
+Y o -74
+Y i -55
+Y - -74
+Y hy -74
+Y char173 -74
+Y e -74
+Y , -74
+Y : -55
+Y a -74
+Y A -55
+f ' 37
+f f -18
+1 1 -37
+` ` -55
+` oq -55
+oq ` -55
+oq oq -55
+' t -18
+' s -55
+' ' -55
+r ' 55
+r . -55
+r - -18
+r hy -18
+r char173 -18
+r , -55
+v . -111
+v , -111
+w . -92
+w , -92
+y . -92
+y , -92
+charset
+ha 606,678 2 0000 asciicircum
+ti 606,342 0 0001 asciitilde
+vS 611,909,17 2 0002 Scaron
+vZ 667,909,3 2 0003 Zcaron
+vs 444,693,17 2 0004 scaron
+vz 500,693,3 2 0005 zcaron
+:Y 667,895,3 2 0006 Ydieresis
+tm 998,678 2 0007 trademark
+aq 227,695 2 0010 quotesingle
+space 250 0 0040
+! 278,688,12 2 0041 exclam
+" 402,695 2 0042 quotedbl
+# 500,673 2 0043 numbersign
+sh "
+$ 500,721,114 2 0044 dollar
+Do "
+% 889,714,9 2 0045 percent
+& 833,684,17 2 0046 ampersand
+' 278,695 2 0047 quoteright
+( 333,723,104 2 0050 parenleft
+) 333,723,104 2 0051 parenright
+* 444,695 2 0052 asterisk
++ 606,505 0 0053 plus
+, 250,141,166 0 0054 comma
+- 333,305 0 0055 hyphen
+hy "
+char173 "
+. 250,144,12 0 0056 period
+/ 296,720,17 2 0057 slash
+sl "
+0 500,660,17 2 0060 zero
+1 500,670,3 2 0061 one
+2 500,660,3 2 0062 two
+3 500,660,17 2 0063 three
+4 500,672,3 2 0064 four
+5 500,656,17 2 0065 five
+6 500,660,17 2 0066 six
+7 500,656,3 2 0067 seven
+8 500,660,17 2 0070 eight
+9 500,660,17 2 0071 nine
+: 250,454,12 0 0072 colon
+; 250,454,166 0 0073 semicolon
+< 606,519,15 0 0074 less
+= 606,396 0 0075 equal
+> 606,519,15 0 0076 greater
+? 444,687,12 2 0077 question
+@ 747,681,12 2 0100 at
+at "
+A 778,686,3 2 0101 A
+B 667,681,3 2 0102 B
+C 722,695,17 2 0103 C
+D 833,681,3 2 0104 D
+E 611,681,4 2 0105 E
+F 556,681,3 2 0106 F
+G 833,695,17 2 0107 G
+H 833,681,3 2 0110 H
+I 389,681,3 2 0111 I
+J 389,681,213 2 0112 J
+K 778,681,3 2 0113 K
+L 611,681,4 2 0114 L
+M 1000,681,10 2 0115 M
+N 833,681,16 2 0116 N
+O 833,695,17 2 0117 O
+P 611,681,3 2 0120 P
+Q 833,695,184 2 0121 Q
+R 722,681,3 2 0122 R
+S 611,695,17 2 0123 S
+T 667,681,3 2 0124 T
+U 778,681,17 2 0125 U
+V 778,681,3 2 0126 V
+W 1000,686,3 2 0127 W
+X 667,695,3 2 0130 X
+Y 667,695,3 2 0131 Y
+Z 667,681,3 2 0132 Z
+[ 333,720,104 2 0133 bracketleft
+lB "
+\ 606,720 2 0134 backslash
+rs "
+] 333,720,104 2 0135 bracketright
+rB "
+a^ 333,681 2 0136 circumflex
+^ "
+_ 500,0,125 0 0137 underscore
+` 278,695 2 0140 quoteleft
+oq "
+a 500,471,17 0 0141 a
+b 611,720,17 2 0142 b
+c 444,471,17 0 0143 c
+d 611,720,17 2 0144 d
+e 500,471,17 0 0145 e
+f 389,720,3 2 0146 f
+g 556,471,266 1 0147 g
+h 611,720,3 2 0150 h
+i 333,706,3 2 0151 i
+j 333,706,266 3 0152 j
+k 611,720,3 2 0153 k
+l 333,720,3 2 0154 l
+m 889,471,3 0 0155 m
+n 611,471,3 0 0156 n
+o 556,471,17 0 0157 o
+p 611,471,258 1 0160 p
+q 611,471,258 1 0161 q
+r 389,471,3 0 0162 r
+s 444,471,17 0 0163 s
+t 333,632,17 2 0164 t
+u 611,471,17 0 0165 u
+v 556,459,3 0 0166 v
+w 833,471,3 0 0167 w
+x 500,471,3 0 0170 x
+y 556,459,266 1 0171 y
+z 500,459,3 0 0172 z
+lC 310,725,117 2 0173 braceleft
+{ "
+ba 606,720 2 0174 bar
+| "
+rC 310,725,117 2 0175 braceright
+} "
+a~ 333,661 2 0176 tilde
+~ "
+bq 333,130,160 0 0200 quotesinglbase
+Fo 500,438 0 0201 guillemotleft
+char171 "
+Fc 500,438 0 0202 guillemotright
+char187 "
+bu 606,516 0 0203 bullet
+Fn 500,703,242 2 0204 florin
+f/ 167,660 2 0205 fraction
+%0 1000,724,9 2 0206 perthousand
+dg 500,682,6 2 0207 dagger
+dd 500,682,245 2 0210 daggerdbl
+en 500,291 0 0211 endash
+em 1000,291 0 0212 emdash
+fi 611,720,3 2 0214 fi
+fl 611,720,3 2 0215 fl
+.i 333,471,3 0 0220 dotlessi
+ga 333,691 2 0222 grave
+a" 333,691 2 0223 hungarumlaut
+a. 333,671 2 0224 dotaccent
+ab 333,669 2 0225 breve
+ah 333,685 2 0226 caron
+ao 333,700 2 0227 ring
+ho 333,0,246 0 0230 ogonek
+lq 500,695 2 0231 quotedblleft
+rq 500,695 2 0232 quotedblright
+oe 833,471,17 0 0233 oe
+/l 333,720,3 2 0234 lslash
+Bq 500,130,160 0 0235 quotedblbase
+OE 1000,695,17 2 0236 OE
+/L 611,681,4 2 0237 Lslash
+r! 278,471,227 0 0241 exclamdown
+char161 "
+ct 500,554,106 0 0242 cent
+char162 "
+Po 500,676,19 2 0243 sterling
+char163 "
+Cs 500,533 0 0244 currency
+char164 "
+Ye 500,695,3 2 0245 yen
+char165 "
+bb 606,720 2 0246 brokenbar
+char166 "
+sc 500,695,217 2 0247 section
+char167 "
+ad 333,671 2 0250 dieresis
+char168 "
+co 747,695,17 2 0251 copyright
+char169 "
+Of 438,660 2 0252 ordfeminine
+char170 "
+fo 389,438 0 0253 guilsinglleft
+no 606,396 0 0254 logicalnot
+char172 "
+\- 606,298 0 0255 minus
+rg 747,695,17 2 0256 registered
+char174 "
+a- 333,609 0 0257 macron
+char175 "
+de 400,660 2 0260 degree
+char176 "
+char177 606,505 0 0261 plusminus
+S2 300,660 2 0262 twosuperior
+char178 "
+S3 300,667 2 0263 threesuperior
+char179 "
+aa 333,691 2 0264 acute
+char180 "
+char181 611,471,225 0 0265 mu
+ps 641,683,161 2 0266 paragraph
+char182 "
+char183 250,335 0 0267 periodcentered
+ac 333,0,225 0 0270 cedilla
+char184 "
+S1 300,665 2 0271 onesuperior
+char185 "
+Om 488,660 2 0272 ordmasculine
+char186 "
+fc 389,438 0 0273 guilsinglright
+14 750,665,2 2 0274 onequarter
+char188 "
+12 750,665,2 2 0275 onehalf
+char189 "
+34 750,667,2 2 0276 threequarters
+char190 "
+r? 444,471,231 0 0277 questiondown
+char191 "
+`A 778,915,3 2 0300 Agrave
+char192 "
+'A 778,915,3 2 0301 Aacute
+char193 "
+^A 778,905,3 2 0302 Acircumflex
+char194 "
+~A 778,885,3 2 0303 Atilde
+char195 "
+:A 778,895,3 2 0304 Adieresis
+char196 "
+oA 778,924,3 2 0305 Aring
+char197 "
+AE 1000,681,4 2 0306 AE
+char198 "
+,C 722,695,225 2 0307 Ccedilla
+char199 "
+`E 611,915,4 2 0310 Egrave
+char200 "
+'E 611,915,4 2 0311 Eacute
+char201 "
+^E 611,905,4 2 0312 Ecircumflex
+char202 "
+:E 611,895,4 2 0313 Edieresis
+char203 "
+`I 389,915,3 2 0314 Igrave
+char204 "
+'I 389,915,3 2 0315 Iacute
+char205 "
+^I 389,905,3 2 0316 Icircumflex
+char206 "
+:I 389,895,3 2 0317 Idieresis
+char207 "
+-D 833,681,3 2 0320 Eth
+char208 "
+~N 833,885,16 2 0321 Ntilde
+char209 "
+`O 833,915,17 2 0322 Ograve
+char210 "
+'O 833,915,17 2 0323 Oacute
+char211 "
+^O 833,905,17 2 0324 Ocircumflex
+char212 "
+~O 833,885,17 2 0325 Otilde
+char213 "
+:O 833,895,17 2 0326 Odieresis
+char214 "
+char215 606,483 0 0327 multiply
+/O 833,698,20 2 0330 Oslash
+char216 "
+`U 778,915,17 2 0331 Ugrave
+char217 "
+'U 778,915,17 2 0332 Uacute
+char218 "
+^U 778,905,17 2 0333 Ucircumflex
+char219 "
+:U 778,895,17 2 0334 Udieresis
+char220 "
+'Y 667,915,3 2 0335 Yacute
+char221 "
+TP 611,681,3 2 0336 Thorn
+char222 "
+ss 611,720,17 2 0337 germandbls
+char223 "
+`a 500,711,17 2 0340 agrave
+char224 "
+'a 500,711,17 2 0341 aacute
+char225 "
+^a 500,701,17 2 0342 acircumflex
+char226 "
+~a 500,673,17 2 0343 atilde
+char227 "
+:a 500,691,17 2 0344 adieresis
+char228 "
+oa 500,700,17 2 0345 aring
+char229 "
+ae 778,471,17 0 0346 ae
+char230 "
+,c 444,471,225 0 0347 ccedilla
+char231 "
+`e 500,711,17 2 0350 egrave
+char232 "
+'e 500,711,17 2 0351 eacute
+char233 "
+^e 500,701,17 2 0352 ecircumflex
+char234 "
+:e 500,691,17 2 0353 edieresis
+char235 "
+`i 333,711,3 2 0354 igrave
+char236 "
+'i 333,711,3 2 0355 iacute
+char237 "
+^i 333,701,3 2 0356 icircumflex
+char238 "
+:i 333,691,3 2 0357 idieresis
+char239 "
+Sd 556,720,17 2 0360 eth
+char240 "
+~n 611,673,3 2 0361 ntilde
+char241 "
+`o 556,711,17 2 0362 ograve
+char242 "
+'o 556,711,17 2 0363 oacute
+char243 "
+^o 556,701,17 2 0364 ocircumflex
+char244 "
+~o 556,673,17 2 0365 otilde
+char245 "
+:o 556,691,17 2 0366 odieresis
+char246 "
+char247 606,510 0 0367 divide
+/o 556,471,18 0 0370 oslash
+char248 "
+`u 611,711,17 2 0371 ugrave
+char249 "
+'u 611,711,17 2 0372 uacute
+char250 "
+^u 611,701,17 2 0373 ucircumflex
+char251 "
+:u 611,691,17 2 0374 udieresis
+char252 "
+'y 556,711,266 3 0375 yacute
+char253 "
+Tp 611,720,258 3 0376 thorn
+char254 "
+:y 556,691,266 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/PBI b/gnu/usr.bin/groff/devices/devps/PBI
new file mode 100644
index 000000000000..37facbe948c1
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/PBI
@@ -0,0 +1,451 @@
+name PBI
+internalname Palatino-BoldItalic
+slant 10
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -55
+A w -37
+A v -55
+A ' -55
+A Y -74
+A W -74
+A V -74
+A T -55
+F . -111
+F , -111
+F A -74
+L y -37
+L ' -55
+L Y -74
+L W -74
+L V -74
+L T -74
+P . -129
+P , -129
+P A -92
+R y -20
+R Y -37
+R W -55
+R V -55
+R T -37
+T y -80
+T w -50
+T u -92
+T ; -55
+T s -92
+T r -92
+T . -55
+T o -111
+T i -74
+T - -92
+T hy -92
+T char173 -92
+T e -111
+T , -55
+T : -55
+T c -92
+T a -111
+T O -18
+T A -55
+V y -50
+V u -50
+V ; -37
+V r -74
+V . -111
+V o -74
+V i -50
+V - -37
+V hy -37
+V char173 -37
+V e -74
+V , -111
+V : -37
+V a -92
+V A -74
+W y -30
+W u -30
+W ; -18
+W r -30
+W . -55
+W o -55
+W i -30
+W e -55
+W , -55
+W : -28
+W a -74
+W A -74
+Y v -30
+Y u -50
+Y ; -55
+Y q -92
+Y . -55
+Y p -74
+Y o -111
+Y i -54
+Y - -55
+Y hy -55
+Y char173 -55
+Y e -92
+Y , -55
+Y : -55
+Y a -111
+Y A -55
+f ' 37
+f f -37
+1 1 -55
+` ` -55
+` oq -55
+oq ` -55
+oq oq -55
+' t -18
+' s -37
+' ' -55
+r ' 55
+r q -18
+r . -55
+r o -18
+r h -18
+r g -18
+r e -18
+r , -55
+r c -18
+v . -55
+v , -55
+w . -55
+w , -55
+y . -37
+y , -37
+charset
+ha 606,678,0,0,-13 2 0000 asciicircum
+ti 606,346,0,0,-1 0 0001 asciitilde
+vS 556,896,17,51,0,51 2 0002 Scaron
+vZ 667,896,3,59,49,59 2 0003 Zcaron
+vs 444,692,17,95,25,66 2 0004 scaron
+vz 500,692,17,67,19,66 2 0005 zcaron
+:Y 611,880,3,114,-4,66 2 0006 Ydieresis
+tm 1000,678,0,11,12,11 2 0007 trademark
+aq 250,720,0,93,-77,66 2 0010 quotesingle
+space 250 0 0040
+! 333,695,17,39,-8,39 2 0041 exclam
+" 500,720,0,43,-87,43 2 0042 quotedbl
+# 500,673,0,46,46,46 2 0043 numbersign
+sh "
+$ 500,737,108,27,30,27 2 0044 dollar
+Do "
+% 889,697,17,0,-6 2 0045 percent
+& 833,695,17,28,-24,28 2 0046 ampersand
+' 278,720,0,74,-26,66 2 0047 quoteright
+( 333,723,129,85,-8,66 2 0050 parenleft
+) 333,723,129,15,62,15 2 0051 parenright
+* 444,695,0,45,-34,45 2 0052 asterisk
++ 606,501,5 0 0053 plus
+, 250,147,164,8,83,8 0 0054 comma
+- 389,300,0,23,13,23 0 0055 hyphen
+hy "
+char173 "
+. 250,135,17,0,2 0 0056 period
+/ 315,720,17,50,49,50 2 0057 slash
+sl "
+0 500,683,17,40,8,40 2 0060 zero
+1 500,678,3,0,9 2 0061 one
+2 500,683,3,4,49,4 2 0062 two
+3 500,683,17,0,42 2 0063 three
+4 500,683,3,37,47,37 2 0064 four
+5 500,675,17,31,36,31 2 0065 five
+6 500,683,17,38,11,38 2 0066 six
+7 500,674,3,94,-19,66 2 0067 seven
+8 500,683,17,34,24,34 2 0070 eight
+9 500,683,17,41,23,41 2 0071 nine
+: 250,452,17,36,12,36 0 0072 colon
+; 250,452,164,47,83,47 0 0073 semicolon
+< 606,517,21,2,1,2 0 0074 less
+= 606,390,0,0,-1 0 0075 equal
+> 606,517,21,1,2,1 0 0076 greater
+? 444,695,17,56,-41,56 2 0077 question
+@ 833,681,12,0,-32 2 0100 at
+at "
+A 722,683,3,13,85,13 2 0101 A
+B 667,681,3,12,42,12 2 0102 B
+C 685,695,17,60,-19,60 2 0103 C
+D 778,682,3,19,50,19 2 0104 D
+E 611,681,3,45,39,45 2 0105 E
+F 556,681,3,87,56,66 2 0106 F
+G 778,695,17,22,-22,22 2 0107 G
+H 778,681,3,98,62,66 2 0110 H
+I 389,681,3,73,51,66 2 0111 I
+J 389,681,207,78,79,66 2 0112 J
+K 722,681,3,74,60,66 2 0113 K
+L 611,681,3,17,24,17 2 0114 L
+M 944,681,17,91,73,66 2 0115 M
+N 778,681,3,101,52,66 2 0116 N
+O 833,695,17,11,-26,11 2 0117 O
+P 667,681,3,56,39,56 2 0120 P
+Q 833,695,222,11,-26,11 2 0121 Q
+R 722,681,3,25,46,25 2 0122 R
+S 556,695,17,11,0,11 2 0123 S
+T 611,681,3,113,-6,66 2 0124 T
+U 778,681,17,97,-33,66 2 0125 U
+V 667,681,3,128,-17,66 2 0126 V
+W 1000,689,3,123,-17,66 2 0127 W
+X 722,681,3,100,59,66 2 0130 X
+Y 611,695,3,114,-4,66 2 0131 Y
+Z 667,681,3,59,49,59 2 0132 Z
+[ 333,723,102,98,5,66 2 0133 bracketleft
+lB "
+\ 606,720,0,0,-22 2 0134 backslash
+rs "
+] 333,723,102,32,71,32 2 0135 bracketright
+rB "
+a^ 333,684,0,132,-38,66 2 0136 circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 underscore
+` 278,720,0,63,-15,63 2 0140 quoteleft
+oq "
+a 556,470,17,13,6,13 0 0141 a
+b 537,726,17,7,6,7 2 0142 b
+c 444,469,17,42,18,42 0 0143 c
+d 556,726,17,44,12,44 2 0144 d
+e 444,469,17,24,22,24 0 0145 e
+f 333,726,271,166,180,66 3 0146 f
+g 500,469,271,79,100,66 1 0147 g
+h 556,726,17,16,28,16 2 0150 h
+i 333,695,17,29,24,29 2 0151 i
+j 333,695,271,40,114,40 3 0152 j
+k 556,726,17,22,16,22 2 0153 k
+l 333,726,17,35,-14,35 2 0154 l
+m 833,469,17,20,31,20 0 0155 m
+n 556,469,17,15,33,15 0 0156 n
+o 556,469,17,0,2 0 0157 o
+p 556,469,271,10,71,10 1 0160 p
+q 537,469,271,26,18,26 1 0161 q
+r 389,469,17,72,30,66 0 0162 r
+s 444,469,17,12,25,12 0 0163 s
+t 389,636,17,70,8,66 2 0164 t
+u 556,469,17,15,28,15 0 0165 u
+v 556,469,17,7,31,7 0 0166 v
+w 833,469,17,19,23,19 0 0167 w
+x 500,469,17,50,58,50 0 0170 x
+y 556,469,271,35,37,35 1 0171 y
+z 500,469,17,20,19,20 0 0172 z
+lC 333,720,105,51,32,51 2 0173 braceleft
+{ "
+ba 606,720,0,0,-209 2 0174 bar
+| "
+rC 333,720,105,32,51,32 2 0175 braceright
+} "
+a~ 333,654,0,158,-32,66 2 0176 tilde
+~ "
+bq 250,145,144,20,53,20 0 0200 quotesinglbase
+Fo 500,446,0,8,15,8 0 0201 guillemotleft
+char171 "
+Fc 500,443,0,8,15,8 0 0202 guillemotright
+char187 "
+bu 606,516,0,0,-81 0 0203 bullet
+Fn 500,690,242,29,42,29 2 0204 florin
+f/ 167,683,0,221,220,66 2 0205 fraction
+%0 1000,691,17,0,-15 2 0206 perthousand
+dg 556,685,3,0,-17 2 0207 dagger
+dd 556,693,153,31,17,31 2 0210 daggerdbl
+en 500,282,0,62,62,62 0 0211 endash
+em 1000,282,0,62,62,62 0 0212 emdash
+fi 611,726,271,27,180,27 3 0214 fi
+fl 611,726,271,70,180,66 3 0215 fl
+.i 333,469,17,10,24,10 0 0220 dotlessi
+ga 333,699,0,39,-60,39 2 0222 grave
+a" 333,699,0,126,78,66 2 0223 hungarumlaut
+a. 333,668,0,42,-152,42 2 0224 dotaccent
+ab 333,680,0,129,-46,66 2 0225 breve
+ah 333,684,0,162,-63,66 2 0226 caron
+ao 556,714,0,0,-227 2 0227 ring
+ho 333,0,206,0,18 0 0230 ogonek
+lq 500,720,0,61,-15,61 2 0231 quotedblleft
+rq 500,720,0,69,-23,66 2 0232 quotedblright
+oe 778,469,17,27,2,27 0 0233 oe
+/l 333,726,17,82,37,66 2 0234 lslash
+Bq 500,145,144,0,68 0 0235 quotedblbase
+OE 944,695,17,67,11,66 2 0236 OE
+/L 611,681,3,17,44,17 2 0237 Lslash
+r! 333,479,225,0,48 0 0241 exclamdown
+char161 "
+ct 500,547,105,6,-2,6 0 0242 cent
+char162 "
+Po 500,683,5,51,29,51 2 0243 sterling
+char163 "
+Cs 500,533,0,18,18,18 0 0244 currency
+char164 "
+Ye 500,695,3,88,39,66 2 0245 yen
+char165 "
+bb 606,720,0,0,-209 2 0246 brokenbar
+char166 "
+sc 556,695,151,0,3 2 0247 section
+char167 "
+ad 333,668,0,143,-40,66 2 0250 dieresis
+char168 "
+co 747,695,17,23,24,23 2 0251 copyright
+char169 "
+Of 333,684,0,72,3,66 2 0252 ordfeminine
+char170 "
+fo 333,446,0,9,-10,9 0 0253 guilsinglleft
+no 606,390,0,0,-1 0 0254 logicalnot
+char172 "
+\- 606,292,0,0,-1 0 0255 minus
+rg 747,695,17,23,24,23 2 0256 registered
+char174 "
+a- 333,608,0,135,-26,66 0 0257 macron
+char175 "
+de 400,683 2 0260 degree
+char176 "
+char177 606,501 0 0261 plusminus
+S2 300,683,0,71,24,66 2 0262 twosuperior
+char178 "
+S3 300,683,0,60,27,60 2 0263 threesuperior
+char179 "
+aa 333,699,0,109,-103,66 2 0264 acute
+char180 "
+char181 556,469,232,15,65,15 0 0265 mu
+ps 556,681,204,123,36,66 2 0266 paragraph
+char182 "
+char183 250,324,0,6,-17,6 0 0267 periodcentered
+ac 333,5,218,0,38 0 0270 cedilla
+char184 "
+S1 300,680,0,48,9,48 2 0271 onesuperior
+char185 "
+Om 333,683,0,63,-1,63 2 0272 ordmasculine
+char186 "
+fc 333,443,0,0,15 0 0273 guilsinglright
+14 750,683,2,32,32,32 2 0274 onequarter
+char188 "
+12 750,683,2,36,36,36 2 0275 onehalf
+char189 "
+34 750,683,2,32,32,32 2 0276 threequarters
+char190 "
+r? 444,479,226,0,62 0 0277 questiondown
+char191 "
+`A 722,911,3,13,85,13 2 0300 Agrave
+char192 "
+'A 722,911,3,13,85,13 2 0301 Aacute
+char193 "
+^A 722,896,3,13,85,13 2 0302 Acircumflex
+char194 "
+~A 722,866,3,13,85,13 2 0303 Atilde
+char195 "
+:A 722,880,3,13,85,13 2 0304 Adieresis
+char196 "
+oA 722,926,3,13,85,13 2 0305 Aring
+char197 "
+AE 944,681,3,33,79,33 2 0306 AE
+char198 "
+,C 685,695,218,60,-19,60 2 0307 Ccedilla
+char199 "
+`E 611,911,3,45,39,45 2 0310 Egrave
+char200 "
+'E 611,911,3,45,39,45 2 0311 Eacute
+char201 "
+^E 611,896,3,45,39,45 2 0312 Ecircumflex
+char202 "
+:E 611,880,3,45,39,45 2 0313 Edieresis
+char203 "
+`I 389,911,3,73,51,66 2 0314 Igrave
+char204 "
+'I 389,911,3,81,51,66 2 0315 Iacute
+char205 "
+^I 389,896,3,104,51,66 2 0316 Icircumflex
+char206 "
+:I 389,880,3,115,51,66 2 0317 Idieresis
+char207 "
+-D 778,682,3,19,50,19 2 0320 Eth
+char208 "
+~N 778,866,3,101,52,66 2 0321 Ntilde
+char209 "
+`O 833,911,17,11,-26,11 2 0322 Ograve
+char210 "
+'O 833,911,17,11,-26,11 2 0323 Oacute
+char211 "
+^O 833,896,17,11,-26,11 2 0324 Ocircumflex
+char212 "
+~O 833,866,17,11,-26,11 2 0325 Otilde
+char213 "
+:O 833,880,17,11,-26,11 2 0326 Odieresis
+char214 "
+char215 606,479,0,0,-22 0 0327 multiply
+/O 833,730,54,14,-7,14 2 0330 Oslash
+char216 "
+`U 778,911,17,97,-33,66 2 0331 Ugrave
+char217 "
+'U 778,911,17,97,-33,66 2 0332 Uacute
+char218 "
+^U 778,896,17,97,-33,66 2 0333 Ucircumflex
+char219 "
+:U 778,880,17,97,-33,66 2 0334 Udieresis
+char220 "
+'Y 611,911,3,114,-4,66 2 0335 Yacute
+char221 "
+TP 667,681,3,27,39,27 2 0336 Thorn
+char222 "
+ss 556,726,271,43,181,43 3 0337 germandbls
+char223 "
+`a 556,719,17,13,6,13 2 0340 agrave
+char224 "
+'a 556,719,17,13,6,13 2 0341 aacute
+char225 "
+^a 556,704,17,21,6,21 2 0342 acircumflex
+char226 "
+~a 556,666,17,47,6,47 2 0343 atilde
+char227 "
+:a 556,688,17,32,6,32 2 0344 adieresis
+char228 "
+oa 556,714,17,13,6,13 2 0345 aring
+char229 "
+ae 738,469,17,23,6,23 0 0346 ae
+char230 "
+,c 444,469,218,42,18,42 0 0347 ccedilla
+char231 "
+`e 444,719,17,24,22,24 2 0350 egrave
+char232 "
+'e 444,719,17,54,22,54 2 0351 eacute
+char233 "
+^e 444,704,17,77,22,66 2 0352 ecircumflex
+char234 "
+:e 444,688,17,88,22,66 2 0353 edieresis
+char235 "
+`i 333,719,17,39,24,39 2 0354 igrave
+char236 "
+'i 333,719,17,109,24,66 2 0355 iacute
+char237 "
+^i 333,704,17,120,24,66 2 0356 icircumflex
+char238 "
+:i 333,688,17,143,24,66 2 0357 idieresis
+char239 "
+Sd 556,726,17,40,2,40 2 0360 eth
+char240 "
+~n 556,666,17,47,33,47 2 0361 ntilde
+char241 "
+`o 556,719,17,0,2 2 0362 ograve
+char242 "
+'o 556,719,17,0,2 2 0363 oacute
+char243 "
+^o 556,704,17,9,2,9 2 0364 ocircumflex
+char244 "
+~o 556,666,17,47,2,47 2 0365 otilde
+char245 "
+:o 556,688,17,32,2,32 2 0366 odieresis
+char246 "
+char247 606,501,5 0 0367 divide
+/o 556,506,50,16,36,16 0 0370 oslash
+char248 "
+`u 556,719,17,15,28,15 2 0371 ugrave
+char249 "
+'u 556,719,17,15,28,15 2 0372 uacute
+char250 "
+^u 556,704,17,15,28,15 2 0373 ucircumflex
+char251 "
+:u 556,688,17,32,28,32 2 0374 udieresis
+char252 "
+'y 556,719,271,35,37,35 3 0375 yacute
+char253 "
+Tp 556,726,271,10,71,10 3 0376 thorn
+char254 "
+:y 556,688,271,35,37,35 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/PI b/gnu/usr.bin/groff/devices/devps/PI
new file mode 100644
index 000000000000..7839606f4979
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/PI
@@ -0,0 +1,453 @@
+name PI
+internalname Palatino-Italic
+slant 10
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -55
+A w -37
+A v -37
+A ' -55
+A Y -55
+A W -55
+A V -74
+A T -55
+F . -111
+F , -111
+F A -111
+L y -37
+L ' -37
+L Y -74
+L W -74
+L V -74
+L T -74
+P . -129
+P , -129
+P A -129
+R y -37
+R Y -55
+R W -55
+R V -74
+R T -55
+T y -92
+T w -92
+T u -111
+T ; -74
+T s -111
+T r -111
+T . -74
+T o -111
+T i -55
+T - -55
+T hy -55
+T char173 -55
+T e -111
+T , -74
+T : -74
+T c -111
+T a -111
+T O -18
+T A -92
+V y -74
+V u -74
+V ; -37
+V r -92
+V . -129
+V o -74
+V i -74
+V - -55
+V hy -55
+V char173 -55
+V e -92
+V , -129
+V : -37
+V a -74
+V A -210
+W y -20
+W u -20
+W ; -18
+W r -20
+W . -55
+W o -20
+W i -20
+W - -18
+W hy -18
+W char173 -18
+W e -20
+W , -55
+W : -18
+W a -20
+W A -92
+Y v -74
+Y u -92
+Y ; -74
+Y q -92
+Y . -92
+Y p -74
+Y o -111
+Y i -55
+Y - -74
+Y hy -74
+Y char173 -74
+Y e -111
+Y , -92
+Y : -74
+Y a -92
+Y A -92
+f ' 55
+1 1 -55
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+' t -37
+' s -55
+' ' -74
+r ' 37
+r q -18
+r . -74
+r o -18
+r h -18
+r g -18
+r e -18
+r , -74
+r c -18
+v . -55
+v , -55
+w . -55
+w , -55
+y . -37
+y , -37
+charset
+ha 606,689,0,0,-1 2 0000 asciicircum
+ti 606,339,0,0,-1 0 0001 asciitilde
+vS 556,907,18,33,8,33 2 0002 Scaron
+vZ 667,907,3,20,30,20 2 0003 Zcaron
+vs 389,687,11,80,41,68 2 0004 scaron
+vz 444,687,11,53,51,53 2 0005 zcaron
+:Y 667,847,3,58,-2,58 2 0006 Ydieresis
+tm 1000,689,0,1,-2,1 2 0007 trademark
+aq 333,733,0,5,-90,5 2 0010 quotesingle
+space 250 0 0040
+! 333,733,8,9,-26,9 2 0041 exclam
+" 500,733,0,5,-90,5 2 0042 quotedbl
+# 500,692,0,45,46,45 2 0043 numbersign
+sh "
+$ 500,733,113,2,35,2 2 0044 dollar
+Do "
+% 889,710,7,0,-24 2 0045 percent
+& 778,692,18,38,3,38 2 0046 ampersand
+' 278,733,0,30,-28,30 2 0047 quoteright
+( 333,733,106,48,-4,48 2 0050 parenleft
+) 333,733,106,0,48 2 0051 parenright
+* 389,706,0,61,-26,61 2 0052 asterisk
++ 606,504,0,0,-1 0 0053 plus
+, 250,123,143,3,42,3 0 0054 comma
+- 333,281,0,21,31,21 0 0055 hyphen
+hy "
+char173 "
+. 250,112,5,0,-3 0 0056 period
+/ 296,733,119,146,90,68 2 0057 slash
+sl "
+0 500,699,11,30,14,30 2 0060 zero
+1 500,699,3,0,-4 2 0061 one
+2 500,699,3,0,38 2 0062 two
+3 500,699,11,0,28 2 0063 three
+4 500,699,3,28,35,28 2 0064 four
+5 500,693,11,41,36,41 2 0065 five
+6 500,699,11,19,1,19 2 0066 six
+7 500,692,3,52,-3,52 2 0067 seven
+8 500,699,11,19,14,19 2 0070 eight
+9 500,699,11,18,18,18 2 0071 nine
+: 250,458,5,7,6,7 0 0072 colon
+; 250,456,146,19,59,19 0 0073 semicolon
+< 606,516,6,0,-3 0 0074 less
+= 606,378,0,0,-1 0 0075 equal
+> 606,516,6,0,-3 0 0076 greater
+? 500,706,8,0,-64 2 0077 question
+@ 747,706,18,21,23,21 2 0100 at
+at "
+A 722,705,3,5,69,5 2 0101 A
+B 611,692,6,0,24 2 0102 B
+C 667,706,18,34,5,34 2 0103 C
+D 778,692,3,13,22,13 2 0104 D
+E 611,692,3,9,20,9 2 0105 E
+F 556,692,3,42,50,42 2 0106 F
+G 722,706,18,22,0,22 2 0107 G
+H 778,692,3,72,53,68 2 0110 H
+I 333,692,3,71,43,68 2 0111 I
+J 333,692,206,75,85,68 2 0112 J
+K 667,692,3,66,37,66 2 0113 K
+L 556,692,3,17,34,17 2 0114 L
+M 944,692,18,46,69,46 2 0115 M
+N 778,692,11,76,48,68 2 0116 N
+O 778,706,18,20,-3,20 2 0117 O
+P 611,692,3,33,41,33 2 0120 P
+Q 778,706,201,20,-3,20 2 0121 Q
+R 667,692,3,22,41,22 2 0122 R
+S 556,706,18,0,8 2 0123 S
+T 611,692,3,74,-3,68 2 0124 T
+U 778,692,18,70,-38,68 2 0125 U
+V 722,692,8,82,-25,68 2 0126 V
+W 944,700,8,86,-21,68 2 0127 W
+X 722,692,3,62,30,62 2 0130 X
+Y 667,705,3,58,-2,58 2 0131 Y
+Z 667,692,3,20,30,20 2 0132 Z
+[ 333,733,100,43,32,43 2 0133 bracketleft
+lB "
+\ 606,733,0,0,-31 2 0134 backslash
+rs "
+] 333,733,100,32,43,32 2 0135 bracketright
+rB "
+a^ 333,679,0,67,-6,67 2 0136 circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 underscore
+` 278,733,0,30,-28,30 2 0140 quoteleft
+oq "
+a 444,482,11,12,46,12 0 0141 a
+b 463,733,11,20,13,20 2 0142 b
+c 407,482,11,32,25,32 0 0143 c
+d 500,733,11,33,33,33 2 0144 d
+e 389,482,11,35,35,35 0 0145 e
+f 278,733,276,185,212,68 3 0146 f
+g 500,482,276,48,87,48 1 0147 g
+h 500,733,9,21,40,21 2 0150 h
+i 278,712,9,36,16,36 2 0151 i
+j 278,712,276,37,120,37 3 0152 j
+k 444,733,9,55,42,55 2 0153 k
+l 278,733,9,23,14,23 2 0154 l
+m 778,482,9,12,26,12 0 0155 m
+n 556,482,9,8,26,8 0 0156 n
+o 444,482,11,17,33,17 0 0157 o
+p 500,482,276,15,57,15 1 0160 p
+q 463,482,276,19,26,19 1 0161 q
+r 389,482,9,45,24,45 0 0162 r
+s 389,482,11,6,41,6 0 0163 s
+t 333,646,9,27,9,27 2 0164 t
+u 556,482,11,6,18,6 0 0165 u
+v 500,482,11,27,29,27 0 0166 v
+w 722,482,11,27,29,27 0 0167 w
+x 500,482,11,34,41,34 0 0170 x
+y 500,482,276,40,58,40 1 0171 y
+z 444,482,11,22,51,22 0 0172 z
+lC 333,733,100,36,35,36 2 0173 braceleft
+{ "
+ba 606,733,0,0,-225 2 0174 bar
+| "
+rC 333,733,100,35,36,35 2 0175 braceright
+} "
+a~ 333,638,0,107,-13,68 0 0176 tilde
+~ "
+bq 278,120,122,0,23 0 0200 quotesinglbase
+Fo 500,440,0,0,-7 0 0201 guillemotleft
+char171 "
+Fc 500,440,0,0,-13 0 0202 guillemotright
+char187 "
+bu 500,526,0,0,-36 0 0203 bullet
+Fn 500,708,276,20,45,20 3 0204 florin
+f/ 167,699,0,220,220,68 2 0205 fraction
+%0 1000,717,6,0,-22 2 0206 perthousand
+dg 500,692,0,19,2,19 2 0207 dagger
+dd 500,692,162,44,40,44 2 0210 daggerdbl
+en 500,278,0,60,60,60 0 0211 endash
+em 1000,278,0,60,60,60 0 0212 emdash
+fi 528,733,276,24,212,24 3 0214 fi
+fl 545,733,276,25,212,25 3 0215 fl
+.i 278,482,9,13,16,13 0 0220 dotlessi
+ga 333,687,0,27,-36,27 2 0222 grave
+a" 333,730,0,102,4,68 2 0223 hungarumlaut
+a. 333,645,0,0,-125 2 0224 dotaccent
+ab 333,677,0,110,-42,68 2 0225 breve
+ah 333,679,0,126,-54,68 2 0226 caron
+ao 333,708,0,76,-109,68 2 0227 ring
+ho 333,0,207,0,12 0 0230 ogonek
+lq 500,733,0,25,-48,25 2 0231 quotedblleft
+rq 500,733,0,25,-48,25 2 0232 quotedblright
+oe 669,482,11,35,33,35 0 0233 oe
+/l 278,733,9,74,60,68 2 0234 lslash
+Bq 500,120,122,0,7 0 0235 quotedblbase
+OE 1028,706,18,11,-6,11 2 0236 OE
+/L 556,692,3,17,66,17 2 0237 Lslash
+r! 333,467,276,0,35 1 0241 exclamdown
+char161 "
+ct 500,551,96,0,-6 0 0242 cent
+char162 "
+Po 500,708,18,29,48,29 2 0243 sterling
+char163 "
+Cs 500,577,0,36,36,36 0 0244 currency
+char164 "
+Ye 500,699,3,62,15,62 2 0245 yen
+char165 "
+bb 606,733,0,0,-225 2 0246 brokenbar
+char166 "
+sc 500,706,220,13,36,13 2 0247 section
+char167 "
+ad 333,637,0,95,-28,68 0 0250 dieresis
+char168 "
+co 747,706,18,39,39,39 2 0251 copyright
+char169 "
+Of 333,699,0,38,-10,38 2 0252 ordfeminine
+char170 "
+fo 333,440,0,0,-7 0 0253 guilsinglleft
+no 606,378,0,0,-1 0 0254 logicalnot
+char172 "
+\- 606,280,0,0,-1 0 0255 minus
+rg 747,706,18,39,39,39 2 0256 registered
+char174 "
+a- 333,589,0,103,-24,68 0 0257 macron
+char175 "
+de 400,689,0,40,-40,40 2 0260 degree
+char176 "
+char177 606,504,0,0,-1 0 0261 plusminus
+S2 300,699,0,40,37,40 2 0262 twosuperior
+char178 "
+S3 300,699,0,54,22,54 2 0263 threesuperior
+char179 "
+aa 333,687,0,63,-72,63 2 0264 acute
+char180 "
+char181 556,482,226,6,35,6 0 0265 mu
+ps 500,692,224,161,17,68 2 0266 paragraph
+char182 "
+char183 250,312,0,0,-3 0 0267 periodcentered
+ac 333,0,216,0,59 0 0270 cedilla
+char184 "
+S1 300,699,0,35,-11,35 2 0271 onesuperior
+char185 "
+Om 333,699,0,39,-16,39 2 0272 ordmasculine
+char186 "
+fc 333,440,0,0,-13 0 0273 guilsinglright
+14 750,699,2,15,19,15 2 0274 onequarter
+char188 "
+12 750,699,2,21,19,21 2 0275 onehalf
+char189 "
+34 750,699,2,15,15,15 2 0276 threequarters
+char190 "
+r? 500,467,246,0,-7 0 0277 questiondown
+char191 "
+`A 722,897,3,5,69,5 2 0300 Agrave
+char192 "
+'A 722,897,3,5,69,5 2 0301 Aacute
+char193 "
+^A 722,889,3,5,69,5 2 0302 Acircumflex
+char194 "
+~A 722,866,3,5,69,5 2 0303 Atilde
+char195 "
+:A 722,847,3,5,69,5 2 0304 Adieresis
+char196 "
+oA 722,918,3,5,69,5 2 0305 Aring
+char197 "
+AE 941,692,3,11,54,11 2 0306 AE
+char198 "
+,C 667,706,216,34,5,34 2 0307 Ccedilla
+char199 "
+`E 611,897,3,9,20,9 2 0310 Egrave
+char200 "
+'E 611,897,3,9,20,9 2 0311 Eacute
+char201 "
+^E 611,889,3,9,20,9 2 0312 Ecircumflex
+char202 "
+:E 611,847,3,9,20,9 2 0313 Edieresis
+char203 "
+`I 333,897,3,71,43,68 2 0314 Igrave
+char204 "
+'I 333,897,3,123,43,68 2 0315 Iacute
+char205 "
+^I 333,889,3,107,43,68 2 0316 Icircumflex
+char206 "
+:I 333,847,3,135,43,68 2 0317 Idieresis
+char207 "
+-D 778,692,3,13,31,13 2 0320 Eth
+char208 "
+~N 778,866,11,76,48,68 2 0321 Ntilde
+char209 "
+`O 778,897,18,20,-3,20 2 0322 Ograve
+char210 "
+'O 778,897,18,20,-3,20 2 0323 Oacute
+char211 "
+^O 778,889,18,20,-3,20 2 0324 Ocircumflex
+char212 "
+~O 778,866,18,20,-3,20 2 0325 Otilde
+char213 "
+:O 778,847,18,20,-3,20 2 0326 Odieresis
+char214 "
+char215 606,474,0,0,-33 0 0327 multiply
+/O 778,721,39,34,18,34 2 0330 Oslash
+char216 "
+`U 778,897,18,70,-38,68 2 0331 Ugrave
+char217 "
+'U 778,897,18,70,-38,68 2 0332 Uacute
+char218 "
+^U 778,889,18,70,-38,68 2 0333 Ucircumflex
+char219 "
+:U 778,847,18,70,-38,68 2 0334 Udieresis
+char220 "
+'Y 667,897,3,58,-2,58 2 0335 Yacute
+char221 "
+TP 611,692,3,9,41,9 2 0336 Thorn
+char222 "
+ss 500,733,276,38,210,38 3 0337 germandbls
+char223 "
+`a 444,707,11,12,46,12 2 0340 agrave
+char224 "
+'a 444,707,11,20,46,20 2 0341 aacute
+char225 "
+^a 444,699,11,12,46,12 2 0342 acircumflex
+char226 "
+~a 444,650,11,52,46,52 2 0343 atilde
+char227 "
+:a 444,657,11,40,46,40 2 0344 adieresis
+char228 "
+oa 444,728,11,12,46,12 2 0345 aring
+char229 "
+ae 638,482,11,35,49,35 0 0346 ae
+char230 "
+,c 407,482,216,32,25,32 0 0347 ccedilla
+char231 "
+`e 389,707,11,35,35,35 2 0350 egrave
+char232 "
+'e 389,707,11,55,35,55 2 0351 eacute
+char233 "
+^e 389,699,11,59,35,59 2 0352 ecircumflex
+char234 "
+:e 389,657,11,67,35,67 2 0353 edieresis
+char235 "
+`i 278,707,9,43,16,43 2 0354 igrave
+char236 "
+'i 278,707,9,103,16,68 2 0355 iacute
+char237 "
+^i 278,699,9,95,21,68 2 0356 icircumflex
+char238 "
+:i 278,657,9,123,16,68 2 0357 idieresis
+char239 "
+Sd 444,733,11,84,33,68 2 0360 eth
+char240 "
+~n 556,650,9,8,26,8 2 0361 ntilde
+char241 "
+`o 444,707,11,17,33,17 2 0362 ograve
+char242 "
+'o 444,707,11,20,33,20 2 0363 oacute
+char243 "
+^o 444,699,11,17,33,17 2 0364 ocircumflex
+char244 "
+~o 444,650,11,52,33,52 2 0365 otilde
+char245 "
+:o 444,657,11,40,33,40 2 0366 odieresis
+char246 "
+char247 606,504,0,0,-1 0 0367 divide
+/o 444,510,24,66,68,66 0 0370 oslash
+char248 "
+`u 556,707,11,6,18,6 2 0371 ugrave
+char249 "
+'u 556,707,11,6,18,6 2 0372 uacute
+char250 "
+^u 556,699,11,6,18,6 2 0373 ucircumflex
+char251 "
+:u 556,657,11,6,18,6 2 0374 udieresis
+char252 "
+'y 500,707,276,40,58,40 3 0375 yacute
+char253 "
+Tp 500,733,276,0,89 3 0376 thorn
+char254 "
+:y 500,657,276,40,58,40 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/PR b/gnu/usr.bin/groff/devices/devps/PR
new file mode 100644
index 000000000000..4dd5626d4e97
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/PR
@@ -0,0 +1,456 @@
+name PR
+internalname Palatino-Roman
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -92
+A ' -74
+A Y -111
+A W -74
+A V -111
+A T -74
+F . -92
+F , -92
+F A -74
+L y -55
+L ' -74
+L Y -92
+L W -74
+L V -92
+L T -74
+P . -129
+P , -129
+P A -92
+R y -37
+R Y -37
+R W -37
+R V -55
+R T -37
+T y -90
+T w -90
+T u -90
+T ; -55
+T s -90
+T r -90
+T . -74
+T o -92
+T i -55
+T - -55
+T hy -55
+T char173 -55
+T e -92
+T , -74
+T : -55
+T c -111
+T a -92
+T O -18
+T A -74
+V y -92
+V u -92
+V ; -55
+V r -92
+V . -129
+V o -111
+V i -55
+V - -74
+V hy -74
+V char173 -74
+V e -111
+V , -129
+V : -55
+V a -92
+V A -111
+W y -50
+W u -50
+W ; -18
+W r -74
+W . -92
+W o -92
+W i -55
+W - -55
+W hy -55
+W char173 -55
+W e -92
+W , -92
+W : -18
+W a -92
+W A -92
+Y v -90
+Y u -90
+Y ; -74
+Y q -90
+Y . -111
+Y p -111
+Y o -92
+Y i -55
+Y - -92
+Y hy -92
+Y char173 -92
+Y e -92
+Y , -111
+Y : -74
+Y a -92
+Y A -92
+f ' 55
+f f -18
+1 1 -55
+` ` -37
+` oq -37
+oq ` -37
+oq oq -37
+' ' -37
+r u -8
+r ' 74
+r q -18
+r . -74
+r o -18
+r - -18
+r hy -18
+r char173 -18
+r h -18
+r g -18
+r e -18
+r d -18
+r , -74
+r c -18
+v . -111
+v , -111
+w . -92
+w , -92
+y . -111
+y , -111
+charset
+ha 606,689 2 0000 asciicircum
+ti 606,347 0 0001 asciitilde
+vS 525,908,20 2 0002 Scaron
+vZ 667,908,3 2 0003 Zcaron
+vs 424,685,20 2 0004 scaron
+vz 500,685,3 2 0005 zcaron
+:Y 667,868,3 2 0006 Ydieresis
+tm 979,689 2 0007 trademark
+aq 208,709 2 0010 quotesingle
+space 250 0 0040
+! 278,694,5 2 0041 exclam
+" 371,709 2 0042 quotedbl
+# 500,684 2 0043 numbersign
+sh "
+$ 500,731,116 2 0044 dollar
+Do "
+% 840,709,20 2 0045 percent
+& 778,689,20 2 0046 ampersand
+' 278,709 2 0047 quoteright
+( 333,726,215 2 0050 parenleft
+) 333,726,215 2 0051 parenright
+* 389,689 2 0052 asterisk
++ 606,512 0 0053 plus
+, 250,123,155 0 0054 comma
+- 333,287 0 0055 hyphen
+hy "
+char173 "
+. 250,111,5 0 0056 period
+/ 606,726,119 2 0057 slash
+sl "
+0 500,689,20 2 0060 zero
+1 500,694,3 2 0061 one
+2 500,689,3 2 0062 two
+3 500,689,20 2 0063 three
+4 500,694,3 2 0064 four
+5 500,689,20 2 0065 five
+6 500,689,20 2 0066 six
+7 500,689,3 2 0067 seven
+8 500,689,20 2 0070 eight
+9 500,689,20 2 0071 nine
+: 250,456,5 0 0072 colon
+; 250,456,153 0 0073 semicolon
+< 606,522 0 0074 less
+= 606,386 0 0075 equal
+> 606,522 0 0076 greater
+? 444,694,5 2 0077 question
+@ 747,694,20 2 0100 at
+at "
+A 778,700,3 2 0101 A
+B 611,692,3 2 0102 B
+C 709,709,20 2 0103 C
+D 774,692,3 2 0104 D
+E 611,692,3 2 0105 E
+F 556,692,3 2 0106 F
+G 763,709,20 2 0107 G
+H 832,692,3 2 0110 H
+I 337,692,3 2 0111 I
+J 333,692,194 2 0112 J
+K 726,692,3 2 0113 K
+L 611,692,3 2 0114 L
+M 946,692,13 2 0115 M
+N 831,692,20 2 0116 N
+O 786,709,20 2 0117 O
+P 604,692,3 2 0120 P
+Q 786,709,176 2 0121 Q
+R 668,692,3 2 0122 R
+S 525,709,20 2 0123 S
+T 613,692,3 2 0124 T
+U 778,692,20 2 0125 U
+V 722,692,9 2 0126 V
+W 1000,700,9 2 0127 W
+X 667,700,3 2 0130 X
+Y 667,704,3 2 0131 Y
+Z 667,692,3 2 0132 Z
+[ 333,726,184 2 0133 bracketleft
+lB "
+\ 606,726 2 0134 backslash
+rs "
+] 333,726,184 2 0135 bracketright
+rB "
+a^ 333,677 2 0136 circumflex
+^ "
+_ 500,0,125 0 0137 underscore
+` 278,709 2 0140 quoteleft
+oq "
+a 500,469,12 0 0141 a
+b 553,726,12 2 0142 b
+c 444,469,20 0 0143 c
+d 611,726,12 2 0144 d
+e 479,469,20 0 0145 e
+f 333,728,3 2 0146 f
+g 556,469,283 1 0147 g
+h 582,726,3 2 0150 h
+i 291,687,3 2 0151 i
+j 234,688,283 3 0152 j
+k 556,726,12 2 0153 k
+l 291,726,3 2 0154 l
+m 883,469,3 0 0155 m
+n 582,469,3 0 0156 n
+o 546,469,20 0 0157 o
+p 601,469,281 1 0160 p
+q 560,469,281 1 0161 q
+r 395,469,3 0 0162 r
+s 424,469,20 0 0163 s
+t 326,621,12 2 0164 t
+u 603,469,12 0 0165 u
+v 565,459,7 0 0166 v
+w 834,469,7 0 0167 w
+x 516,469,3 0 0170 x
+y 556,459,283 1 0171 y
+z 500,462,3 0 0172 z
+lC 333,726,175 2 0173 braceleft
+{ "
+ba 606,726 2 0174 bar
+| "
+rC 333,726,175 2 0175 braceright
+} "
+a~ 333,640 2 0176 tilde
+~ "
+bq 278,110,153 0 0200 quotesinglbase
+Fo 500,428 0 0201 guillemotleft
+char171 "
+Fc 500,428 0 0202 guillemotright
+char187 "
+bu 606,516 0 0203 bullet
+Fn 500,706,262 2 0204 florin
+f/ 167,689 2 0205 fraction
+%0 1144,709,20 2 0206 perthousand
+dg 500,694,5 2 0207 dagger
+dd 500,694,249 2 0210 daggerdbl
+en 500,277 0 0211 endash
+em 1000,277 0 0212 emdash
+fi 605,728,3 2 0214 fi
+fl 608,728,3 2 0215 fl
+.i 287,469,3 0 0220 dotlessi
+ga 333,677 2 0222 grave
+a" 380,687 2 0223 hungarumlaut
+a. 250,637 2 0224 dotaccent
+ab 333,664 2 0225 breve
+ah 333,677 2 0226 caron
+ao 333,696 2 0227 ring
+ho 313,0,165 0 0230 ogonek
+lq 500,709 2 0231 quotedblleft
+rq 500,709 2 0232 quotedblright
+oe 827,469,20 0 0233 oe
+/l 291,726,3 2 0234 lslash
+Bq 500,110,153 0 0235 quotedblbase
+OE 998,709,20 2 0236 OE
+/L 611,692,3 2 0237 Lslash
+r! 278,469,225 0 0241 exclamdown
+char161 "
+ct 500,562,101 0 0242 cent
+char162 "
+Po 500,694,13 2 0243 sterling
+char163 "
+Cs 500,531 0 0244 currency
+char164 "
+Ye 500,701,3 2 0245 yen
+char165 "
+bb 606,726 2 0246 brokenbar
+char166 "
+sc 500,709,219 2 0247 section
+char167 "
+ad 333,637 2 0250 dieresis
+char168 "
+co 747,706,18 2 0251 copyright
+char169 "
+Of 333,709 2 0252 ordfeminine
+char170 "
+fo 331,428 0 0253 guilsinglleft
+no 606,386 0 0254 logicalnot
+char172 "
+\- 606,289 0 0255 minus
+rg 747,706,18 2 0256 registered
+char174 "
+a- 333,591 0 0257 macron
+char175 "
+de 400,689 2 0260 degree
+char176 "
+char177 606,512 0 0261 plusminus
+S2 300,689 2 0262 twosuperior
+char178 "
+S3 300,689 2 0263 threesuperior
+char179 "
+aa 333,677 2 0264 acute
+char180 "
+char181 603,469,236 0 0265 mu
+ps 628,694,150 2 0266 paragraph
+char182 "
+char183 250,319 0 0267 periodcentered
+ac 333,0,225 0 0270 cedilla
+char184 "
+S1 300,692 2 0271 onesuperior
+char185 "
+Om 333,709 2 0272 ordmasculine
+char186 "
+fc 331,428 0 0273 guilsinglright
+14 750,692,3 2 0274 onequarter
+char188 "
+12 750,692,3 2 0275 onehalf
+char189 "
+34 750,689,3 2 0276 threequarters
+char190 "
+r? 444,469,231 0 0277 questiondown
+char191 "
+`A 778,908,3 2 0300 Agrave
+char192 "
+'A 778,908,3 2 0301 Aacute
+char193 "
+^A 778,908,3 2 0302 Acircumflex
+char194 "
+~A 778,871,3 2 0303 Atilde
+char195 "
+:A 778,868,3 2 0304 Adieresis
+char196 "
+oA 778,927,3 2 0305 Aring
+char197 "
+AE 944,692,3 2 0306 AE
+char198 "
+,C 709,709,225 2 0307 Ccedilla
+char199 "
+`E 611,908,3 2 0310 Egrave
+char200 "
+'E 611,908,3 2 0311 Eacute
+char201 "
+^E 611,908,3 2 0312 Ecircumflex
+char202 "
+:E 611,868,3 2 0313 Edieresis
+char203 "
+`I 337,908,3 2 0314 Igrave
+char204 "
+'I 337,908,3 2 0315 Iacute
+char205 "
+^I 337,908,3 2 0316 Icircumflex
+char206 "
+:I 337,868,3 2 0317 Idieresis
+char207 "
+-D 774,692,3 2 0320 Eth
+char208 "
+~N 831,871,20 2 0321 Ntilde
+char209 "
+`O 786,908,20 2 0322 Ograve
+char210 "
+'O 786,908,20 2 0323 Oacute
+char211 "
+^O 786,908,20 2 0324 Ocircumflex
+char212 "
+~O 786,883,20 2 0325 Otilde
+char213 "
+:O 786,868,20 2 0326 Odieresis
+char214 "
+char215 606,474 0 0327 multiply
+/O 833,709,20 2 0330 Oslash
+char216 "
+`U 778,908,20 2 0331 Ugrave
+char217 "
+'U 778,908,20 2 0332 Uacute
+char218 "
+^U 778,908,20 2 0333 Ucircumflex
+char219 "
+:U 778,868,20 2 0334 Udieresis
+char220 "
+'Y 667,908,3 2 0335 Yacute
+char221 "
+TP 604,692,3 2 0336 Thorn
+char222 "
+ss 556,731,9 2 0337 germandbls
+char223 "
+`a 500,697,12 2 0340 agrave
+char224 "
+'a 500,697,12 2 0341 aacute
+char225 "
+^a 500,697,12 2 0342 acircumflex
+char226 "
+~a 500,652,12 2 0343 atilde
+char227 "
+:a 500,657,12 2 0344 adieresis
+char228 "
+oa 500,716,12 2 0345 aring
+char229 "
+ae 758,469,20 0 0346 ae
+char230 "
+,c 444,469,225 0 0347 ccedilla
+char231 "
+`e 479,697,20 2 0350 egrave
+char232 "
+'e 479,697,20 2 0351 eacute
+char233 "
+^e 479,697,20 2 0352 ecircumflex
+char234 "
+:e 479,657,20 2 0353 edieresis
+char235 "
+`i 287,697,3 2 0354 igrave
+char236 "
+'i 287,697,3 2 0355 iacute
+char237 "
+^i 287,697,3 2 0356 icircumflex
+char238 "
+:i 287,657,3 2 0357 idieresis
+char239 "
+Sd 546,728,20 2 0360 eth
+char240 "
+~n 582,652,3 2 0361 ntilde
+char241 "
+`o 546,697,20 2 0362 ograve
+char242 "
+'o 546,697,20 2 0363 oacute
+char243 "
+^o 546,697,20 2 0364 ocircumflex
+char244 "
+~o 546,652,20 2 0365 otilde
+char245 "
+:o 546,657,20 2 0366 odieresis
+char246 "
+char247 606,512 0 0367 divide
+/o 556,474,23 0 0370 oslash
+char248 "
+`u 603,697,12 2 0371 ugrave
+char249 "
+'u 603,697,12 2 0372 uacute
+char250 "
+^u 603,697,12 2 0373 ucircumflex
+char251 "
+:u 603,657,12 2 0374 udieresis
+char252 "
+'y 556,697,283 3 0375 yacute
+char253 "
+Tp 601,726,281 3 0376 thorn
+char254 "
+:y 556,657,283 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/S b/gnu/usr.bin/groff/devices/devps/S
new file mode 100644
index 000000000000..4c58752ed3a8
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/S
@@ -0,0 +1,227 @@
+name S
+internalname Symbol
+special
+spacewidth 250
+charset
+space 250 0 0040
+! 333,672,17 3 0041 exclam
+fa 713,705 3 0042 universal
+# 500,673,16 3 0043 numbersign
+sh "
+te 549,707 3 0044 existential
+% 833,655,36 3 0045 percent
+& 778,661,18 3 0046 ampersand
+st 439,500,17 3 0047 suchthat
+( 333,673,191 3 0050 parenleft
+) 333,673,191 3 0051 parenright
+** 500,551 3 0052 asteriskmath
++ 549,533 3 0053 plus
+pl "
+, 250,104,152 3 0054 comma
+\- 549,288 3 0055 minus
+mi "
+. 250,95,17 3 0056 period
+/ 278,646,18 3 0057 slash
+sl "
+0 500,685,17 3 0060 zero
+1 500,673 3 0061 one
+2 500,686 3 0062 two
+3 500,685,17 3 0063 three
+4 500,685 3 0064 four
+5 500,685,17 3 0065 five
+6 500,685,17 3 0066 six
+7 500,673,16 3 0067 seven
+8 500,685,18 3 0070 eight
+9 500,685,18 3 0071 nine
+: 278,460,17 3 0072 colon
+; 278,460,152 3 0073 semicolon
+< 549,522 3 0074 less
+= 549,390 3 0075 equal
+eq "
+> 549,522 3 0076 greater
+? 444,686,17 3 0077 question
+=~ 549,475 3 0100 congruent
+*A 722,673 3 0101 Alpha
+*B 667,673 3 0102 Beta
+*X 722,673 3 0103 Chi
+*D 612,688 3 0104 Delta
+*E 611,673 3 0105 Epsilon
+*F 763,673 3 0106 Phi
+*G 603,673 3 0107 Gamma
+*Y 722,673 3 0110 Eta
+*I 333,673 3 0111 Iota
++h 631,689,18 3 0112 theta1
+*K 722,673 3 0113 Kappa
+*L 686,688 3 0114 Lambda
+*M 889,673 3 0115 Mu
+*N 722,673,8 3 0116 Nu
+*O 722,685,17 3 0117 Omicron
+*P 768,673 3 0120 Pi
+*H 741,685,17 3 0121 Theta
+*R 556,673 3 0122 Rho
+*S 592,673 3 0123 Sigma
+*T 611,673 3 0124 Tau
+--- 690,673 3 0125 Upsilon
+ts 439,500,233 3 0126 sigma1
+*W 768,688 3 0127 Omega
+*C 645,673 3 0130 Xi
+*Q 795,684 3 0131 Psi
+*Z 611,673 3 0132 Zeta
+[ 333,674,155 3 0133 bracketleft
+lB "
+3d 863,478 3 0134 therefore
+tf "
+] 333,674,155 3 0135 bracketright
+rB "
+pp 658,674 3 0136 perpendicular
+_ 500,0,252 3 0137 underscore
+rn 500,917 3 0140 radicalex
+*a 631,500,18 3 0141 alpha
+*b 549,741,223 3 0142 beta
+*x 549,499,231 3 0143 chi
+*d 494,740,19 3 0144 delta
+*e 439,502,19 3 0145 epsilon
+*f 521,671,224 3 0146 phi
+*g 411,499,225 3 0147 gamma
+*y 603,514,202 3 0150 eta
+*i 329,503,17 3 0151 iota
++f 603,499,224 3 0152 phi1
+*k 549,501 3 0153 kappa
+*l 549,739,17 3 0154 lambda
+char181 576,500,223 3 0155 mu
+*m "
+*n 521,507,16 3 0156 nu
+*o 549,499,19 3 0157 omicron
+*p 549,487,19 3 0160 pi
+*h 521,690,17 3 0161 theta
+*r 549,499,230 3 0162 rho
+*s 603,500,21 3 0163 sigma
+*t 439,500,19 3 0164 tau
+*u 576,507,18 3 0165 upsilon
++p 713,583,18 3 0166 omega1
+*w 686,500,17 3 0167 omega
+*c 493,766,224 3 0170 xi
+*q 686,500,228 3 0171 psi
+*z 494,756,225 3 0172 zeta
+lC 480,673,183 3 0173 braceleft
+{ "
+ba 200,673,177 3 0174 bar
+| "
+rC 480,673,183 3 0175 braceright
+} "
+ap 549,307 3 0176 similar
+*U 620,685 3 0241 Upsilon1
+fm 247,735 3 0242 minute
+<= 549,639 3 0243 lessequal
+f/ 167,677,12 3 0244 fraction
+if 713,404 3 0245 infinity
+Fn 500,686,193 3 0246 florin
+CL 753,533,26 3 0247 club
+DI 753,550,36 3 0250 diamond
+HE 753,532,33 3 0251 heart
+SP 753,548,36 3 0252 spade
+<> 1042,511,15 3 0253 arrowboth
+<- 987,511,15 3 0254 arrowleft
+ua 603,910 3 0255 arrowup
+arrowverttp "
+-> 987,511,15 3 0256 arrowright
+da 603,888,22 3 0257 arrowdown
+arrowvertbt "
+de 400,685 3 0260 degree
+char176 "
+char177 549,645 3 0261 plusminus
++- "
+sd 411,737 3 0262 second
+>= 549,639 3 0263 greaterequal
+char215 549,524 3 0264 multiply
+mu "
+pt 713,404 3 0265 proportional
+pd 494,746,20 3 0266 partialdiff
+bu 460,473 3 0267 bullet
+char247 549,456 3 0270 divide
+di "
+!= 549,549,25 3 0271 notequal
+== 549,443 3 0272 equivalence
+~~ 549,394 3 0273 approxequal
+~= "
+--- 1000,95,17 3 0274 ellipsis
+arrowvertex 603,1010,120 3 0275 arrowvertex
+--- 1000,276 3 0276 arrowhorizex
+CR 658,629,16 3 0277 carriagereturn
+Ah 823,658,18 3 0300 aleph
+Im 686,740,53 3 0301 Ifraktur
+Re 795,734,15 3 0302 Rfraktur
+wp 987,573,211 3 0303 weierstrass
+c* 768,673,17 3 0304 circlemultiply
+c+ 768,675,15 3 0305 circleplus
+es 823,719,24 3 0306 emptyset
+ca 768,509 3 0307 intersection
+cu 768,492,17 3 0310 union
+sp 713,470 3 0311 propersuperset
+ip 713,470,125 3 0312 reflexsuperset
+--- 713,540,70 3 0313 notsubset
+sb 713,470 3 0314 propersubset
+ib 713,470,125 3 0315 reflexsubset
+mo 713,468 3 0316 element
+nm 713,555,58 3 0317 notelement
+/_ 768,673 3 0320 angle
+gr 713,718,19 3 0321 gradient
+--- 790,673,17 3 0322 registerserif
+--- 790,675,15 3 0323 copyrightserif
+--- 890,673 3 0324 trademarkserif
+product 823,751,101 3 0325 product
+sr 549,917,38 3 0326 radical
+md 250,310 3 0327 dotmath
+no 713,288 3 0330 logicalnot
+char172 "
+AN 603,454 3 0331 logicaland
+OR 603,477 3 0332 logicalor
+hA 1042,510,20 3 0333 arrowdblboth
+lA 987,513,15 3 0334 arrowdblleft
+uA 603,911 3 0335 arrowdblup
+rA 987,508,20 3 0336 arrowdblright
+dA 603,890,19 3 0337 arrowdbldown
+lz 494,745 3 0340 lozenge
+la 329,746,198 3 0341 angleleft
+--- 790,670,20 3 0342 registersans
+--- 790,675,15 3 0343 copyrightsans
+--- 786,673 3 0344 trademarksans
+sum 713,752,108 3 0345 summation
+parenlefttp 384,926,293 3 0346 parenlefttp
+parenleftex 384,920,80 3 0347 parenleftex
+parenleftbt 384,920,293 3 0350 parenleftbt
+bracketlefttp 384,925,75 3 0351 bracketlefttp
+lc "
+bracketleftex 384,925,75 3 0352 bracketleftex
+bracketleftbt 384,925,75 3 0353 bracketleftbt
+lf "
+bracelefttp 494,925,75 3 0354 bracelefttp
+lt "
+braceleftmid 494,925,75 3 0355 braceleftmid
+lk "
+braceleftbt 494,925,75 3 0356 braceleftbt
+lb "
+braceex 494,925,75 3 0357 braceex
+bracerightex "
+braceleftex "
+barex "
+bv "
+ra 329,746,198 3 0361 angleright
+is 274,916,107,67,52,-10 3 0362 integral
+--- 686,921,83 3 0363 integraltp
+--- 686,975,88 3 0364 integralex
+--- 686,921,81 3 0365 integralbt
+parenrighttp 384,926,293 3 0366 parenrighttp
+parenrightex 384,920,80 3 0367 parenrightex
+parenrightbt 384,920,293 3 0370 parenrightbt
+bracketrighttp 384,925,75 3 0371 bracketrighttp
+rc "
+bracketrightex 384,925,75 3 0372 bracketrightex
+bracketrightbt 384,925,75 3 0373 bracketrightbt
+rf "
+bracerighttp 494,925,75 3 0374 bracerighttp
+rt "
+bracerightmid 494,925,75 3 0375 bracerightmid
+rk "
+bracerightbt 494,925,75 3 0376 bracerightbt
+rb "
diff --git a/gnu/usr.bin/groff/devices/devps/SS b/gnu/usr.bin/groff/devices/devps/SS
new file mode 100644
index 000000000000..02b999c17b6d
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/SS
@@ -0,0 +1,194 @@
+name SS
+internalname Symbol-Slanted
+special
+slant 15.5
+spacewidth 223
+charset
+space 223 0 0040
+--- 296,599,15,137,-72,99 3 0041 exclam
+--- 635,627,0,216,-173,99 3 0042 universal
+--- 445,599,15,162,-21,99 3 0043 numbersign
+--- 489,629,0,183,28,99 3 0044 existential
+--- 741,583,32,75,-97,75 3 0045 percent
+--- 692,589,16,103,-18,99 3 0046 ampersand
+--- 391,444,15,109,6,99 3 0047 suchthat
+--- 296,599,170,203,-39,99 3 0050 parenleft
+--- 296,600,170,93,72,93 3 0051 parenright
+--- 445,490,0,105,-76,99 3 0052 asteriskmath
+--- 489,474,0,123,-26,99 3 0053 plus
+--- 223,93,136,10,41,10 3 0054 comma
+--- 489,256,0,117,-24,99 3 0055 minus
+--- 223,85,15,1,-20,1 3 0056 period
+--- 247,575,15,208,55,99 3 0057 slash
+--- 445,610,15,142,-40,99 3 0060 zero
+--- 445,599,0,56,-57,56 3 0061 one
+--- 445,611,0,129,28,99 3 0062 two
+--- 445,611,16,115,-6,99 3 0063 three
+--- 445,610,0,135,-8,99 3 0064 four
+--- 445,610,15,188,14,99 3 0065 five
+--- 445,610,16,193,-37,99 3 0066 six
+--- 445,599,15,190,-101,99 3 0067 seven
+--- 445,611,16,141,-32,99 3 0070 eight
+--- 445,609,15,140,-2,99 3 0071 nine
+--- 247,409,15,89,-31,89 3 0072 colon
+--- 247,409,136,99,17,99 3 0073 semicolon
+--- 489,464,0,171,-37,99 3 0074 less
+--- 489,347,0,147,1,99 3 0075 equal
+--- 489,464,0,108,27,99 3 0076 greater
+--- 395,610,15,172,-113,99 3 0077 question
+--- 489,423,0,158,40,99 3 0100 congruent
+--- 643,599,0,21,47,21 3 0101 Alpha
+--- 594,598,0,101,24,99 3 0102 Beta
+--- 643,599,0,205,58,99 3 0103 Chi
+--- 545,612,0,46,45,46 3 0104 Delta
+--- 544,599,0,194,22,99 3 0105 Epsilon
+--- 679,598,0,132,-55,99 3 0106 Phi
+--- 537,599,0,227,19,99 3 0107 Gamma
+--- 643,599,0,243,15,99 3 0110 Eta
+--- 296,599,0,222,22,99 3 0111 Iota
++h 562,614,15,133,-58,99 3 0112 theta1
+--- 643,598,0,185,19,99 3 0113 Kappa
+--- 611,612,0,49,45,49 3 0114 Lambda
+--- 791,599,0,233,22,99 3 0115 Mu
+--- 643,599,7,234,24,99 3 0116 Nu
+--- 643,610,15,154,-62,99 3 0117 Omicron
+--- 684,599,0,213,28,99 3 0120 Pi
+--- 659,610,15,138,-62,99 3 0121 Theta
+--- 495,599,0,200,25,99 3 0122 Rho
+--- 527,599,0,186,45,99 3 0123 Sigma
+--- 544,599,0,229,-109,99 3 0124 Tau
+--- 614,599,0,240,-125,99 3 0125 Upsilon
+ts 391,445,208,151,-28,99 3 0126 sigma1
+--- 684,612,0,126,20,99 3 0127 Omega
+--- 574,598,0,176,14,99 3 0130 Xi
+--- 708,608,0,227,-138,99 3 0131 Psi
+--- 544,599,0,231,11,99 3 0132 Zeta
+--- 296,599,138,207,16,99 3 0133 bracketleft
+--- 768,426,0,0,-110 3 0134 therefore
+--- 296,599,138,159,64,99 3 0135 bracketright
+--- 586,600,0,60,37,60 3 0136 perpendicular
+--- 445,0,224,0,122 3 0137 underscore
+--- 445,816,0,829,-622,99 3 0140 radicalex
+*a 562,445,15,146,-34,99 3 0141 alpha
+*b 489,659,198,139,57,99 3 0142 beta
+*x 489,445,206,134,98,99 3 0143 chi
+*d 440,658,16,181,-33,99 3 0144 delta
+*e 391,447,17,127,1,99 3 0145 epsilon
+*f 464,596,200,103,-28,99 3 0146 phi
+*g 366,444,200,252,-42,99 3 0147 gamma
+*y 537,457,180,68,-50,68 3 0150 eta
+*i 293,448,16,53,-47,53 3 0151 iota
++f 537,444,199,117,-42,99 3 0152 phi1
+*k 489,447,0,182,-56,99 3 0153 kappa
+*l 489,658,16,91,29,91 3 0154 lambda
+*m 513,445,198,70,68,70 3 0155 mu
+*n 464,451,15,134,-69,99 3 0156 nu
+*o 489,444,17,87,-36,87 3 0157 omicron
+*p 489,433,18,160,-8,99 3 0160 pi
+*h 464,614,16,140,-53,99 3 0161 theta
+*r 489,444,205,82,69,82 3 0162 rho
+*s 537,445,19,175,-37,99 3 0163 sigma
+*t 391,445,16,170,-45,99 3 0164 tau
+*u 513,451,15,95,-55,95 3 0165 upsilon
++p 635,519,15,173,-28,99 3 0166 omega1
+*w 611,445,16,126,-35,99 3 0167 omega
+*c 439,681,200,126,-20,99 3 0170 xi
+*q 611,445,203,198,-91,99 3 0171 psi
+*z 440,673,200,190,-50,99 3 0172 zeta
+--- 427,599,163,163,-66,99 3 0173 braceleft
+--- 178,599,158,179,41,99 3 0174 bar
+--- 427,599,163,67,31,67 3 0175 braceright
+--- 489,273,0,110,-28,99 3 0176 similar
+--- 552,609,0,208,-84,99 3 0241 Upsilon1
+--- 220,654,0,223,-106,99 3 0242 minute
+--- 489,569,0,206,24,99 3 0243 lessequal
+--- 149,603,11,391,214,99 3 0244 fraction
+--- 635,360,0,107,-41,99 3 0245 infinity
+--- 445,612,172,219,86,99 3 0246 florin
+--- 670,474,23,25,-69,25 3 0247 club
+--- 670,490,32,0,-148 3 0250 diamond
+--- 670,473,29,59,-155,59 3 0251 heart
+--- 670,488,32,0,-82 3 0252 spade
+--- 927,455,13,103,-40,99 3 0253 arrowboth
+--- 878,455,13,87,-47,87 3 0254 arrowleft
+--- 537,810,0,204,-173,99 3 0255 arrowup
+--- 878,455,13,94,-55,94 3 0256 arrowright
+--- 537,790,20,85,-54,85 3 0257 arrowdown
+--- 356,609,0,160,-137,99 3 0260 degree
+--- 489,574,0,154,41,99 3 0261 plusminus
+--- 366,656,0,244,-100,99 3 0262 second
+--- 489,569,0,143,24,99 3 0263 greaterequal
+--- 489,466,0,170,22,99 3 0264 multiply
+--- 635,360,0,82,-40,82 3 0265 proportional
+--- 440,664,18,152,-12,99 3 0266 partialdiff
+--- 409,421,0,95,-68,95 3 0267 bullet
+--- 489,406,0,119,-24,99 3 0270 divide
+--- 489,489,22,148,-1,99 3 0271 notequal
+--- 489,394,0,163,15,99 3 0272 equivalence
+--- 489,351,0,133,-7,99 3 0273 approxequal
+--- 890,85,15,0,-57 3 0274 ellipsis
+--- 537,899,107,92,-166,92 3 0275 arrowvertex
+--- 890,246,0,171,42,99 3 0276 arrowhorizex
+--- 586,560,14,174,10,99 3 0277 carriagereturn
+--- 732,586,16,58,-109,58 3 0300 aleph
+--- 611,659,47,123,24,99 3 0301 Ifraktur
+--- 708,653,13,175,-21,99 3 0302 Rfraktur
+--- 878,510,188,50,-62,50 3 0303 weierstrass
+--- 684,599,15,124,-64,99 3 0304 circlemultiply
+--- 684,601,13,125,-65,99 3 0305 circleplus
+--- 732,640,21,202,12,99 3 0306 emptyset
+--- 684,453,0,80,14,80 3 0307 intersection
+--- 684,438,15,154,-60,99 3 0310 union
+--- 635,418,0,90,32,90 3 0311 propersuperset
+--- 635,418,111,89,67,89 3 0312 reflexsuperset
+--- 635,481,62,159,-37,99 3 0313 notsubset
+--- 635,418,0,159,-37,99 3 0314 propersubset
+--- 635,418,111,159,34,99 3 0315 reflexsubset
+--- 635,417,0,0,-43 3 0316 element
+--- 635,494,52,0,-24 3 0317 notelement
+--- 684,599,0,199,27,99 3 0320 angle
+--- 635,639,17,220,-181,99 3 0321 gradient
+--- 703,596,18,110,-70,99 3 0322 registerserif
+--- 703,601,13,113,-72,99 3 0323 copyrightserif
+--- 792,599,0,205,-119,99 3 0324 trademarkserif
+--- 732,668,90,238,56,99 3 0325 product
+--- 489,816,34,272,-84,99 3 0326 radical
+--- 223,276,0,52,-81,52 3 0327 dotmath
+--- 635,256,0,100,-28,99 3 0330 logicalnot
+--- 537,404,0,32,29,32 3 0331 logicaland
+--- 537,424,0,152,-101,99 3 0332 logicalor
+--- 927,454,18,101,-42,99 3 0333 arrowdblboth
+--- 878,457,13,114,-46,99 3 0334 arrowdblleft
+--- 537,811,0,201,-102,99 3 0335 arrowdblup
+--- 878,452,18,89,-21,89 3 0336 arrowdblright
+--- 537,792,17,152,-53,99 3 0337 arrowdbldown
+--- 440,663,0,129,-71,99 3 0340 lozenge
+--- 293,664,176,229,-48,99 3 0341 angleleft
+--- 703,596,18,110,-70,99 3 0342 registersans
+--- 703,601,13,111,-70,99 3 0343 copyrightsans
+--- 700,599,0,182,-129,99 3 0344 trademarksans
+--- 635,669,96,171,65,99 3 0345 summation
+--- 342,824,261,350,96,99 3 0346 parenlefttp
+--- 342,823,76,46,38,46 3 0347 parenleftex
+--- 342,824,261,47,-63,47 3 0350 parenleftbt
+--- 342,824,71,268,72,99 3 0351 bracketlefttp
+--- 342,823,70,13,72,13 3 0352 bracketleftex
+--- 342,824,71,14,72,14 3 0353 bracketleftbt
+--- 440,824,67,258,-108,99 3 0354 bracelefttp
+--- 440,832,76,96,-76,96 3 0355 braceleftmid
+--- 440,824,62,94,-169,94 3 0356 braceleftbt
+--- 440,832,71,96,-107,96 3 0357 braceex
+--- 293,664,176,102,79,99 3 0361 angleright
+--- 244,815,95,305,63,99 3 0362 integral
+--- 611,820,74,312,-222,99 3 0363 integraltp
+--- 611,868,78,79,-221,79 3 0364 integralex
+--- 611,820,72,64,20,64 3 0365 integralbt
+--- 342,824,261,206,-223,99 3 0366 parenrighttp
+--- 342,823,76,365,-281,99 3 0367 parenrightex
+--- 342,824,261,365,80,99 3 0370 parenrightbt
+--- 342,824,71,285,-199,99 3 0371 bracketrighttp
+--- 342,823,70,285,-200,99 3 0372 bracketrightex
+--- 342,824,71,285,54,99 3 0373 bracketrightbt
+--- 440,824,67,35,-108,35 3 0374 bracerighttp
+--- 440,832,76,127,-105,99 3 0375 bracerightmid
+--- 440,824,62,94,54,94 3 0376 bracerightbt
diff --git a/gnu/usr.bin/groff/devices/devps/TB b/gnu/usr.bin/groff/devices/devps/TB
new file mode 100644
index 000000000000..9dae3ad182ce
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/TB
@@ -0,0 +1,533 @@
+name TB
+internalname Times-Bold
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -90
+A v -100
+A u -50
+A ' -74
+A p -25
+A Y -100
+A W -130
+A V -145
+A U -50
+A T -95
+A Q -45
+A O -45
+A G -55
+A C -55
+B U -10
+B A -30
+D . -20
+D Y -40
+D W -40
+D V -40
+D A -35
+F . -110
+F o -25
+F e -25
+F , -92
+F a -25
+F A -90
+J u -15
+J . -20
+J o -15
+J e -15
+J a -15
+J A -30
+K y -45
+K u -15
+K o -25
+K e -25
+K O -30
+L y -55
+L ' -110
+L rq -20
+L Y -92
+L W -92
+L V -92
+L T -92
+N A -20
+O Y -50
+O X -40
+O W -50
+O V -50
+O T -40
+O A -40
+P . -110
+P o -20
+P e -20
+P , -92
+P a -10
+P A -74
+Q . -20
+Q U -10
+R Y -35
+R W -35
+R V -55
+R U -30
+R T -40
+R O -30
+T y -74
+T w -74
+T u -92
+T ; -74
+T r -74
+T . -90
+T o -92
+T i -18
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -74
+T : -74
+T a -92
+T O -18
+T A -90
+U . -50
+U , -50
+U A -60
+V u -92
+V ; -92
+V . -145
+V o -100
+V i -37
+V - -74
+V hy -74
+V char173 -74
+V e -100
+V , -129
+V : -92
+V a -92
+V O -45
+V G -30
+V A -135
+W y -60
+W u -50
+W ; -55
+W . -92
+W o -75
+W i -18
+W - -37
+W hy -37
+W char173 -37
+W e -65
+W , -92
+W : -55
+W a -65
+W O -10
+W A -120
+Y u -92
+Y ; -92
+Y . -92
+Y o -111
+Y i -37
+Y - -92
+Y hy -92
+Y char173 -92
+Y e -111
+Y , -92
+Y : -92
+Y a -85
+Y O -35
+Y A -110
+a v -25
+b v -15
+b u -20
+b . -40
+b b -10
+, ' -55
+, rq -45
+d w -15
+e v -15
+f ' 55
+f rq 50
+f . -15
+f o -25
+f i -25
+f .i -35
+f , -15
+g . -15
+h y -15
+i v -10
+k y -15
+k o -15
+k e -10
+n v -40
+o w -10
+o v -10
+. ' -55
+. rq -55
+lq A -10
+` ` -63
+` oq -63
+oq ` -63
+oq oq -63
+` A -10
+oq A -10
+' v -20
+' s -37
+' r -20
+' ' -63
+' d -20
+r v -10
+r q -18
+r . -100
+r p -10
+r o -18
+r n -15
+r - -37
+r hy -37
+r char173 -37
+r g -10
+r e -18
+r , -92
+r c -18
+v . -70
+v o -10
+v e -10
+v , -55
+v a -10
+w . -70
+w o -10
+w , -55
+y . -70
+y o -25
+y e -10
+y , -55
+charset
+ha 581,676 2 0000 asciicircum
+ti 520,333 0 0001 asciitilde
+vS 556,914,19 2 0002 Scaron
+vZ 667,914 2 0003 Zcaron
+vs 389,704,14 2 0004 scaron
+vz 444,704 2 0005 zcaron
+:Y 722,877 2 0006 Ydieresis
+tm 1000,676 2 0007 trademark
+aq 278,691 2 0010 quotesingle
+space 250 0 0040
+! 333,691,13 2 0041 exclam
+" 555,691 2 0042 quotedbl
+# 500,700 2 0043 numbersign
+sh "
+$ 500,750,99 2 0044 dollar
+Do "
+% 1000,692,14 2 0045 percent
+& 833,691,16 2 0046 ampersand
+' 333,691 2 0047 quoteright
+( 333,694,168 2 0050 parenleft
+) 333,694,168 2 0051 parenright
+* 500,691 2 0052 asterisk
++ 570,506 0 0053 plus
+, 250,155,180 0 0054 comma
+- 333,287 0 0055 hyphen
+hy "
+char173 "
+. 250,156,13 0 0056 period
+/ 278,691,19 2 0057 slash
+sl "
+0 500,688,13 2 0060 zero
+1 500,688 2 0061 one
+2 500,688 2 0062 two
+3 500,688,14 2 0063 three
+4 500,688 2 0064 four
+5 500,676,8 2 0065 five
+6 500,688,13 2 0066 six
+7 500,676 2 0067 seven
+8 500,688,13 2 0070 eight
+9 500,688,13 2 0071 nine
+: 333,472,13 0 0072 colon
+; 333,472,180 0 0073 semicolon
+< 570,514,8 0 0074 less
+= 570,399 0 0075 equal
+> 570,514,8 0 0076 greater
+? 500,689,13 2 0077 question
+@ 930,691,19 2 0100 at
+at "
+A 722,690 2 0101 A
+B 667,676 2 0102 B
+C 722,691,19 2 0103 C
+D 722,676 2 0104 D
+E 667,676 2 0105 E
+F 611,676 2 0106 F
+G 778,691,19 2 0107 G
+H 778,676 2 0110 H
+I 389,676 2 0111 I
+J 500,676,96 2 0112 J
+K 778,676 2 0113 K
+L 667,676 2 0114 L
+M 944,676 2 0115 M
+N 722,676,18 2 0116 N
+O 778,691,19 2 0117 O
+P 611,676 2 0120 P
+Q 778,691,176 2 0121 Q
+R 722,676 2 0122 R
+S 556,692,19 2 0123 S
+T 667,676 2 0124 T
+U 722,676,19 2 0125 U
+V 722,676,18 2 0126 V
+W 1000,676,15 2 0127 W
+X 722,676 2 0130 X
+Y 722,676 2 0131 Y
+Z 667,676 2 0132 Z
+[ 333,678,149 2 0133 bracketleft
+lB "
+\ 278,691,19 2 0134 backslash
+rs "
+] 333,678,149 2 0135 bracketright
+rB "
+a^ 333,704 2 0136 circumflex
+^ "
+_ 500,0,125 0 0137 underscore
+` 333,691 2 0140 quoteleft
+oq "
+a 500,473,14 0 0141 a
+b 556,676,14 2 0142 b
+c 444,473,14 0 0143 c
+d 556,676,14 2 0144 d
+e 444,473,14 0 0145 e
+f 333,691 2 0146 f
+g 500,473,206 1 0147 g
+h 556,676 2 0150 h
+i 278,691 2 0151 i
+j 333,691,203 3 0152 j
+k 556,676 2 0153 k
+l 278,676 2 0154 l
+m 833,473 0 0155 m
+n 556,473 0 0156 n
+o 500,473,14 0 0157 o
+p 556,473,205 1 0160 p
+q 556,473,205 1 0161 q
+r 444,473 0 0162 r
+s 389,473,14 0 0163 s
+t 333,630,12 2 0164 t
+u 556,461,14 0 0165 u
+v 500,461,14 0 0166 v
+w 722,461,14 0 0167 w
+x 500,461 0 0170 x
+y 500,461,205 1 0171 y
+z 444,461 0 0172 z
+lC 394,698,175 2 0173 braceleft
+{ "
+ba 220,691,19 2 0174 bar
+| "
+rC 394,698,175 2 0175 braceright
+} "
+a~ 333,674 2 0176 tilde
+~ "
+bq 333,155,180 0 0200 quotesinglbase
+Fo 500,415 0 0201 guillemotleft
+char171 "
+Fc 500,415 0 0202 guillemotright
+char187 "
+bu 350,478 0 0203 bullet
+Fn 500,706,155 2 0204 florin
+f/ 167,688,12 2 0205 fraction
+%0 1000,706,29 2 0206 perthousand
+dg 500,691,134 2 0207 dagger
+dd 500,691,132 2 0210 daggerdbl
+en 500,271 0 0211 endash
+em 1000,271 0 0212 emdash
+fi 556,691 2 0214 fi
+fl 556,691 2 0215 fl
+.i 278,461 0 0220 dotlessi
+ga 333,713 2 0222 grave
+a" 333,713 2 0223 hungarumlaut
+a. 333,667 2 0224 dotaccent
+ab 333,691 2 0225 breve
+ah 333,704 2 0226 caron
+ao 333,740 2 0227 ring
+ho 333,44,173 0 0230 ogonek
+lq 500,691 2 0231 quotedblleft
+rq 500,691 2 0232 quotedblright
+oe 722,473,14 0 0233 oe
+/l 278,676 2 0234 lslash
+Bq 500,155,180 0 0235 quotedblbase
+OE 1000,684,5 2 0236 OE
+/L 667,676 2 0237 Lslash
+r! 333,501,203 1 0241 exclamdown
+char161 "
+ct 500,588,140 0 0242 cent
+char162 "
+Po 500,684,14 2 0243 sterling
+char163 "
+Cs 500,613 0 0244 currency
+char164 "
+Ye 500,676 2 0245 yen
+char165 "
+bb 220,691,19 2 0246 brokenbar
+char166 "
+sc 500,691,132 2 0247 section
+char167 "
+ad 333,667 2 0250 dieresis
+char168 "
+co 747,691,19 2 0251 copyright
+char169 "
+Of 300,688 2 0252 ordfeminine
+char170 "
+fo 333,415 0 0253 guilsinglleft
+no 570,399 0 0254 logicalnot
+char172 "
+\- 570,297 0 0255 minus
+rg 747,691,19 2 0256 registered
+char174 "
+a- 333,637 2 0257 macron
+char175 "
+de 400,688 2 0260 degree
+char176 "
+char177 570,506 0 0261 plusminus
+S2 300,688 2 0262 twosuperior
+char178 "
+S3 300,688 2 0263 threesuperior
+char179 "
+aa 333,713 2 0264 acute
+char180 "
+char181 556,461,206 1 0265 mu
+ps 540,676,186 2 0266 paragraph
+char182 "
+char183 250,417 0 0267 periodcentered
+ac 333,0,218 1 0270 cedilla
+char184 "
+S1 300,688 2 0271 onesuperior
+char185 "
+Om 330,688 2 0272 ordmasculine
+char186 "
+fc 333,415 0 0273 guilsinglright
+14 750,688,12 2 0274 onequarter
+char188 "
+12 750,688,12 2 0275 onehalf
+char189 "
+34 750,688,12 2 0276 threequarters
+char190 "
+r? 500,501,201 0 0277 questiondown
+char191 "
+`A 722,923 2 0300 Agrave
+char192 "
+'A 722,923 2 0301 Aacute
+char193 "
+^A 722,914 2 0302 Acircumflex
+char194 "
+~A 722,884 2 0303 Atilde
+char195 "
+:A 722,877 2 0304 Adieresis
+char196 "
+oA 722,935 2 0305 Aring
+char197 "
+AE 1000,676 2 0306 AE
+char198 "
+,C 722,691,218 3 0307 Ccedilla
+char199 "
+`E 667,923 2 0310 Egrave
+char200 "
+'E 667,923 2 0311 Eacute
+char201 "
+^E 667,914 2 0312 Ecircumflex
+char202 "
+:E 667,877 2 0313 Edieresis
+char203 "
+`I 389,923 2 0314 Igrave
+char204 "
+'I 389,923 2 0315 Iacute
+char205 "
+^I 389,914 2 0316 Icircumflex
+char206 "
+:I 389,877 2 0317 Idieresis
+char207 "
+-D 722,676 2 0320 Eth
+char208 "
+~N 722,884,18 2 0321 Ntilde
+char209 "
+`O 778,923,19 2 0322 Ograve
+char210 "
+'O 778,923,19 2 0323 Oacute
+char211 "
+^O 778,914,19 2 0324 Ocircumflex
+char212 "
+~O 778,884,19 2 0325 Otilde
+char213 "
+:O 778,877,19 2 0326 Odieresis
+char214 "
+char215 570,490 0 0327 multiply
+/O 778,737,74 2 0330 Oslash
+char216 "
+`U 722,923,19 2 0331 Ugrave
+char217 "
+'U 722,923,19 2 0332 Uacute
+char218 "
+^U 722,914,19 2 0333 Ucircumflex
+char219 "
+:U 722,877,19 2 0334 Udieresis
+char220 "
+'Y 722,928 2 0335 Yacute
+char221 "
+TP 611,676 2 0336 Thorn
+char222 "
+ss 556,691,12 2 0337 germandbls
+char223 "
+`a 500,713,14 2 0340 agrave
+char224 "
+'a 500,713,14 2 0341 aacute
+char225 "
+^a 500,704,14 2 0342 acircumflex
+char226 "
+~a 500,674,14 2 0343 atilde
+char227 "
+:a 500,667,14 2 0344 adieresis
+char228 "
+oa 500,740,14 2 0345 aring
+char229 "
+ae 722,473,14 0 0346 ae
+char230 "
+,c 444,473,218 1 0347 ccedilla
+char231 "
+`e 444,713,14 2 0350 egrave
+char232 "
+'e 444,713,14 2 0351 eacute
+char233 "
+^e 444,704,14 2 0352 ecircumflex
+char234 "
+:e 444,667,14 2 0353 edieresis
+char235 "
+`i 278,713 2 0354 igrave
+char236 "
+'i 278,713 2 0355 iacute
+char237 "
+^i 278,704 2 0356 icircumflex
+char238 "
+:i 278,667 2 0357 idieresis
+char239 "
+Sd 500,691,14 2 0360 eth
+char240 "
+~n 556,674 2 0361 ntilde
+char241 "
+`o 500,713,14 2 0362 ograve
+char242 "
+'o 500,713,14 2 0363 oacute
+char243 "
+^o 500,704,14 2 0364 ocircumflex
+char244 "
+~o 500,674,14 2 0365 otilde
+char245 "
+:o 500,667,14 2 0366 odieresis
+char246 "
+char247 570,537,31 0 0367 divide
+/o 500,549,92 0 0370 oslash
+char248 "
+`u 556,713,14 2 0371 ugrave
+char249 "
+'u 556,713,14 2 0372 uacute
+char250 "
+^u 556,704,14 2 0373 ucircumflex
+char251 "
+:u 556,667,14 2 0374 udieresis
+char252 "
+'y 500,713,205 3 0375 yacute
+char253 "
+Tp 556,676,205 3 0376 thorn
+char254 "
+:y 500,667,205 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/TBI b/gnu/usr.bin/groff/devices/devps/TBI
new file mode 100644
index 000000000000..ba58a3af3725
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/TBI
@@ -0,0 +1,515 @@
+name TBI
+internalname Times-BoldItalic
+slant 15
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -74
+A u -30
+A ' -74
+A Y -70
+A W -100
+A V -95
+A U -50
+A T -55
+A Q -55
+A O -50
+A G -60
+A C -65
+B U -10
+B A -25
+D Y -50
+D W -40
+D V -50
+D A -25
+F r -50
+F . -129
+F o -70
+F i -40
+F e -100
+F , -129
+F a -95
+F A -100
+J u -40
+J . -10
+J o -40
+J e -40
+J , -10
+J a -40
+J A -25
+K y -20
+K u -20
+K o -25
+K e -25
+K O -30
+L y -37
+L ' -55
+L Y -37
+L W -37
+L V -37
+L T -18
+N A -30
+O Y -50
+O X -40
+O W -50
+O V -50
+O T -40
+O A -40
+P . -129
+P o -55
+P e -50
+P , -129
+P a -40
+P A -85
+Q U -10
+R Y -18
+R W -18
+R V -18
+R U -40
+R T -30
+R O -40
+T y -37
+T w -37
+T u -37
+T ; -74
+T r -37
+T . -92
+T o -95
+T i -37
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -92
+T : -74
+T a -92
+T O -18
+T A -55
+U A -45
+V u -55
+V ; -74
+V . -129
+V o -111
+V i -55
+V - -70
+V hy -70
+V char173 -70
+V e -111
+V , -129
+V : -74
+V a -111
+V O -30
+V G -10
+V A -85
+W y -55
+W u -55
+W ; -55
+W . -74
+W o -80
+W i -37
+W - -50
+W hy -50
+W char173 -50
+W e -90
+W , -74
+W : -55
+W a -85
+W O -15
+W A -74
+Y u -92
+Y ; -92
+Y . -74
+Y o -111
+Y i -55
+Y - -92
+Y hy -92
+Y char173 -92
+Y e -111
+Y , -92
+Y : -92
+Y a -92
+Y O -25
+Y A -74
+b u -20
+b . -40
+b b -10
+c k -10
+c h -10
+, ' -95
+, rq -95
+e b -10
+f ' 55
+f . -10
+f o -10
+f f -18
+f e -10
+f .i -30
+f , -10
+k o -10
+k e -30
+n v -40
+o y -10
+o x -10
+o w -25
+o v -15
+. ' -95
+. rq -95
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+' v -15
+' t -37
+' s -74
+' r -15
+' ' -74
+' d -15
+r . -65
+r , -65
+v . -37
+v o -15
+v e -15
+v , -37
+w . -37
+w o -15
+w e -10
+w , -37
+w a -10
+x e -10
+y . -37
+y , -37
+charset
+ha 570,669,0,0,-17 2 0000 asciicircum
+ti 570,333,0,0,-4 0 0001 asciitilde
+vS 556,897,18,20,48,20 2 0002 Scaron
+vZ 611,897,0,29,61,29 2 0003 Zcaron
+vs 389,690,13,100,69,99 2 0004 scaron
+vz 389,690,78,85,93,85 2 0005 zcaron
+:Y 611,862,0,98,-23,98 2 0006 Ydieresis
+tm 1000,669,0,18,18,18 2 0007 trademark
+aq 278,685,0,40,-78,40 2 0010 quotesingle
+space 250 0 0040
+! 389,684,13,31,-17,31 2 0041 exclam
+" 555,685,0,31,-86,31 2 0042 quotedbl
+# 500,700,0,83,83,83 2 0043 numbersign
+sh "
+$ 500,733,100,47,70,47 2 0044 dollar
+Do "
+% 833,692,10,10,11,10 2 0045 percent
+& 778,682,19,0,45 2 0046 ampersand
+' 333,685,0,19,-48,19 2 0047 quoteright
+( 333,685,179,61,22,61 2 0050 parenleft
+) 333,685,179,0,94 2 0051 parenright
+* 500,685,0,6,-15,6 2 0052 asterisk
++ 570,506,0,17,17,17 0 0053 plus
+, 250,134,182,0,110 0 0054 comma
+- 333,282,0,0,48 0 0055 hyphen
+hy "
+char173 "
+. 250,135,13,0,59 0 0056 period
+/ 278,685,18,114,114,99 2 0057 slash
+sl "
+0 500,683,14,27,33,27 2 0060 zero
+1 500,683,0,0,45 2 0061 one
+2 500,683,0,0,77 2 0062 two
+3 500,683,13,0,65 2 0063 three
+4 500,683,0,53,65,53 2 0064 four
+5 500,669,13,37,61,37 2 0065 five
+6 500,679,15,59,27,59 2 0066 six
+7 500,669,0,75,-2,75 2 0067 seven
+8 500,683,13,26,47,26 2 0070 eight
+9 500,683,10,25,62,25 2 0071 nine
+: 333,459,13,0,27 0 0072 colon
+; 333,459,183,0,75 0 0073 semicolon
+< 570,514,8,19,19,19 0 0074 less
+= 570,399,0,17,17,17 0 0075 equal
+> 570,514,8,19,19,19 0 0076 greater
+? 500,684,13,20,-29,20 2 0077 question
+@ 832,685,18,0,-13 2 0100 at
+at "
+A 667,683,0,0,117 2 0101 A
+B 667,669,0,7,74,7 2 0102 B
+C 667,685,18,60,18,60 2 0103 C
+D 722,669,0,13,96,13 2 0104 D
+E 667,669,0,36,77,36 2 0105 E
+F 667,669,0,43,63,43 2 0106 F
+G 722,685,18,34,29,34 2 0107 G
+H 778,669,0,71,74,71 2 0110 H
+I 389,669,0,67,82,67 2 0111 I
+J 500,669,99,74,96,74 2 0112 J
+K 667,669,0,85,71,85 2 0113 K
+L 611,669,0,29,72,29 2 0114 L
+M 889,669,12,78,79,78 2 0115 M
+N 722,669,15,76,77,76 2 0116 N
+O 722,685,18,19,23,19 2 0117 O
+P 611,669,0,52,77,52 2 0120 P
+Q 722,685,208,19,23,19 3 0121 Q
+R 667,669,0,6,79,6 2 0122 R
+S 556,685,18,20,48,20 2 0123 S
+T 611,669,0,89,0,89 2 0124 T
+U 722,669,18,72,-17,72 2 0125 U
+V 667,669,18,98,-15,98 2 0126 V
+W 889,669,18,101,-15,99 2 0127 W
+X 667,669,0,77,74,77 2 0130 X
+Y 611,669,0,98,-23,98 2 0131 Y
+Z 611,669,0,29,61,29 2 0132 Z
+[ 333,674,159,79,87,79 2 0133 bracketleft
+lB "
+\ 278,685,18,51,51,51 2 0134 backslash
+rs "
+] 333,674,157,60,106,60 2 0135 bracketright
+rB "
+a^ 333,690,0,84,10,84 2 0136 circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 underscore
+` 333,685,0,49,-78,49 2 0140 quoteleft
+oq "
+a 500,462,14,5,71,5 0 0141 a
+b 500,699,13,0,64 2 0142 b
+c 444,462,13,0,55 0 0143 c
+d 500,699,13,67,71,67 2 0144 d
+e 444,462,13,4,45,4 0 0145 e
+f 333,698,205,163,219,99 3 0146 f
+g 500,462,203,28,102,28 1 0147 g
+h 556,699,9,0,63 2 0150 h
+i 278,684,9,35,48,35 2 0151 i
+j 278,684,207,51,239,51 3 0152 j
+k 500,699,8,33,73,33 2 0153 k
+l 278,699,9,62,48,62 2 0154 l
+m 778,462,9,0,64 0 0155 m
+n 556,462,9,0,56 0 0156 n
+o 500,462,13,0,53 0 0157 o
+p 500,462,205,0,170 1 0160 p
+q 500,462,205,21,49,21 1 0161 q
+r 389,462,0,50,71,50 0 0162 r
+s 389,462,13,0,69 0 0163 s
+t 278,594,9,53,61,53 2 0164 t
+u 556,462,9,0,35 0 0165 u
+v 444,462,13,7,34,7 0 0166 v
+w 667,462,13,0,34 0 0167 w
+x 500,462,13,19,96,19 0 0170 x
+y 444,462,205,0,144 1 0171 y
+z 389,449,78,29,93,29 0 0172 z
+lC 348,686,187,138,45,99 2 0173 braceleft
+{ "
+ba 220,685,18,0,-16 2 0174 bar
+| "
+rC 348,686,187,4,179,4 2 0175 braceright
+} "
+a~ 333,655,0,124,2,99 2 0176 tilde
+~ "
+bq 333,134,182,0,55 0 0200 quotesinglbase
+Fo 500,415,0,18,38,18 0 0201 guillemotleft
+char171 "
+Fc 500,415,0,18,38,18 0 0202 guillemotright
+char187 "
+bu 350,525,0,50,50,50 0 0203 bullet
+Fn 500,707,156,87,137,87 2 0204 florin
+f/ 167,683,14,207,219,99 2 0205 fraction
+%0 1000,706,29,46,43,46 2 0206 perthousand
+dg 500,685,145,44,-41,44 2 0207 dagger
+dd 500,685,139,43,40,43 2 0210 daggerdbl
+en 500,269,0,27,90,27 0 0211 endash
+em 1000,269,0,27,90,27 0 0212 emdash
+fi 556,703,205,8,238,8 3 0214 fi
+fl 556,704,205,47,236,47 3 0215 fl
+.i 278,462,9,10,48,10 0 0220 dotlessi
+ga 333,697,0,14,-35,14 2 0222 grave
+a" 333,697,0,215,-19,99 2 0223 hungarumlaut
+a. 333,655,0,10,-113,10 2 0224 dotaccent
+ab 333,678,0,104,-21,99 2 0225 breve
+ah 333,690,0,128,-29,99 2 0226 caron
+ao 333,729,0,57,-77,57 2 0227 ring
+ho 333,44,173,0,90 0 0230 ogonek
+lq 500,685,0,63,-3,63 2 0231 quotedblleft
+rq 500,685,0,63,-3,63 2 0232 quotedblright
+oe 722,462,13,2,44,2 0 0233 oe
+/l 278,699,9,73,63,73 2 0234 lslash
+Bq 500,134,182,0,107 0 0235 quotedblbase
+OE 944,677,8,52,27,52 2 0236 OE
+/L 611,669,0,29,72,29 2 0237 Lslash
+r! 389,492,205,0,31 1 0241 exclamdown
+char161 "
+ct 500,576,143,0,8 0 0242 cent
+char162 "
+Po 500,683,12,60,82,60 2 0243 sterling
+char163 "
+Cs 500,586,0,76,76,76 0 0244 currency
+char164 "
+Ye 500,669,0,178,17,99 2 0245 yen
+char165 "
+bb 220,685,18,0,-16 2 0246 brokenbar
+char166 "
+sc 500,685,143,9,14,9 2 0247 section
+char167 "
+ad 333,655,0,114,-5,99 2 0250 dieresis
+char168 "
+co 747,685,18,21,20,21 2 0251 copyright
+char169 "
+Of 266,685,0,114,34,99 2 0252 ordfeminine
+char170 "
+fo 333,415,0,20,18,20 0 0253 guilsinglleft
+no 606,399,0,0,-1 0 0254 logicalnot
+char172 "
+\- 606,297,0,0,-1 0 0255 minus
+rg 747,685,18,21,20,21 2 0256 registered
+char174 "
+a- 333,623,0,110,-1,99 2 0257 macron
+char175 "
+de 400,683,0,19,-33,19 2 0260 degree
+char176 "
+char177 570,506,0,17,17,17 0 0261 plusminus
+S2 300,683,0,63,48,63 2 0262 twosuperior
+char178 "
+S3 300,683,0,71,33,71 2 0263 threesuperior
+char179 "
+aa 333,697,0,96,-89,96 2 0264 acute
+char180 "
+char181 576,449,207,0,110 1 0265 mu
+ps 500,669,193,112,107,99 2 0266 paragraph
+char182 "
+char183 250,405,0,0,-1 0 0267 periodcentered
+ac 333,5,218,0,130 1 0270 cedilla
+char184 "
+S1 300,683,0,51,20,51 2 0271 onesuperior
+char185 "
+Om 300,685,0,97,-6,97 2 0272 ordmasculine
+char186 "
+fc 333,415,0,0,40 0 0273 guilsinglright
+14 750,683,14,21,43,21 2 0274 onequarter
+char188 "
+12 750,683,14,23,59,23 2 0275 onehalf
+char189 "
+34 750,683,14,26,43,26 2 0276 threequarters
+char190 "
+r? 500,492,205,0,20 1 0277 questiondown
+char191 "
+`A 667,904,0,0,117 2 0300 Agrave
+char192 "
+'A 667,904,0,0,117 2 0301 Aacute
+char193 "
+^A 667,897,0,0,117 2 0302 Acircumflex
+char194 "
+~A 667,862,0,0,117 2 0303 Atilde
+char195 "
+:A 667,862,0,0,117 2 0304 Adieresis
+char196 "
+oA 667,921,0,0,117 2 0305 Aring
+char197 "
+AE 944,669,0,24,114,24 2 0306 AE
+char198 "
+,C 667,685,218,60,18,60 3 0307 Ccedilla
+char199 "
+`E 667,904,0,36,77,36 2 0310 Egrave
+char200 "
+'E 667,904,0,36,77,36 2 0311 Eacute
+char201 "
+^E 667,897,0,36,77,36 2 0312 Ecircumflex
+char202 "
+:E 667,862,0,36,77,36 2 0313 Edieresis
+char203 "
+`I 389,904,0,67,82,67 2 0314 Igrave
+char204 "
+'I 389,904,0,73,82,73 2 0315 Iacute
+char205 "
+^I 389,897,0,81,82,81 2 0316 Icircumflex
+char206 "
+:I 389,862,0,106,82,99 2 0317 Idieresis
+char207 "
+-D 722,669,0,28,81,28 2 0320 Eth
+char208 "
+~N 722,862,15,76,77,76 2 0321 Ntilde
+char209 "
+`O 722,904,18,19,23,19 2 0322 Ograve
+char210 "
+'O 722,904,18,19,23,19 2 0323 Oacute
+char211 "
+^O 722,897,18,19,23,19 2 0324 Ocircumflex
+char212 "
+~O 722,862,18,19,23,19 2 0325 Otilde
+char213 "
+:O 722,862,18,19,23,19 2 0326 Odieresis
+char214 "
+char215 570,490,0,2,2,2 0 0327 multiply
+/O 722,764,125,19,23,19 2 0330 Oslash
+char216 "
+`U 722,904,18,72,-17,72 2 0331 Ugrave
+char217 "
+'U 722,904,18,72,-17,72 2 0332 Uacute
+char218 "
+^U 722,897,18,72,-17,72 2 0333 Ucircumflex
+char219 "
+:U 722,862,18,72,-17,72 2 0334 Udieresis
+char220 "
+'Y 611,904,0,98,-23,98 2 0335 Yacute
+char221 "
+TP 611,669,0,12,77,12 2 0336 Thorn
+char222 "
+ss 500,705,200,23,250,23 2 0337 germandbls
+char223 "
+`a 500,697,14,5,71,5 2 0340 agrave
+char224 "
+'a 500,697,14,13,71,13 2 0341 aacute
+char225 "
+^a 500,690,14,5,71,5 2 0342 acircumflex
+char226 "
+~a 500,655,14,41,71,41 2 0343 atilde
+char227 "
+:a 500,655,14,21,71,21 2 0344 adieresis
+char228 "
+oa 500,729,14,5,71,5 2 0345 aring
+char229 "
+ae 722,462,13,1,55,1 0 0346 ae
+char230 "
+,c 444,462,218,0,74 1 0347 ccedilla
+char231 "
+`e 444,697,13,4,45,4 2 0350 egrave
+char232 "
+'e 444,697,13,41,45,41 2 0351 eacute
+char233 "
+^e 444,690,13,29,45,29 2 0352 ecircumflex
+char234 "
+:e 444,655,13,49,45,49 2 0353 edieresis
+char235 "
+`i 278,697,9,32,48,32 2 0354 igrave
+char236 "
+'i 278,697,9,124,48,99 2 0355 iacute
+char237 "
+^i 278,690,9,97,52,97 2 0356 icircumflex
+char238 "
+:i 278,655,9,132,48,99 2 0357 idieresis
+char239 "
+Sd 500,699,13,4,53,4 2 0360 eth
+char240 "
+~n 556,655,9,0,56 2 0361 ntilde
+char241 "
+`o 500,697,13,0,53 2 0362 ograve
+char242 "
+'o 500,697,13,13,53,13 2 0363 oacute
+char243 "
+^o 500,690,13,1,53,1 2 0364 ocircumflex
+char244 "
+~o 500,655,13,41,53,41 2 0365 otilde
+char245 "
+:o 500,655,13,16,53,16 2 0366 odieresis
+char246 "
+char247 570,535,29,17,17,17 0 0367 divide
+/o 500,560,119,0,53 0 0370 oslash
+char248 "
+`u 556,697,9,0,35 2 0371 ugrave
+char249 "
+'u 556,697,9,0,35 2 0372 uacute
+char250 "
+^u 556,690,9,0,35 2 0373 ucircumflex
+char251 "
+:u 556,655,9,0,35 2 0374 udieresis
+char252 "
+'y 444,697,205,41,144,41 3 0375 yacute
+char253 "
+Tp 500,699,205,0,170 3 0376 thorn
+char254 "
+:y 444,655,205,44,144,44 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/TI b/gnu/usr.bin/groff/devices/devps/TI
new file mode 100644
index 000000000000..156cba79677a
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/TI
@@ -0,0 +1,528 @@
+name TI
+internalname Times-Italic
+slant 7
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -55
+A w -55
+A v -55
+A u -20
+A ' -37
+A Y -55
+A W -95
+A V -105
+A U -50
+A T -37
+A Q -40
+A O -40
+A G -35
+A C -30
+B U -10
+B A -25
+D Y -40
+D W -40
+D V -40
+D A -35
+F r -55
+F . -135
+F o -105
+F i -45
+F e -75
+F , -135
+F a -75
+F A -115
+J u -35
+J . -25
+J o -25
+J e -25
+J , -25
+J a -35
+J A -40
+K y -40
+K u -40
+K o -40
+K e -35
+K O -50
+L y -30
+L ' -37
+L Y -20
+L W -55
+L V -55
+L T -20
+N A -27
+O Y -50
+O X -40
+O W -50
+O V -50
+O T -40
+O A -55
+P . -135
+P o -80
+P e -80
+P , -135
+P a -80
+P A -90
+Q U -10
+R Y -18
+R W -18
+R V -18
+R U -40
+R O -40
+T y -74
+T w -74
+T u -55
+T ; -65
+T r -55
+T . -74
+T o -92
+T i -55
+T - -74
+T hy -74
+T char173 -74
+T e -92
+T , -74
+T : -55
+T a -92
+T O -18
+T A -50
+U . -25
+U , -25
+U A -40
+V u -74
+V ; -74
+V . -129
+V o -111
+V i -74
+V - -55
+V hy -55
+V char173 -55
+V e -111
+V , -129
+V : -65
+V a -111
+V O -30
+V A -60
+W y -70
+W u -55
+W ; -65
+W . -92
+W o -92
+W i -55
+W - -37
+W hy -37
+W char173 -37
+W e -92
+W , -92
+W : -65
+W a -92
+W O -25
+W A -60
+Y u -92
+Y ; -65
+Y . -92
+Y o -92
+Y i -74
+Y - -74
+Y hy -74
+Y char173 -74
+Y e -92
+Y , -92
+Y : -65
+Y a -92
+Y O -15
+Y A -50
+a g -10
+b u -20
+b . -40
+c k -20
+c h -15
+, ' -140
+, rq -140
+e y -30
+e x -20
+e w -15
+e v -15
+e . -15
+e g -40
+e , -10
+f ' 92
+f . -15
+f i -20
+f f -18
+f .i -60
+f , -10
+g . -15
+g g -10
+g e -10
+g , -10
+k y -10
+k o -10
+k e -10
+n v -40
+o v -10
+o g -10
+. ' -140
+. rq -140
+` ` -111
+` oq -111
+oq ` -111
+oq oq -111
+' v -10
+' t -30
+' s -40
+' r -25
+' ' -111
+' d -25
+r s -10
+r q -37
+r . -111
+r o -45
+r - -20
+r hy -20
+r char173 -20
+r g -37
+r e -37
+r d -37
+r , -111
+r c -37
+r a -15
+v . -74
+v , -74
+w . -74
+w , -74
+y . -55
+y , -55
+charset
+ha 422,666,0,50,50,43 2 0000 asciicircum
+ti 541,323,0,11,10,11 0 0001 asciitilde
+vS 500,873,18,70,33,43 2 0002 Scaron
+vZ 556,873,0,100,56,43 2 0003 Zcaron
+vs 389,661,13,115,34,43 2 0004 scaron
+vz 389,661,81,95,52,43 2 0005 zcaron
+:Y 556,818,0,127,-28,43 2 0006 Ydieresis
+tm 980,653,0,27,20,27 2 0007 trademark
+aq 214,666,0,77,-82,43 2 0010 quotesingle
+space 250 0 0040
+! 333,667,11,19,11,19 2 0041 exclam
+" 420,666,0,62,-94,43 2 0042 quotedbl
+# 500,676,0,90,48,43 2 0043 numbersign
+sh "
+$ 500,731,89,47,19,43 2 0044 dollar
+Do "
+% 833,676,13,7,-29,7 2 0045 percent
+& 778,666,18,0,-26 2 0046 ampersand
+' 333,666,0,7,-101,7 2 0047 quoteright
+( 333,669,181,32,8,32 2 0050 parenleft
+) 333,669,180,6,34,6 2 0051 parenright
+* 500,666,0,42,-78,42 2 0052 asterisk
++ 675,506,0,0,-36 0 0053 plus
+, 250,101,129,0,54 0 0054 comma
+- 333,255,0,0,1 0 0055 hyphen
+hy "
+char173 "
+. 250,100,11,0,23 0 0056 period
+/ 278,666,18,158,115,43 2 0057 slash
+sl "
+0 500,676,7,47,18,43 2 0060 zero
+1 500,676,0,0,1 2 0061 one
+2 500,676,0,2,38,2 2 0062 two
+3 500,676,7,15,35,15 2 0063 three
+4 500,676,0,29,49,29 2 0064 four
+5 500,666,7,41,35,41 2 0065 five
+6 500,686,7,71,20,43 2 0066 six
+7 500,666,8,87,-25,43 2 0067 seven
+8 500,676,7,43,20,43 2 0070 eight
+9 500,676,17,42,27,42 2 0071 nine
+: 333,441,11 0 0072 colon
+; 333,441,129,0,23 0 0073 semicolon
+< 675,514,8,0,-34 0 0074 less
+= 675,386,0,0,-36 0 0075 equal
+> 675,514,8,0,-34 0 0076 greater
+? 500,664,12,22,-82,22 2 0077 question
+@ 920,666,18,0,-68 2 0100 at
+at "
+A 611,668,0,3,101,3 2 0101 A
+B 611,653,0,27,58,27 2 0102 B
+C 667,666,18,72,-16,43 2 0103 C
+D 722,653,0,28,58,28 2 0104 D
+E 611,653,0,73,51,43 2 0105 E
+F 611,653,0,84,42,43 2 0106 F
+G 722,666,18,50,-2,43 2 0107 G
+H 722,653,0,95,58,43 2 0110 H
+I 333,653,0,101,58,43 2 0111 I
+J 444,653,18,97,56,43 2 0112 J
+K 667,653,0,105,43,43 2 0113 K
+L 556,653,0,53,58,43 2 0114 L
+M 833,653,0,90,68,43 2 0115 M
+N 667,653,15,110,70,43 2 0116 N
+O 722,666,18,27,-10,27 2 0117 O
+P 611,653,0,44,50,43 2 0120 P
+Q 722,666,182,27,-9,27 2 0121 Q
+R 611,653,0,27,63,27 2 0122 R
+S 500,667,18,58,33,43 2 0123 S
+T 556,653,0,127,-9,43 2 0124 T
+U 722,653,18,93,-52,43 2 0125 U
+V 611,653,18,127,-26,43 2 0126 V
+W 833,653,18,123,-21,43 2 0127 W
+X 611,653,0,94,79,43 2 0130 X
+Y 556,653,0,127,-28,43 2 0131 Y
+Z 556,653,0,100,56,43 2 0132 Z
+[ 389,663,153,52,29,43 2 0133 bracketleft
+lB "
+\ 278,666,18,91,91,43 2 0134 backslash
+rs "
+] 389,663,153,43,38,43 2 0135 bracketright
+rB "
+a^ 333,661,0,102,-41,43 2 0136 circumflex
+^ "
+_ 500,0,125,50,50,43 0 0137 underscore
+` 333,666,0,27,-121,27 2 0140 quoteleft
+oq "
+a 500,441,11,26,33,26 0 0141 a
+b 500,683,11,23,27,23 2 0142 b
+c 444,441,11,31,20,31 0 0143 c
+d 500,683,13,77,35,43 2 0144 d
+e 444,441,11,18,19,18 0 0145 e
+f 278,678,207,196,197,43 3 0146 f
+g 500,441,206,22,42,22 1 0147 g
+h 500,683,9,28,31,28 2 0150 h
+i 278,654,11,36,1,36 2 0151 i
+j 278,654,207,48,174,43 3 0152 j
+k 444,683,11,67,36,43 2 0153 k
+l 278,683,11,51,9,43 2 0154 l
+m 722,441,9,32,38,32 0 0155 m
+n 500,441,9,24,36,24 0 0156 n
+o 500,441,11,18,23,18 0 0157 o
+p 500,441,205,19,125,19 1 0160 p
+q 500,441,209,33,25,33 1 0161 q
+r 389,441,0,73,5,43 0 0162 r
+s 389,442,13,27,34,27 0 0163 s
+t 278,546,11,68,13,43 2 0164 t
+u 500,441,11,25,8,25 0 0165 u
+v 444,441,18,32,29,32 0 0166 v
+w 667,441,18,31,34,31 0 0167 w
+x 444,441,11,53,77,43 0 0170 x
+y 444,441,206,32,74,32 1 0171 y
+z 389,428,81,41,52,41 0 0172 z
+lC 400,687,177,57,-1,43 2 0173 braceleft
+{ "
+ba 275,666,18,0,-55 2 0174 bar
+| "
+rC 400,687,177,0,57 2 0175 braceright
+} "
+a~ 333,624,0,144,-50,43 2 0176 tilde
+~ "
+bq 333,101,129,0,6 0 0200 quotesinglbase
+Fo 500,403,0,0,-3 0 0201 guillemotleft
+char171 "
+Fc 500,403,0,0,-5 0 0202 guillemotright
+char187 "
+bu 350,461,0,10,10,10 0 0203 bullet
+Fn 500,682,182,57,25,43 2 0204 florin
+f/ 167,676,10,220,219,43 2 0205 fraction
+%0 1000,706,19,60,25,43 2 0206 perthousand
+dg 500,666,159,38,-51,38 2 0207 dagger
+dd 500,666,143,41,28,41 2 0210 daggerdbl
+en 500,243,0,55,56,43 0 0211 endash
+em 889,243,0,55,56,43 0 0212 emdash
+fi 500,681,207,31,191,31 3 0214 fi
+fl 500,682,204,68,191,43 3 0215 fl
+.i 278,441,11,7,1,7 0 0220 dotlessi
+ga 333,664,0,28,-71,28 2 0222 grave
+a" 333,664,0,203,-43,43 2 0223 hungarumlaut
+a. 333,606,0,22,-157,22 2 0224 dotaccent
+ab 333,650,0,135,-67,43 2 0225 breve
+ah 333,661,0,143,-71,43 2 0226 caron
+ao 333,691,0,72,-105,43 2 0227 ring
+ho 333,40,169,0,70 0 0230 ogonek
+lq 556,666,0,8,-116,8 2 0231 quotedblleft
+rq 556,666,0,0,-101 2 0232 quotedblright
+oe 667,441,12,29,30,29 0 0233 oe
+/l 278,683,11,79,13,43 2 0234 lslash
+Bq 556,101,129,0,-7 0 0235 quotedblbase
+OE 944,666,8,70,1,43 2 0236 OE
+/L 556,653,0,53,58,43 2 0237 Lslash
+r! 389,473,205,0,-9 1 0241 exclamdown
+char161 "
+ct 500,560,143,22,-27,22 2 0242 cent
+char162 "
+Po 500,670,6,67,40,43 2 0243 sterling
+char163 "
+Cs 500,597,0,72,72,43 2 0244 currency
+char164 "
+Ye 500,653,0,153,23,43 2 0245 yen
+char165 "
+bb 275,666,18,0,-55 2 0246 brokenbar
+char166 "
+sc 500,666,162,11,-3,11 2 0247 section
+char167 "
+ad 333,606,0,122,-57,43 2 0250 dieresis
+char168 "
+co 760,666,18,9,9,9 2 0251 copyright
+char169 "
+Of 276,676,0,126,8,43 2 0252 ordfeminine
+char170 "
+fo 333,403,0,0,-1 0 0253 guilsinglleft
+no 675,386,0,0,-36 0 0254 logicalnot
+char172 "
+\- 675,286,0,0,-36 0 0255 minus
+rg 760,666,18,9,9,9 2 0256 registered
+char174 "
+a- 333,583,0,128,-49,43 2 0257 macron
+char175 "
+de 400,676,0,37,-51,37 2 0260 degree
+char176 "
+char177 675,506,0,0,-36 0 0261 plusminus
+S2 300,676,0,74,17,43 2 0262 twosuperior
+char178 "
+S3 300,676,0,89,7,43 2 0263 threesuperior
+char179 "
+aa 333,664,0,120,-130,43 2 0264 acute
+char180 "
+char181 500,428,209,47,80,43 1 0265 mu
+ps 523,653,123,143,-5,43 2 0266 paragraph
+char182 "
+char183 250,310,0,0,-20 0 0267 periodcentered
+ac 333,0,217,0,80 1 0270 cedilla
+char184 "
+S1 300,676,0,34,7,34 2 0271 onesuperior
+char185 "
+Om 310,676,0,102,-17,43 2 0272 ordmasculine
+char186 "
+fc 333,403,0,0,-2 0 0273 guilsinglright
+14 750,676,10,36,17,36 2 0274 onequarter
+char188 "
+12 750,676,10,49,16,43 2 0275 onehalf
+char189 "
+34 750,676,10,36,27,36 2 0276 threequarters
+char190 "
+r? 500,471,205,0,22 1 0277 questiondown
+char191 "
+`A 611,876,0,3,101,3 2 0300 Agrave
+char192 "
+'A 611,876,0,3,101,3 2 0301 Aacute
+char193 "
+^A 611,873,0,3,101,3 2 0302 Acircumflex
+char194 "
+~A 611,836,0,5,101,5 2 0303 Atilde
+char195 "
+:A 611,818,0,3,101,3 2 0304 Adieresis
+char196 "
+oA 611,883,0,3,101,3 2 0305 Aring
+char197 "
+AE 889,653,0,72,77,43 2 0306 AE
+char198 "
+,C 667,666,217,72,-16,43 3 0307 Ccedilla
+char199 "
+`E 611,876,0,73,51,43 2 0310 Egrave
+char200 "
+'E 611,876,0,73,51,43 2 0311 Eacute
+char201 "
+^E 611,873,0,73,51,43 2 0312 Ecircumflex
+char202 "
+:E 611,818,0,73,51,43 2 0313 Edieresis
+char203 "
+`I 333,876,0,101,58,43 2 0314 Igrave
+char204 "
+'I 333,876,0,130,58,43 2 0315 Iacute
+char205 "
+^I 333,873,0,142,58,43 2 0316 Icircumflex
+char206 "
+:I 333,818,0,152,58,43 2 0317 Idieresis
+char207 "
+-D 722,653,0,28,58,28 2 0320 Eth
+char208 "
+~N 667,836,15,110,70,43 2 0321 Ntilde
+char209 "
+`O 722,876,18,27,-10,27 2 0322 Ograve
+char210 "
+'O 722,876,18,27,-10,27 2 0323 Oacute
+char211 "
+^O 722,873,18,27,-10,27 2 0324 Ocircumflex
+char212 "
+~O 722,836,18,27,-10,27 2 0325 Otilde
+char213 "
+:O 722,818,18,27,-10,27 2 0326 Odieresis
+char214 "
+char215 675,497,0,0,-43 0 0327 multiply
+/O 722,722,105,27,-10,27 2 0330 Oslash
+char216 "
+`U 722,876,18,93,-52,43 2 0331 Ugrave
+char217 "
+'U 722,876,18,93,-52,43 2 0332 Uacute
+char218 "
+^U 722,873,18,93,-52,43 2 0333 Ucircumflex
+char219 "
+:U 722,818,18,93,-52,43 2 0334 Udieresis
+char220 "
+'Y 556,876,0,127,-28,43 2 0335 Yacute
+char221 "
+TP 611,653,0,8,50,8 2 0336 Thorn
+char222 "
+ss 500,679,207,43,218,43 3 0337 germandbls
+char223 "
+`a 500,664,11,26,33,26 2 0340 agrave
+char224 "
+'a 500,664,11,37,33,37 2 0341 aacute
+char225 "
+^a 500,661,11,26,33,26 2 0342 acircumflex
+char226 "
+~a 500,624,11,61,33,43 2 0343 atilde
+char227 "
+:a 500,606,11,39,33,39 2 0344 adieresis
+char228 "
+oa 500,691,11,26,33,26 2 0345 aring
+char229 "
+ae 667,441,11,23,27,23 0 0346 ae
+char230 "
+,c 444,441,217,31,24,31 1 0347 ccedilla
+char231 "
+`e 444,664,11,18,19,18 2 0350 egrave
+char232 "
+'e 444,664,11,65,19,43 2 0351 eacute
+char233 "
+^e 444,661,11,47,19,43 2 0352 ecircumflex
+char234 "
+:e 444,606,11,57,19,43 2 0353 edieresis
+char235 "
+`i 278,664,11,56,1,43 2 0354 igrave
+char236 "
+'i 278,664,11,128,1,43 2 0355 iacute
+char237 "
+^i 278,661,11,100,16,43 2 0356 icircumflex
+char238 "
+:i 278,606,11,125,1,43 2 0357 idieresis
+char239 "
+Sd 500,683,11,32,23,32 2 0360 eth
+char240 "
+~n 500,624,9,26,36,26 2 0361 ntilde
+char241 "
+`o 500,664,11,18,23,18 2 0362 ograve
+char242 "
+'o 500,664,11,37,23,37 2 0363 oacute
+char243 "
+^o 500,661,11,18,23,18 2 0364 ocircumflex
+char244 "
+~o 500,624,11,46,23,43 2 0365 otilde
+char245 "
+:o 500,606,11,39,23,39 2 0366 odieresis
+char246 "
+char247 675,517,11,0,-36 0 0367 divide
+/o 500,554,135,19,22,19 2 0370 oslash
+char248 "
+`u 500,664,11,25,8,25 2 0371 ugrave
+char249 "
+'u 500,664,11,27,8,27 2 0372 uacute
+char250 "
+^u 500,661,11,25,8,25 2 0373 ucircumflex
+char251 "
+:u 500,606,11,29,8,29 2 0374 udieresis
+char252 "
+'y 444,664,206,65,74,43 3 0375 yacute
+char253 "
+Tp 500,683,205,19,125,19 3 0376 thorn
+char254 "
+:y 444,606,206,47,74,43 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/TR b/gnu/usr.bin/groff/devices/devps/TR
new file mode 100644
index 000000000000..25232c6d1add
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/TR
@@ -0,0 +1,519 @@
+name TR
+internalname Times-Roman
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -92
+A w -92
+A v -74
+A ' -111
+A Y -105
+A W -90
+A V -135
+A U -55
+A T -111
+A Q -55
+A O -55
+A G -40
+A C -40
+B U -10
+B A -35
+D Y -55
+D W -30
+D V -40
+D A -40
+F . -80
+F o -15
+F , -80
+F a -15
+F A -74
+J A -60
+K y -25
+K u -15
+K o -35
+K e -25
+K O -30
+L y -55
+L ' -92
+L Y -100
+L W -74
+L V -100
+L T -92
+N A -35
+O Y -50
+O X -40
+O W -35
+O V -50
+O T -40
+O A -35
+P . -111
+P , -111
+P a -15
+P A -92
+Q U -10
+R Y -65
+R W -55
+R V -80
+R U -40
+R T -60
+R O -40
+T y -80
+T w -80
+T u -45
+T ; -55
+T r -35
+T . -74
+T o -80
+T i -35
+T - -92
+T hy -92
+T char173 -92
+T e -70
+T , -74
+T : -50
+T a -80
+T O -18
+T A -93
+U A -40
+V u -75
+V ; -74
+V . -129
+V o -129
+V i -60
+V - -100
+V hy -100
+V char173 -100
+V e -111
+V , -129
+V : -74
+V a -111
+V O -40
+V G -15
+V A -135
+W y -73
+W u -50
+W ; -37
+W . -92
+W o -80
+W i -40
+W - -65
+W hy -65
+W char173 -65
+W e -80
+W , -92
+W : -37
+W a -80
+W O -10
+W A -120
+Y u -111
+Y ; -92
+Y . -129
+Y o -110
+Y i -55
+Y - -111
+Y hy -111
+Y char173 -111
+Y e -100
+Y , -129
+Y : -92
+Y a -100
+Y O -30
+Y A -120
+a w -15
+a v -20
+b v -15
+b u -20
+b . -40
+c y -15
+, ' -70
+, rq -70
+e y -15
+e x -15
+e w -25
+e v -25
+e g -15
+f ' 55
+f i -20
+f f -25
+f .i -50
+f a -10
+g a -5
+h y -5
+i v -25
+k y -15
+k o -10
+k e -10
+l w -10
+n y -15
+n v -40
+o y -10
+o w -25
+o v -15
+p y -10
+. ' -70
+. rq -70
+lq A -80
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+` A -80
+oq A -80
+' v -50
+' t -18
+' s -55
+' r -50
+' ' -74
+' l -10
+' d -50
+r . -55
+r - -20
+r hy -20
+r char173 -20
+r g -18
+r , -40
+v . -65
+v o -20
+v e -15
+v , -65
+v a -25
+w . -65
+w o -10
+w , -65
+w a -10
+x e -15
+y . -65
+y , -65
+charset
+ha 469,662 2 0000 asciicircum
+ti 541,323 0 0001 asciitilde
+vS 556,886,14 2 0002 Scaron
+vZ 611,886 2 0003 Zcaron
+vs 389,674,10 2 0004 scaron
+vz 444,674 2 0005 zcaron
+:Y 722,835 2 0006 Ydieresis
+tm 980,662 2 0007 trademark
+aq 180,676 2 0010 quotesingle
+space 250 0 0040
+! 333,676,9 2 0041 exclam
+" 408,676 2 0042 quotedbl
+# 500,662 2 0043 numbersign
+sh "
+$ 500,727,87 2 0044 dollar
+Do "
+% 833,676,13 2 0045 percent
+& 778,676,13 2 0046 ampersand
+' 333,676 2 0047 quoteright
+( 333,676,177 2 0050 parenleft
+) 333,676,177 2 0051 parenright
+* 500,676 2 0052 asterisk
++ 564,506 0 0053 plus
+, 250,102,141 0 0054 comma
+- 333,257 0 0055 hyphen
+hy "
+char173 "
+. 250,100,11 0 0056 period
+/ 278,676,14 2 0057 slash
+sl "
+0 500,676,14 2 0060 zero
+1 500,676 2 0061 one
+2 500,676 2 0062 two
+3 500,676,14 2 0063 three
+4 500,676 2 0064 four
+5 500,688,14 2 0065 five
+6 500,684,14 2 0066 six
+7 500,662,8 2 0067 seven
+8 500,676,14 2 0070 eight
+9 500,676,22 2 0071 nine
+: 278,459,11 0 0072 colon
+; 278,459,141 0 0073 semicolon
+< 564,514,8 0 0074 less
+= 564,386 0 0075 equal
+> 564,514,8 0 0076 greater
+? 444,676,8 2 0077 question
+@ 921,676,14 2 0100 at
+at "
+A 722,674 2 0101 A
+B 667,662 2 0102 B
+C 667,676,14 2 0103 C
+D 722,662 2 0104 D
+E 611,662 2 0105 E
+F 556,662 2 0106 F
+G 722,676,14 2 0107 G
+H 722,662 2 0110 H
+I 333,662 2 0111 I
+J 389,662,14 2 0112 J
+K 722,662 2 0113 K
+L 611,662 2 0114 L
+M 889,662 2 0115 M
+N 722,662,11 2 0116 N
+O 722,676,14 2 0117 O
+P 556,662 2 0120 P
+Q 722,676,178 2 0121 Q
+R 667,662 2 0122 R
+S 556,676,14 2 0123 S
+T 611,662 2 0124 T
+U 722,662,14 2 0125 U
+V 722,662,11 2 0126 V
+W 944,662,11 2 0127 W
+X 722,662 2 0130 X
+Y 722,662 2 0131 Y
+Z 611,662 2 0132 Z
+[ 333,662,156 2 0133 bracketleft
+lB "
+\ 278,676,14 2 0134 backslash
+rs "
+] 333,662,156 2 0135 bracketright
+rB "
+a^ 333,674 2 0136 circumflex
+^ "
+_ 500,0,125 0 0137 underscore
+` 333,676 2 0140 quoteleft
+oq "
+a 444,460,10 0 0141 a
+b 500,683,10 2 0142 b
+c 444,460,10 0 0143 c
+d 500,683,10 2 0144 d
+e 444,460,10 0 0145 e
+f 333,683 2 0146 f
+g 500,460,218 1 0147 g
+h 500,683 2 0150 h
+i 278,683 2 0151 i
+j 278,683,218 3 0152 j
+k 500,683 2 0153 k
+l 278,683 2 0154 l
+m 778,460 0 0155 m
+n 500,460 0 0156 n
+o 500,460,10 0 0157 o
+p 500,460,217 1 0160 p
+q 500,460,217 1 0161 q
+r 333,460 0 0162 r
+s 389,460,10 0 0163 s
+t 278,579,10 2 0164 t
+u 500,450,10 0 0165 u
+v 500,450,14 0 0166 v
+w 722,450,14 0 0167 w
+x 500,450 0 0170 x
+y 500,450,218 1 0171 y
+z 444,450 0 0172 z
+lC 480,680,181 2 0173 braceleft
+{ "
+ba 200,676,14 2 0174 bar
+| "
+rC 480,680,181 2 0175 braceright
+} "
+a~ 333,638 2 0176 tilde
+~ "
+bq 333,102,141 0 0200 quotesinglbase
+Fo 500,416 0 0201 guillemotleft
+char171 "
+Fc 500,416 0 0202 guillemotright
+char187 "
+bu 350,466 0 0203 bullet
+Fn 500,676,189 2 0204 florin
+f/ 167,676,14 2 0205 fraction
+%0 1000,706,19 2 0206 perthousand
+dg 500,676,149 2 0207 dagger
+dd 500,676,153 2 0210 daggerdbl
+en 500,250 0 0211 endash
+em 1000,250 0 0212 emdash
+fi 556,683 2 0214 fi
+fl 556,683 2 0215 fl
+.i 278,460 0 0220 dotlessi
+ga 333,678 2 0222 grave
+a" 333,678 2 0223 hungarumlaut
+a. 333,623 2 0224 dotaccent
+ab 333,664 2 0225 breve
+ah 333,674 2 0226 caron
+ao 333,711 2 0227 ring
+ho 333,0,165 0 0230 ogonek
+lq 444,676 2 0231 quotedblleft
+rq 444,676 2 0232 quotedblright
+oe 722,460,10 0 0233 oe
+/l 278,683 2 0234 lslash
+Bq 444,102,141 0 0235 quotedblbase
+OE 889,668,6 2 0236 OE
+/L 611,662 2 0237 Lslash
+r! 333,467,218 1 0241 exclamdown
+char161 "
+ct 500,579,138 2 0242 cent
+char162 "
+Po 500,676,8 2 0243 sterling
+char163 "
+Cs 500,602 2 0244 currency
+char164 "
+Ye 500,662 2 0245 yen
+char165 "
+bb 200,676,14 2 0246 brokenbar
+char166 "
+sc 500,676,148 2 0247 section
+char167 "
+ad 333,623 2 0250 dieresis
+char168 "
+co 760,676,14 2 0251 copyright
+char169 "
+Of 276,676 2 0252 ordfeminine
+char170 "
+fo 333,416 0 0253 guilsinglleft
+no 564,386 0 0254 logicalnot
+char172 "
+\- 564,286 0 0255 minus
+rg 760,676,14 2 0256 registered
+char174 "
+a- 333,601 2 0257 macron
+char175 "
+de 400,676 2 0260 degree
+char176 "
+char177 564,506 0 0261 plusminus
+S2 300,676 2 0262 twosuperior
+char178 "
+S3 300,676 2 0263 threesuperior
+char179 "
+aa 333,678 2 0264 acute
+char180 "
+char181 500,450,218 1 0265 mu
+ps 453,662,154 2 0266 paragraph
+char182 "
+char183 250,310 0 0267 periodcentered
+ac 333,0,215 0 0270 cedilla
+char184 "
+S1 300,676 2 0271 onesuperior
+char185 "
+Om 310,676 2 0272 ordmasculine
+char186 "
+fc 333,416 0 0273 guilsinglright
+14 750,676,14 2 0274 onequarter
+char188 "
+12 750,676,14 2 0275 onehalf
+char189 "
+34 750,676,14 2 0276 threequarters
+char190 "
+r? 444,466,218 1 0277 questiondown
+char191 "
+`A 722,890 2 0300 Agrave
+char192 "
+'A 722,890 2 0301 Aacute
+char193 "
+^A 722,886 2 0302 Acircumflex
+char194 "
+~A 722,850 2 0303 Atilde
+char195 "
+:A 722,835 2 0304 Adieresis
+char196 "
+oA 722,898 2 0305 Aring
+char197 "
+AE 889,662 2 0306 AE
+char198 "
+,C 667,676,215 2 0307 Ccedilla
+char199 "
+`E 611,890 2 0310 Egrave
+char200 "
+'E 611,890 2 0311 Eacute
+char201 "
+^E 611,886 2 0312 Ecircumflex
+char202 "
+:E 611,835 2 0313 Edieresis
+char203 "
+`I 333,890 2 0314 Igrave
+char204 "
+'I 333,890 2 0315 Iacute
+char205 "
+^I 333,886 2 0316 Icircumflex
+char206 "
+:I 333,835 2 0317 Idieresis
+char207 "
+-D 722,662 2 0320 Eth
+char208 "
+~N 722,850,11 2 0321 Ntilde
+char209 "
+`O 722,890,14 2 0322 Ograve
+char210 "
+'O 722,890,14 2 0323 Oacute
+char211 "
+^O 722,886,14 2 0324 Ocircumflex
+char212 "
+~O 722,850,14 2 0325 Otilde
+char213 "
+:O 722,835,14 2 0326 Odieresis
+char214 "
+char215 564,497 0 0327 multiply
+/O 722,734,80 2 0330 Oslash
+char216 "
+`U 722,890,14 2 0331 Ugrave
+char217 "
+'U 722,890,14 2 0332 Uacute
+char218 "
+^U 722,886,14 2 0333 Ucircumflex
+char219 "
+:U 722,835,14 2 0334 Udieresis
+char220 "
+'Y 722,890 2 0335 Yacute
+char221 "
+TP 556,662 2 0336 Thorn
+char222 "
+ss 500,683,9 2 0337 germandbls
+char223 "
+`a 444,678,10 2 0340 agrave
+char224 "
+'a 444,678,10 2 0341 aacute
+char225 "
+^a 444,674,10 2 0342 acircumflex
+char226 "
+~a 444,638,10 2 0343 atilde
+char227 "
+:a 444,623,10 2 0344 adieresis
+char228 "
+oa 444,711,10 2 0345 aring
+char229 "
+ae 667,460,10 0 0346 ae
+char230 "
+,c 444,460,215 0 0347 ccedilla
+char231 "
+`e 444,678,10 2 0350 egrave
+char232 "
+'e 444,678,10 2 0351 eacute
+char233 "
+^e 444,674,10 2 0352 ecircumflex
+char234 "
+:e 444,623,10 2 0353 edieresis
+char235 "
+`i 278,678 2 0354 igrave
+char236 "
+'i 278,678 2 0355 iacute
+char237 "
+^i 278,674 2 0356 icircumflex
+char238 "
+:i 278,623 2 0357 idieresis
+char239 "
+Sd 500,686,10 2 0360 eth
+char240 "
+~n 500,638 2 0361 ntilde
+char241 "
+`o 500,678,10 2 0362 ograve
+char242 "
+'o 500,678,10 2 0363 oacute
+char243 "
+^o 500,674,10 2 0364 ocircumflex
+char244 "
+~o 500,638,10 2 0365 otilde
+char245 "
+:o 500,623,10 2 0366 odieresis
+char246 "
+char247 564,516,10 0 0367 divide
+/o 500,551,112 0 0370 oslash
+char248 "
+`u 500,678,10 2 0371 ugrave
+char249 "
+'u 500,678,10 2 0372 uacute
+char250 "
+^u 500,674,10 2 0373 ucircumflex
+char251 "
+:u 500,623,10 2 0374 udieresis
+char252 "
+'y 500,678,218 3 0375 yacute
+char253 "
+Tp 500,683,217 3 0376 thorn
+char254 "
+:y 500,623,218 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/ZCMI b/gnu/usr.bin/groff/devices/devps/ZCMI
new file mode 100644
index 000000000000..53e56fd7170b
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/ZCMI
@@ -0,0 +1,477 @@
+name ZCMI
+internalname ZapfChancery-MediumItalic
+slant 14
+spacewidth 220
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A ' -40
+A rq -40
+A U -10
+A T 10
+A Q 10
+A O 10
+A G -30
+A C 20
+D . -30
+D , -20
+D Y 10
+D A -10
+F . -40
+F i 10
+F , -30
+G . -20
+G , -10
+J . -20
+J , -10
+K u -20
+K o -20
+K e -20
+L y -10
+L ' -25
+L rq -25
+L W -10
+L V -20
+O . -20
+O , -10
+O Y 10
+O T 20
+O A -20
+P . -50
+P o -10
+P e -10
+P , -40
+P a -20
+P A -10
+Q U -10
+R Y 10
+R W 10
+R T 20
+T o -20
+T i 20
+T - -20
+T hy -20
+T char173 -20
+T h 20
+T e -20
+T a -20
+T O 30
+T A 10
+V . -100
+V o -20
+V e -20
+V , -90
+V a -20
+V O 10
+V G -20
+W . -50
+W o -20
+W i 10
+W h 10
+W e -20
+W , -40
+W a -20
+W O 10
+Y u -20
+Y . -50
+Y o -50
+Y i 10
+Y e -40
+Y , -40
+Y a -60
+b . -30
+b l -20
+b , -20
+b b -20
+c k -10
+, ' -70
+, rq -70
+d w -20
+d v -10
+d d -40
+e y 10
+f ' 30
+f rq 30
+f . -50
+f f -50
+f e -10
+f , -40
+f a -20
+g y 10
+g . -30
+g i 10
+g e 10
+g , -20
+g a 10
+k y 10
+k o -10
+k e -20
+m y 10
+m u 10
+n y 20
+o . -30
+o , -20
+p . -30
+p p -10
+p , -20
+. ' -80
+. rq -80
+lq ` 20
+lq oq 20
+lq A 10
+` ` -115
+` oq -115
+oq ` -115
+oq oq -115
+` A 10
+oq A 10
+' v 30
+' t 20
+' s -25
+' r 30
+' ' -115
+' rq 20
+' l 20
+r . -50
+r i 10
+r , -40
+s . -20
+s , -10
+v . -30
+v , -20
+w . -30
+w o 10
+w h 20
+w , -20
+charset
+ha 520,594,0,62,-82,62 2 0000 asciicircum
+ti 520,320,0,69,-73,69 0 0001 asciitilde
+vS 460,831,81,184,5,87 2 0002 Scaron
+vZ 620,831,19,99,8,87 2 0003 Zcaron
+vs 320,659,14,194,4,87 2 0004 scaron
+vz 440,659,14,124,24,87 2 0005 zcaron
+:Y 560,762,168,264,9,87 2 0006 Ydieresis
+tm 1000,594,0,96,-77,87 2 0007 trademark
+aq 160,610,0,105,-95,87 2 0010 quotesingle
+space 220 0 0040
+! 280,610,14,123,-69,87 2 0041 exclam
+" 220,610,0,163,-70,87 2 0042 quotedbl
+# 440,594,0,131,-33,87 2 0043 numbersign
+sh "
+$ 440,709,144,118,-10,87 2 0044 dollar
+Do "
+% 680,700,160,80,-82,80 2 0045 percent
+& 780,610,16,185,-76,87 2 0046 ampersand
+' 240,610,0,148,-118,87 2 0047 quoteright
+( 260,664,216,201,-46,87 2 0050 parenleft
+) 220,664,216,132,63,87 2 0051 parenright
+* 420,610,0,109,-89,87 2 0052 asterisk
++ 520,426,0,73,-67,73 0 0053 plus
+, 220,148,140,43,25,43 0 0054 comma
+- 280,248,0,104,-19,87 0 0055 hyphen
+hy "
+char173 "
+. 220,128,14,58,-52,58 0 0056 period
+/ 340,610,16,168,-24,87 2 0057 slash
+sl "
+0 440,610,16,148,-29,87 2 0060 zero
+1 440,610,0,38,9,38 2 0061 one
+2 440,610,16,95,33,87 2 0062 two
+3 440,610,16,95,49,87 2 0063 three
+4 440,610,35,109,-27,87 2 0064 four
+5 440,679,16,205,-10,87 2 0065 five
+6 440,610,16,166,-40,87 2 0066 six
+7 440,645,33,171,-107,87 2 0067 seven
+8 440,610,16,139,-15,87 2 0070 eight
+9 440,610,16,127,18,87 2 0071 nine
+: 260,438,14,86,-48,86 0 0072 colon
+; 240,438,140,109,21,87 0 0073 semicolon
+< 520,468,0,57,-89,57 0 0074 less
+= 520,340,0,73,-67,73 0 0075 equal
+> 520,468,0,57,-89,57 0 0076 greater
+? 380,610,14,125,-100,87 2 0077 question
+@ 700,610,16,103,-77,87 2 0100 at
+at "
+A 620,632,16,127,37,87 2 0101 A
+B 600,640,6,124,-35,87 2 0102 B
+C 520,610,16,161,-43,87 2 0103 C
+D 700,640,6,118,-36,87 2 0104 D
+E 620,618,12,139,-41,87 2 0105 E
+F 580,629,118,263,-70,87 2 0106 F
+G 620,610,242,139,-98,87 2 0107 G
+H 680,708,16,248,32,87 2 0110 H
+I 380,594,0,174,-49,87 2 0111 I
+J 400,594,147,188,64,87 2 0112 J
+K 660,610,153,234,-3,87 2 0113 K
+L 580,610,16,127,-3,87 2 0114 L
+M 840,722,16,230,-8,87 2 0115 M
+N 700,708,168,265,-35,87 2 0116 N
+O 600,610,16,110,-44,87 2 0117 O
+P 540,628,0,168,8,87 2 0120 P
+Q 600,610,177,225,-34,87 2 0121 Q
+R 600,640,168,255,-8,87 2 0122 R
+S 460,610,81,148,5,87 2 0123 S
+T 500,667,0,294,-13,87 2 0124 T
+U 740,617,16,102,-76,87 2 0125 U
+V 640,714,16,220,-74,87 2 0126 V
+W 880,723,16,216,-44,87 2 0127 W
+X 560,610,16,189,80,87 2 0130 X
+Y 560,647,168,264,9,87 2 0131 Y
+Z 620,624,19,99,8,87 2 0132 Z
+[ 240,655,207,215,63,87 2 0133 bracketleft
+lB "
+\ 480,610,16,94,-90,87 2 0134 backslash
+rs "
+] 320,655,207,121,77,87 2 0135 bracketright
+rB "
+a^ 340,649,0,153,-173,87 2 0136 circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 underscore
+` 240,610,0,149,-119,87 2 0140 quoteleft
+oq "
+a 420,438,15,115,-42,87 0 0141 a
+b 420,714,23,122,-32,87 2 0142 b
+c 340,438,14,116,-37,87 0 0143 c
+d 440,714,14,261,-52,87 2 0144 d
+e 340,438,14,113,-37,87 0 0145 e
+f 320,714,314,277,169,87 3 0146 f
+g 400,438,314,153,158,87 1 0147 g
+h 440,714,14,134,-5,87 2 0150 h
+i 240,635,14,151,-50,87 2 0151 i
+j 220,635,314,162,162,87 3 0152 j
+k 440,714,184,238,-37,87 2 0153 k
+l 240,714,14,290,-52,87 2 0154 l
+m 620,438,14,134,-36,87 0 0155 m
+n 460,438,14,134,-51,87 0 0156 n
+o 400,438,14,99,-37,87 0 0157 o
+p 440,432,314,94,73,87 1 0160 p
+q 400,510,300,140,-37,87 1 0161 q
+r 300,438,14,174,-51,87 0 0162 r
+s 320,438,14,133,4,87 0 0163 s
+t 320,539,14,156,-56,87 2 0164 t
+u 460,438,14,118,-52,87 0 0165 u
+v 440,488,14,143,-37,87 0 0166 v
+w 680,488,14,152,-37,87 0 0167 w
+x 420,438,195,219,-20,87 0 0170 x
+y 400,438,314,133,74,87 1 0171 y
+z 440,445,14,118,24,87 0 0172 z
+lC 240,655,207,193,-5,87 2 0173 braceleft
+{ "
+ba 520,714,16,0,-270 2 0174 bar
+| "
+rC 240,655,207,128,60,87 2 0175 braceright
+} "
+a~ 440,619,0,132,-193,87 2 0176 tilde
+~ "
+bq 180,146,121,61,29,61 0 0200 quotesinglbase
+Fo 340,414,0,66,-48,66 0 0201 guillemotleft
+char171 "
+Fc 380,414,0,45,-67,45 0 0202 guillemotright
+char187 "
+bu 600,445,0,0,-178 0 0203 bullet
+Fn 440,610,314,192,114,87 3 0204 florin
+f/ 60,610,16,310,231,87 2 0205 fraction
+%0 960,700,160,95,-62,87 2 0206 perthousand
+dg 460,610,37,158,-88,87 2 0207 dagger
+dd 480,610,59,103,-88,87 2 0210 daggerdbl
+en 500,239,0,115,-1,87 0 0211 endash
+em 1000,239,0,115,-1,87 0 0212 emdash
+fi 520,714,314,135,174,87 3 0214 fi
+fl 520,714,314,200,174,87 3 0215 fl
+.i 240,438,14,116,-50,87 0 0220 dotlessi
+ga 220,659,0,169,-143,87 2 0222 grave
+a" 400,659,0,145,-158,87 2 0223 hungarumlaut
+a. 220,610,0,158,-186,87 2 0224 dotaccent
+ab 440,631,0,111,-203,87 2 0225 breve
+ah 340,659,0,184,-204,87 2 0226 caron
+ao 300,659,0,166,-190,87 2 0227 ring
+ho 280,6,191,3,12,3 0 0230 ogonek
+lq 340,610,0,174,-119,87 2 0231 quotedblleft
+rq 360,610,0,143,-108,87 2 0232 quotedblright
+oe 560,438,14,118,-28,87 0 0233 oe
+/l 300,714,14,265,-71,87 2 0234 lslash
+Bq 280,146,121,51,64,51 0 0235 quotedblbase
+OE 820,610,16,139,-13,87 2 0236 OE
+/L 580,610,16,127,1,87 2 0237 Lslash
+r! 280,438,186,76,-22,76 0 0241 exclamdown
+char161 "
+ct 440,543,134,86,-72,86 2 0242 cent
+char162 "
+Po 440,610,52,116,66,87 2 0243 sterling
+char163 "
+Cs 440,509,0,84,0,84 0 0244 currency
+char164 "
+Ye 440,647,168,223,51,87 2 0245 yen
+char165 "
+bb 520,714,16,0,-270 2 0246 brokenbar
+char166 "
+sc 420,610,215,144,-3,87 2 0247 section
+char167 "
+ad 360,610,0,159,-193,87 2 0250 dieresis
+char168 "
+co 740,610,16,73,-87,73 2 0251 copyright
+char169 "
+Of 260,610,0,176,-61,87 2 0252 ordfeminine
+char170 "
+fo 240,414,0,68,-48,68 0 0253 guilsinglleft
+no 520,340,0,73,-67,73 0 0254 logicalnot
+char172 "
+\- 520,242,0,73,-67,73 0 0255 minus
+rg 740,610,16,73,-87,73 2 0256 registered
+char174 "
+a- 440,578,0,75,-172,75 2 0257 macron
+char175 "
+de 400,610,0,107,-121,87 2 0260 degree
+char176 "
+char177 520,436,0,73,-67,73 0 0261 plusminus
+S2 264,610,0,140,-22,87 2 0262 twosuperior
+char178 "
+S3 264,610,0,134,-9,87 2 0263 threesuperior
+char179 "
+aa 300,659,0,172,-215,87 2 0264 acute
+char180 "
+char181 460,438,314,113,43,87 1 0265 mu
+ps 500,594,199,188,-55,87 2 0266 paragraph
+char182 "
+char183 220,310,0,71,-89,71 0 0267 periodcentered
+ac 300,6,191,0,38 0 0270 cedilla
+char184 "
+S1 264,610,0,97,-33,87 2 0271 onesuperior
+char185 "
+Om 260,610,0,163,-78,87 2 0272 ordmasculine
+char186 "
+fc 260,414,0,56,-56,56 0 0273 guilsinglright
+14 660,610,16,92,-6,87 2 0274 onequarter
+char188 "
+12 660,610,16,92,-6,87 2 0275 onehalf
+char189 "
+34 660,610,16,96,11,87 2 0276 threequarters
+char190 "
+r? 400,438,186,37,-32,37 0 0277 questiondown
+char191 "
+`A 620,821,16,127,37,87 2 0300 Agrave
+char192 "
+'A 620,821,16,132,37,87 2 0301 Aacute
+char193 "
+^A 620,821,16,127,37,87 2 0302 Acircumflex
+char194 "
+~A 620,771,16,132,37,87 2 0303 Atilde
+char195 "
+:A 620,762,16,139,37,87 2 0304 Adieresis
+char196 "
+oA 620,831,16,127,37,87 2 0305 Aring
+char197 "
+AE 740,594,16,109,71,87 2 0306 AE
+char198 "
+,C 520,610,191,161,-43,87 2 0307 Ccedilla
+char199 "
+`E 620,821,12,139,-41,87 2 0310 Egrave
+char200 "
+'E 620,821,12,139,-41,87 2 0311 Eacute
+char201 "
+^E 620,821,12,139,-41,87 2 0312 Ecircumflex
+char202 "
+:E 620,762,12,139,-41,87 2 0313 Edieresis
+char203 "
+`I 380,821,0,174,-49,87 2 0314 Igrave
+char204 "
+'I 380,821,0,202,-49,87 2 0315 Iacute
+char205 "
+^I 380,821,0,174,-49,87 2 0316 Icircumflex
+char206 "
+:I 380,762,0,189,-49,87 2 0317 Idieresis
+char207 "
+-D 700,640,6,118,-36,87 2 0320 Eth
+char208 "
+~N 700,761,168,265,-35,87 2 0321 Ntilde
+char209 "
+`O 600,821,16,110,-44,87 2 0322 Ograve
+char210 "
+'O 600,821,16,110,-44,87 2 0323 Oacute
+char211 "
+^O 600,821,16,110,-44,87 2 0324 Ocircumflex
+char212 "
+~O 600,761,16,110,-44,87 2 0325 Otilde
+char213 "
+:O 600,762,16,110,-44,87 2 0326 Odieresis
+char214 "
+char215 520,410,0,57,-83,57 0 0327 multiply
+/O 660,672,78,141,-33,87 2 0330 Oslash
+char216 "
+`U 740,821,16,102,-76,87 2 0331 Ugrave
+char217 "
+'U 740,821,16,102,-76,87 2 0332 Uacute
+char218 "
+^U 740,821,16,102,-76,87 2 0333 Ucircumflex
+char219 "
+:U 740,762,16,102,-76,87 2 0334 Udieresis
+char220 "
+'Y 560,821,168,264,9,87 2 0335 Yacute
+char221 "
+TP 540,623,0,157,-2,87 2 0336 Thorn
+char222 "
+ss 420,714,314,172,177,87 3 0337 germandbls
+char223 "
+`a 420,659,15,115,-42,87 2 0340 agrave
+char224 "
+'a 420,659,15,122,-42,87 2 0341 aacute
+char225 "
+^a 420,649,15,115,-42,87 2 0342 acircumflex
+char226 "
+~a 420,619,15,152,-42,87 2 0343 atilde
+char227 "
+:a 420,610,15,115,-42,87 2 0344 adieresis
+char228 "
+oa 420,659,15,115,-42,87 2 0345 aring
+char229 "
+ae 540,468,14,134,-17,87 0 0346 ae
+char230 "
+,c 340,438,191,116,-12,87 0 0347 ccedilla
+char231 "
+`e 340,659,14,113,-37,87 2 0350 egrave
+char232 "
+'e 340,659,14,172,-37,87 2 0351 eacute
+char233 "
+^e 340,649,14,143,-37,87 2 0352 ecircumflex
+char234 "
+:e 340,610,14,159,-37,87 2 0353 edieresis
+char235 "
+`i 240,659,14,116,-50,87 2 0354 igrave
+char236 "
+'i 240,659,14,202,-50,87 2 0355 iacute
+char237 "
+^i 240,649,14,173,-50,87 2 0356 icircumflex
+char238 "
+:i 240,610,14,179,-50,87 2 0357 idieresis
+char239 "
+Sd 400,714,14,172,-37,87 2 0360 eth
+char240 "
+~n 460,619,14,134,-51,87 2 0361 ntilde
+char241 "
+`o 400,659,14,99,-37,87 2 0362 ograve
+char242 "
+'o 400,659,14,132,-37,87 2 0363 oacute
+char243 "
+^o 400,649,14,103,-37,87 2 0364 ocircumflex
+char244 "
+~o 400,619,14,152,-37,87 2 0365 otilde
+char245 "
+:o 400,610,14,129,-37,87 2 0366 odieresis
+char246 "
+char247 520,440,14,73,-67,73 0 0367 divide
+/o 440,488,64,150,4,87 0 0370 oslash
+char248 "
+`u 460,659,14,118,-52,87 2 0371 ugrave
+char249 "
+'u 460,659,14,118,-52,87 2 0372 uacute
+char250 "
+^u 460,649,14,118,-52,87 2 0373 ucircumflex
+char251 "
+:u 460,610,14,118,-52,87 2 0374 udieresis
+char252 "
+'y 400,659,314,133,74,87 3 0375 yacute
+char253 "
+Tp 440,714,314,115,88,87 3 0376 thorn
+char254 "
+:y 400,610,314,133,74,87 3 0377 ydieresis
+char255 "
diff --git a/gnu/usr.bin/groff/devices/devps/ZD b/gnu/usr.bin/groff/devices/devps/ZD
new file mode 100644
index 000000000000..c2bd4eb8ff4d
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/ZD
@@ -0,0 +1,193 @@
+name ZD
+internalname ZapfDingbats
+special
+spacewidth 278
+charset
+space 278 0 0040
+--- 974,621 3 0041 a1
+--- 961,611 3 0042 a2
+--- 974,621 3 0043 a202
+--- 980,692 3 0044 a3
+--- 719,566 3 0045 a4
+--- 789,705,14 3 0046 a5
+--- 790,705,14 3 0047 a119
+--- 791,705,13 3 0050 a118
+--- 690,553 3 0051 a117
+--- 960,568 3 0052 a11
+rh 939,559 3 0053 a12
+--- 549,705,11 3 0054 a13
+--- 855,632 3 0055 a14
+--- 911,642 3 0056 a15
+--- 933,550 3 0057 a16
+--- 911,642 3 0060 a105
+--- 945,553 3 0061 a17
+--- 974,587 3 0062 a18
+OK 755,705,13 3 0063 a19
+--- 846,705,14 3 0064 a20
+--- 762,692 3 0065 a21
+--- 761,692 3 0066 a22
+--- 571,661,68 3 0067 a23
+--- 677,705,13 3 0070 a24
+--- 763,692 3 0071 a25
+--- 760,692 3 0072 a26
+--- 759,692 3 0073 a27
+--- 754,692 3 0074 a28
+--- 494,692 3 0075 a6
+--- 552,692 3 0076 a7
+--- 537,692 3 0077 a8
+--- 577,596 3 0100 a9
+--- 692,705,14 3 0101 a10
+--- 786,705,14 3 0102 a29
+--- 788,705,14 3 0103 a30
+--- 788,705,14 3 0104 a31
+--- 790,705,14 3 0105 a32
+--- 793,705,13 3 0106 a33
+--- 794,705,13 3 0107 a34
+--- 816,705,14 3 0110 a35
+--- 823,705,14 3 0111 a36
+--- 789,705,14 3 0112 a37
+--- 841,705,14 3 0113 a38
+--- 823,705,14 3 0114 a39
+--- 833,705,14 3 0115 a40
+--- 816,705,13 3 0116 a41
+--- 831,705,14 3 0117 a42
+--- 923,705,14 3 0120 a43
+--- 744,692 3 0121 a44
+--- 723,692 3 0122 a45
+--- 749,692 3 0123 a46
+--- 790,705,14 3 0124 a47
+--- 792,705,14 3 0125 a48
+--- 695,706,14 3 0126 a49
+--- 776,699,6 3 0127 a50
+--- 768,699,7 3 0130 a51
+--- 792,705,14 3 0131 a52
+--- 759,692 3 0132 a53
+--- 707,704,13 3 0133 a54
+--- 708,705,14 3 0134 a55
+--- 682,705,14 3 0135 a56
+--- 701,705,14 3 0136 a57
+--- 826,705,14 3 0137 a58
+--- 815,705,14 3 0140 a59
+--- 789,705,14 3 0141 a60
+--- 789,705,14 3 0142 a61
+--- 707,705,14 3 0143 a62
+--- 687,692 3 0144 a63
+--- 696,691 3 0145 a64
+--- 689,692 3 0146 a65
+--- 786,705,14 3 0147 a66
+--- 787,705,14 3 0150 a67
+--- 713,705,14 3 0151 a68
+--- 791,705,14 3 0152 a69
+--- 785,705,14 3 0153 a70
+--- 791,705,14 3 0154 a71
+--- 873,705,14 3 0155 a72
+--- 761,692 3 0156 a73
+--- 762,692 3 0157 a74
+--- 762,692 3 0160 a203
+--- 759,692 3 0161 a75
+--- 759,692 3 0162 a204
+--- 892,705 3 0163 a76
+--- 892,692,14 3 0164 a77
+--- 788,705,14 3 0165 a78
+--- 784,705,14 3 0166 a79
+--- 438,705,14 3 0167 a81
+--- 138,692 3 0170 a82
+--- 277,692 3 0171 a83
+--- 415,692 3 0172 a84
+--- 392,705 3 0173 a97
+--- 392,705 3 0174 a98
+--- 668,705 3 0175 a99
+--- 668,705 3 0176 a100
+--- 732,806,143 3 0241 a101
+--- 544,706,14 3 0242 a102
+--- 544,705,14 3 0243 a103
+--- 910,651 3 0244 a104
+--- 667,705,14 3 0245 a106
+--- 760,705,14 3 0246 a107
+--- 760,569 3 0247 a108
+--- 776,705 3 0250 a112
+--- 595,705,14 3 0251 a111
+--- 694,705,14 3 0252 a110
+--- 626,705 3 0253 a109
+--- 788,705,14 3 0254 a120
+--- 788,705,14 3 0255 a121
+--- 788,705,14 3 0256 a122
+--- 788,705,14 3 0257 a123
+--- 788,705,14 3 0260 a124
+--- 788,705,14 3 0261 a125
+--- 788,705,14 3 0262 a126
+--- 788,705,14 3 0263 a127
+--- 788,705,14 3 0264 a128
+--- 788,705,14 3 0265 a129
+--- 788,705,14 3 0266 a130
+--- 788,705,14 3 0267 a131
+--- 788,705,14 3 0270 a132
+--- 788,705,14 3 0271 a133
+--- 788,705,14 3 0272 a134
+--- 788,705,14 3 0273 a135
+--- 788,705,14 3 0274 a136
+--- 788,705,14 3 0275 a137
+--- 788,705,14 3 0276 a138
+--- 788,705,14 3 0277 a139
+--- 788,705,14 3 0300 a140
+--- 788,705,14 3 0301 a141
+--- 788,705,14 3 0302 a142
+--- 788,705,14 3 0303 a143
+--- 788,705,14 3 0304 a144
+--- 788,705,14 3 0305 a145
+--- 788,705,14 3 0306 a146
+--- 788,705,14 3 0307 a147
+--- 788,705,14 3 0310 a148
+--- 788,705,14 3 0311 a149
+--- 788,705,14 3 0312 a150
+--- 788,705,14 3 0313 a151
+--- 788,705,14 3 0314 a152
+--- 788,705,14 3 0315 a153
+--- 788,705,14 3 0316 a154
+--- 788,705,14 3 0317 a155
+--- 788,705,14 3 0320 a156
+--- 788,705,14 3 0321 a157
+--- 788,705,14 3 0322 a158
+--- 788,705,14 3 0323 a159
+--- 894,634 3 0324 a160
+--- 838,540 3 0325 a161
+--- 1016,540 3 0326 a163
+--- 458,820,127 3 0327 a164
+--- 748,597 3 0330 a196
+--- 924,552 3 0331 a165
+--- 748,597 3 0332 a192
+--- 918,526 3 0333 a166
+--- 927,660 3 0334 a167
+--- 928,562 3 0335 a168
+--- 928,563 3 0336 a169
+--- 834,537 3 0337 a170
+--- 873,599 3 0340 a171
+--- 828,588 3 0341 a172
+--- 924,594 3 0342 a173
+--- 924,594 3 0343 a162
+--- 917,692 3 0344 a174
+--- 930,608 3 0345 a175
+--- 931,608 3 0346 a176
+--- 463,791,99 3 0347 a177
+--- 883,623 3 0350 a178
+--- 836,648 3 0351 a179
+--- 836,648 3 0352 a193
+--- 867,591 3 0353 a180
+--- 867,591 3 0354 a199
+--- 696,648 3 0355 a181
+--- 696,648 3 0356 a200
+--- 874,619 3 0357 a182
+--- 874,615 3 0361 a201
+--- 760,692 3 0362 a183
+--- 946,533 3 0363 a184
+--- 771,655 3 0364 a197
+--- 865,481 3 0365 a185
+--- 771,655 3 0366 a194
+--- 888,712,19 3 0367 a198
+--- 967,568 3 0370 a186
+--- 888,712,19 3 0371 a195
+--- 831,579 3 0372 a187
+--- 873,578 3 0373 a188
+--- 927,542 3 0374 a189
+--- 970,616 3 0375 a190
+--- 918,593 3 0376 a191
diff --git a/gnu/usr.bin/groff/devices/devps/ZDR b/gnu/usr.bin/groff/devices/devps/ZDR
new file mode 100644
index 000000000000..3b7f0a64cddf
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/ZDR
@@ -0,0 +1,193 @@
+name ZDR
+internalname ZapfDingbats-Reverse
+special
+spacewidth 278
+charset
+space 278 0 0040
+--- 974,621 3 0041 a1
+--- 961,611 3 0042 a2
+--- 974,621 3 0043 a202
+--- 980,692 3 0044 a3
+--- 719,566 3 0045 a4
+--- 789,705,14 3 0046 a5
+--- 790,705,14 3 0047 a119
+--- 791,705,13 3 0050 a118
+--- 690,553 3 0051 a117
+--- 960,568 3 0052 a11
+lh 939,559 3 0053 a12
+--- 549,705,11 3 0054 a13
+--- 855,632 3 0055 a14
+--- 911,642 3 0056 a15
+--- 933,550 3 0057 a16
+--- 911,642 3 0060 a105
+--- 945,553 3 0061 a17
+--- 974,587 3 0062 a18
+--- 755,705,13 3 0063 a19
+--- 846,705,14 3 0064 a20
+--- 762,692 3 0065 a21
+--- 761,692 3 0066 a22
+--- 571,661,68 3 0067 a23
+--- 677,705,13 3 0070 a24
+--- 763,692 3 0071 a25
+--- 760,692 3 0072 a26
+--- 759,692 3 0073 a27
+--- 754,692 3 0074 a28
+--- 494,692 3 0075 a6
+--- 552,692 3 0076 a7
+--- 537,692 3 0077 a8
+--- 577,596 3 0100 a9
+--- 692,705,14 3 0101 a10
+--- 786,705,14 3 0102 a29
+--- 788,705,14 3 0103 a30
+--- 788,705,14 3 0104 a31
+--- 790,705,14 3 0105 a32
+--- 793,705,13 3 0106 a33
+--- 794,705,13 3 0107 a34
+--- 816,705,14 3 0110 a35
+--- 823,705,14 3 0111 a36
+--- 789,705,14 3 0112 a37
+--- 841,705,14 3 0113 a38
+--- 823,705,14 3 0114 a39
+--- 833,705,14 3 0115 a40
+--- 816,705,13 3 0116 a41
+--- 831,705,14 3 0117 a42
+--- 923,705,14 3 0120 a43
+--- 744,692 3 0121 a44
+--- 723,692 3 0122 a45
+--- 749,692 3 0123 a46
+--- 790,705,14 3 0124 a47
+--- 792,705,14 3 0125 a48
+--- 695,706,14 3 0126 a49
+--- 776,699,6 3 0127 a50
+--- 768,699,7 3 0130 a51
+--- 792,705,14 3 0131 a52
+--- 759,692 3 0132 a53
+--- 707,704,13 3 0133 a54
+--- 708,705,14 3 0134 a55
+--- 682,705,14 3 0135 a56
+--- 701,705,14 3 0136 a57
+--- 826,705,14 3 0137 a58
+--- 815,705,14 3 0140 a59
+--- 789,705,14 3 0141 a60
+--- 789,705,14 3 0142 a61
+--- 707,705,14 3 0143 a62
+--- 687,692 3 0144 a63
+--- 696,691 3 0145 a64
+--- 689,692 3 0146 a65
+--- 786,705,14 3 0147 a66
+--- 787,705,14 3 0150 a67
+--- 713,705,14 3 0151 a68
+--- 791,705,14 3 0152 a69
+--- 785,705,14 3 0153 a70
+--- 791,705,14 3 0154 a71
+--- 873,705,14 3 0155 a72
+--- 761,692 3 0156 a73
+--- 762,692 3 0157 a74
+--- 762,692 3 0160 a203
+--- 759,692 3 0161 a75
+--- 759,692 3 0162 a204
+--- 892,705 3 0163 a76
+--- 892,692,14 3 0164 a77
+--- 788,705,14 3 0165 a78
+--- 784,705,14 3 0166 a79
+--- 438,705,14 3 0167 a81
+--- 138,692 3 0170 a82
+--- 277,692 3 0171 a83
+--- 415,692 3 0172 a84
+--- 392,705 3 0173 a97
+--- 392,705 3 0174 a98
+--- 668,705 3 0175 a99
+--- 668,705 3 0176 a100
+--- 732,806,143 3 0241 a101
+--- 544,706,14 3 0242 a102
+--- 544,705,14 3 0243 a103
+--- 910,651 3 0244 a104
+--- 667,705,14 3 0245 a106
+--- 760,705,14 3 0246 a107
+--- 760,569 3 0247 a108
+--- 776,705 3 0250 a112
+--- 595,705,14 3 0251 a111
+--- 694,705,14 3 0252 a110
+--- 626,705 3 0253 a109
+--- 788,705,14 3 0254 a120
+--- 788,705,14 3 0255 a121
+--- 788,705,14 3 0256 a122
+--- 788,705,14 3 0257 a123
+--- 788,705,14 3 0260 a124
+--- 788,705,14 3 0261 a125
+--- 788,705,14 3 0262 a126
+--- 788,705,14 3 0263 a127
+--- 788,705,14 3 0264 a128
+--- 788,705,14 3 0265 a129
+--- 788,705,14 3 0266 a130
+--- 788,705,14 3 0267 a131
+--- 788,705,14 3 0270 a132
+--- 788,705,14 3 0271 a133
+--- 788,705,14 3 0272 a134
+--- 788,705,14 3 0273 a135
+--- 788,705,14 3 0274 a136
+--- 788,705,14 3 0275 a137
+--- 788,705,14 3 0276 a138
+--- 788,705,14 3 0277 a139
+--- 788,705,14 3 0300 a140
+--- 788,705,14 3 0301 a141
+--- 788,705,14 3 0302 a142
+--- 788,705,14 3 0303 a143
+--- 788,705,14 3 0304 a144
+--- 788,705,14 3 0305 a145
+--- 788,705,14 3 0306 a146
+--- 788,705,14 3 0307 a147
+--- 788,705,14 3 0310 a148
+--- 788,705,14 3 0311 a149
+--- 788,705,14 3 0312 a150
+--- 788,705,14 3 0313 a151
+--- 788,705,14 3 0314 a152
+--- 788,705,14 3 0315 a153
+--- 788,705,14 3 0316 a154
+--- 788,705,14 3 0317 a155
+--- 788,705,14 3 0320 a156
+--- 788,705,14 3 0321 a157
+--- 788,705,14 3 0322 a158
+--- 788,705,14 3 0323 a159
+--- 894,634 3 0324 a160
+--- 838,540 3 0325 a161
+--- 1016,540 3 0326 a163
+--- 458,820,127 3 0327 a164
+--- 748,597 3 0330 a196
+--- 924,552 3 0331 a165
+--- 748,597 3 0332 a192
+--- 918,526 3 0333 a166
+--- 927,660 3 0334 a167
+--- 928,562 3 0335 a168
+--- 928,563 3 0336 a169
+--- 834,537 3 0337 a170
+--- 873,599 3 0340 a171
+--- 828,588 3 0341 a172
+--- 924,594 3 0342 a173
+--- 924,594 3 0343 a162
+--- 917,692 3 0344 a174
+--- 930,608 3 0345 a175
+--- 931,608 3 0346 a176
+--- 463,791,99 3 0347 a177
+--- 883,623 3 0350 a178
+--- 836,648 3 0351 a179
+--- 836,648 3 0352 a193
+--- 867,591 3 0353 a180
+--- 867,591 3 0354 a199
+--- 696,648 3 0355 a181
+--- 696,648 3 0356 a200
+--- 874,619 3 0357 a182
+--- 874,615 3 0361 a201
+--- 760,692 3 0362 a183
+--- 946,533 3 0363 a184
+--- 771,655 3 0364 a197
+--- 865,481 3 0365 a185
+--- 771,655 3 0366 a194
+--- 888,712,19 3 0367 a198
+--- 967,568 3 0370 a186
+--- 888,712,19 3 0371 a195
+--- 831,579 3 0372 a187
+--- 873,578 3 0373 a188
+--- 927,542 3 0374 a189
+--- 970,616 3 0375 a190
+--- 918,593 3 0376 a191
diff --git a/gnu/usr.bin/groff/devices/devps/download b/gnu/usr.bin/groff/devices/devps/download
new file mode 100644
index 000000000000..b98885cdbbab
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/download
@@ -0,0 +1,5 @@
+# List of downloadable fonts
+# PostScript-name Filename
+
+Symbol-Slanted symbolsl.pfa
+ZapfDingbats-Reverse zapfdr.pfa
diff --git a/gnu/usr.bin/groff/devices/devps/generate/Makefile b/gnu/usr.bin/groff/devices/devps/generate/Makefile
new file mode 100644
index 000000000000..3382cc60a941
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/Makefile
@@ -0,0 +1,224 @@
+#Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff is free software; you can redistribute 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.
+#
+#groff is distributed in the hope that it will be useful, but WITHOUT ANY
+#WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+#for more details.
+#
+#You should have received a copy of the GNU General Public License along
+#with groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# This is set up so you can do
+# make -f generate/Makefile
+# in the parent directory of this directory.
+
+# Directory containing AFM files. Must not be current directory.
+# Either long names (eg Times-Roman.afm) or short names (eg timesr.afm)
+# may be used. See the afmname script.
+afmdir=/usr/local/afm
+srcdir=generate
+
+SPECIALFONTS=S
+DINGBATSFONTS=ZD ZDR
+GREEKFONTS=SS
+TEXTFONTS=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
+
+FONTS=$(TEXTFONTS) $(SPECIALFONTS) $(GREEKFONTS) $(DINGBATSFONTS)
+
+DESC=$(srcdir)/../DESC
+AFMTODIT=afmtodit -d$(DESC)
+IFLAG=-i 50
+NOLIGFLAG=-n
+TEXTENC=$(srcdir)/../text.enc
+EFLAG=-e $(TEXTENC)
+TEXTMAP=$(srcdir)/textmap
+SHELL=/bin/sh
+AFMNAME=$(SHELL) $(srcdir)/afmname
+
+all: $(FONTS)
+
+TR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Times-Roman.afm` $(TEXTMAP) $@
+
+TB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Times-Bold.afm` $(TEXTMAP) $@
+
+TI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) -a 7 \
+ `$(AFMNAME) $(afmdir)/Times-Italic.afm` $(TEXTMAP) $@
+
+TBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Times-BoldItalic.afm` $(TEXTMAP) $@
+
+HR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica.afm` $(TEXTMAP) $@
+
+HB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Bold.afm` $(TEXTMAP) $@
+
+HI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Oblique.afm` $(TEXTMAP) $@
+
+HBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-BoldOblique.afm` $(TEXTMAP) $@
+
+CR:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier.afm` $(TEXTMAP) $@
+
+CB:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier-Bold.afm` $(TEXTMAP) $@
+
+CI:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier-Oblique.afm` $(TEXTMAP) $@
+
+CBI:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier-BoldOblique.afm` $(TEXTMAP) $@
+
+PR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-Roman.afm` $(TEXTMAP) $@
+
+PB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-Bold.afm` $(TEXTMAP) $@
+
+PI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-Italic.afm` $(TEXTMAP) $@
+
+PBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-BoldItalic.afm` $(TEXTMAP) $@
+
+NR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-Roman.afm` $(TEXTMAP) $@
+
+NB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-Bold.afm` $(TEXTMAP) $@
+
+NI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-Italic.afm` $(TEXTMAP) $@
+
+NBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-BoldItalic.afm` $(TEXTMAP) $@
+
+BMR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-Light.afm` $(TEXTMAP) $@
+
+BMB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-Demi.afm` $(TEXTMAP) $@
+
+BMI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-LightItalic.afm` $(TEXTMAP) $@
+
+BMBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-DemiItalic.afm` $(TEXTMAP) $@
+
+AR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-Book.afm` $(TEXTMAP) $@
+
+AB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-Demi.afm` $(TEXTMAP) $@
+
+AI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-BookOblique.afm` $(TEXTMAP) $@
+
+ABI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-DemiOblique.afm` $(TEXTMAP) $@
+
+HNR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow.afm` $(TEXTMAP) $@
+
+HNB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow-Bold.afm` $(TEXTMAP) $@
+
+HNI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow-Oblique.afm` $(TEXTMAP) $@
+
+HNBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow-BoldOblique.afm` $(TEXTMAP) $@
+
+ZCMI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/ZapfChancery-MediumItalic.afm` $(TEXTMAP) $@
+
+ZD:
+ $(AFMTODIT) -s \
+ `$(AFMNAME) $(afmdir)/ZapfDingbats.afm` $(srcdir)/dingbatsmap $@
+
+SS: $(srcdir)/symbolsl.afm
+ $(AFMTODIT) -s $(IFLAG) $(srcdir)/symbolsl.afm $(srcdir)/lgreekmap $@
+
+S: symbol.afm
+ $(AFMTODIT) -s symbol.afm symbolmap $@
+
+ZDR: zapfdr.afm
+ $(AFMTODIT) -s zapfdr.afm $(srcdir)/dingbatsrmap $@
+
+symbol.afm: $(srcdir)/symbol.sed
+ -rm -f $@
+ sed -f $(srcdir)/symbol.sed `$(AFMNAME) $(afmdir)/Symbol.afm` >$@
+
+zapfdr.afm:
+ -rm -f $@
+ sed -e '/^FontName /s/ZapfDingbats/ZapfDingbats-Reverse/' \
+ `$(AFMNAME) $(afmdir)/ZapfDingbats.afm` >$@
+
+ZD: $(srcdir)/dingbatsmap
+ZDR: $(srcdir)/dingbatsrmap
+$(TEXTFONTS): $(TEXTMAP) $(TEXTENC)
+$(SPECIALFONTS): symbolmap
+$(GREEKFONTS): $(srcdir)/lgreekmap
+$(FONTS): $(DESC)
+
+symbolmap: $(TEXTMAP) $(srcdir)/symbolchars
+ cat $(TEXTMAP) $(srcdir)/symbolchars >$@
+
+clean:
+ -rm -f symbolmap symbol.afm zapfdr.afm
+
+realclean: clean
+ -rm -f $(FONTS)
+
+extraclean: realclean
+ -rm -f core *~ \#*
+
+.PHONY: all clean realclean extraclean
+
diff --git a/gnu/usr.bin/groff/devices/devps/generate/afmname b/gnu/usr.bin/groff/devices/devps/generate/afmname
new file mode 100644
index 000000000000..8503d46d8b50
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/afmname
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Fix the path name of an AFM file.
+if test -f "$1"
+then
+ echo "$1"
+else
+ echo `dirname $1`/`basename $1 .afm | awk -e '
+/^AvantGarde-Book$/ { print "avangbk" }
+/^AvantGarde-BookOblique$/ { print "avangbko" }
+/^AvantGarde-Demi$/ { print "avangd" }
+/^AvantGarde-DemiOblique$/ { print "avangdo" }
+/^Bookman-Demi$/ { print "bookmd" }
+/^Bookman-DemiItalic$/ { print "bookmdi" }
+/^Bookman-Light$/ { print "bookml" }
+/^Bookman-LightItalic$/ { print "bookmli" }
+/^Courier$/ { print "couri" }
+/^Courier-Bold$/ { print "courib" }
+/^Courier-BoldOblique$/ { print "couribo" }
+/^Courier-Oblique$/ { print "courio" }
+/^Helvetica$/ { print "helve" }
+/^Helvetica-Bold$/ { print "helveb" }
+/^Helvetica-BoldOblique$/ { print "helvebo" }
+/^Helvetica-Narrow$/ { print "helven" }
+/^Helvetica-Narrow-Bold$/ { print "helvenb" }
+/^Helvetica-Narrow-BoldOblique$/ { print "helvenbo" }
+/^Helvetica-Narrow-Oblique$/ { print "helveno" }
+/^Helvetica-Oblique$/ { print "helveo" }
+/^NewCenturySchlbk-Bold$/ { print "newcsb" }
+/^NewCenturySchlbk-BoldItalic$/ { print "newcsbi" }
+/^NewCenturySchlbk-Italic$/ { print "newcsi" }
+/^NewCenturySchlbk-Roman$/ { print "newcsr" }
+/^Palatino-Bold$/ { print "palatb" }
+/^Palatino-BoldItalic$/ { print "palatbi" }
+/^Palatino-Italic$/ { print "palati" }
+/^Palatino-Roman$/ { print "palatr" }
+/^Symbol$/ { print "symbol" }
+/^Times-Bold$/ { print "timesb" }
+/^Times-BoldItalic$/ { print "timesbi" }
+/^Times-Italic$/ { print "timesi" }
+/^Times-Roman$/ { print "timesr" }
+/^ZapfChancery-MediumItalic$/ { print "zapfcmi" }
+/^ZapfDingbats$/ { print "zapfd" }
+' `.afm
+fi
diff --git a/gnu/usr.bin/groff/devices/devps/generate/dingbatsmap b/gnu/usr.bin/groff/devices/devps/generate/dingbatsmap
new file mode 100644
index 000000000000..3a97fa99b05c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/dingbatsmap
@@ -0,0 +1,2 @@
+a19 OK
+a12 rh
diff --git a/gnu/usr.bin/groff/devices/devps/generate/dingbatsrmap b/gnu/usr.bin/groff/devices/devps/generate/dingbatsrmap
new file mode 100644
index 000000000000..ccc14cb2dfa0
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/dingbatsrmap
@@ -0,0 +1 @@
+a12 lh
diff --git a/gnu/usr.bin/groff/devices/devps/generate/lgreekmap b/gnu/usr.bin/groff/devices/devps/generate/lgreekmap
new file mode 100644
index 000000000000..0b0c19780854
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/lgreekmap
@@ -0,0 +1,28 @@
+alpha *a
+beta *b
+chi *x
+delta *d
+epsilon *e
+eta *y
+gamma *g
+iota *i
+kappa *k
+lambda *l
+mu *m
+nu *n
+omega *w
+omega1 +p
+omicron *o
+phi *f
+phi1 +f
+pi *p
+psi *q
+rho *r
+sigma *s
+tau *t
+theta *h
+theta1 +h
+upsilon *u
+xi *c
+zeta *z
+sigma1 ts
diff --git a/gnu/usr.bin/groff/devices/devps/generate/symbol.sed b/gnu/usr.bin/groff/devices/devps/generate/symbol.sed
new file mode 100644
index 000000000000..b4b02aba6a55
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/symbol.sed
@@ -0,0 +1,33 @@
+#! /bin/sed -f
+# Tweak the AFM file for the Symbol font.
+/^C .*[ ;]N bracketlefttp[ ;]/bx
+/^C .*[ ;]N bracketleftex[ ;]/bx
+/^C .*[ ;]N bracketleftbt[ ;]/bx
+/^C .*[ ;]N bracketrighttp[ ;]/bx
+/^C .*[ ;]N bracketrightex[ ;]/bx
+/^C .*[ ;]N bracketrightbt[ ;]/bx
+/^C .*[ ;]N bracelefttp[ ;]/bx
+/^C .*[ ;]N braceleftmid[ ;]/bx
+/^C .*[ ;]N braceleftbt[ ;]/bx
+/^C .*[ ;]N bracerighttp[ ;]/bx
+/^C .*[ ;]N bracerightmid[ ;]/bx
+/^C .*[ ;]N bracerightbt[ ;]/bx
+/^C .*[ ;]N braceex[ ;]/bx
+/^C .*[ ;]N parenleftex[ ;]/by
+/^C .*[ ;]N parenrightex[ ;]/by
+/^C .*[ ;]N parenleftbt[ ;]/bz
+/^C .*[ ;]N parenrightbt[ ;]/bz
+/^EndCharMetrics/a\
+italicCorrection integral 67\
+leftItalicCorrection integral 52\
+subscriptCorrection integral -10
+b
+:x
+s/B \([-0-9][0-9]*\) [-0-9][0-9]* \([-0-9][0-9]*\) [-0-9][0-9]*/B \1 -75 \2 925/
+b
+:y
+s/B \([-0-9][0-9]*\) [-0-9][0-9]* \([-0-9][0-9]*\) [-0-9][0-9]*/B \1 -80 \2 920/
+b
+:z
+s/B \([-0-9][0-9]*\) \([-0-9][0-9]*\) \([-0-9][0-9]*\) [-0-9][0-9]*/B \1 \2 \3 920/
+b
diff --git a/gnu/usr.bin/groff/devices/devps/generate/symbolchars b/gnu/usr.bin/groff/devices/devps/generate/symbolchars
new file mode 100644
index 000000000000..41ec3e466353
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/symbolchars
@@ -0,0 +1,60 @@
+plus pl
+minus mi
+plusminus +-
+equal eq
+divide di
+multiply mu
+arrowup arrowverttp
+arrowdown arrowvertbt
+Alpha *A
+Beta *B
+Chi *X
+Delta *D
+Epsilon *E
+Eta *Y
+Gamma *G
+Iota *I
+Kappa *K
+Lambda *L
+Mu *M
+Nu *N
+Omega *W
+Omicron *O
+Phi *F
+Pi *P
+Psi *Q
+Rho *R
+Sigma *S
+Tau *T
+Theta *H
+Upsilon1 *U
+Xi *C
+Zeta *Z
+alpha *a
+beta *b
+chi *x
+delta *d
+epsilon *e
+eta *y
+gamma *g
+iota *i
+kappa *k
+lambda *l
+mu *m
+nu *n
+omega *w
+omega1 +p
+omicron *o
+phi *f
+phi1 +f
+pi *p
+psi *q
+rho *r
+sigma *s
+sigma1 ts
+tau *t
+theta *h
+theta1 +h
+upsilon *u
+xi *c
+zeta *z
diff --git a/gnu/usr.bin/groff/devices/devps/generate/symbolsl.afm b/gnu/usr.bin/groff/devices/devps/generate/symbolsl.afm
new file mode 100644
index 000000000000..90939ada9697
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/symbolsl.afm
@@ -0,0 +1,203 @@
+StartFontMetrics 2.0
+FontName Symbol-Slanted
+Version 001.001
+FamilyName Symbol
+ItalicAngle -15.5
+IsFixedPitch false
+UnderlineThickness 54
+Weight Medium
+UnderlinePosition -98
+FullName Symbol
+FontBBox -241 -261 1250 899
+StartCharMetrics 189
+C 32 ; WX 223 ; N space ; B 223 0 223 0 ;
+C 33 ; WX 296 ; N exclam ; B 122 -15 383 599 ;
+C 34 ; WX 635 ; N universal ; B 223 0 801 627 ;
+C 35 ; WX 445 ; N numbersign ; B 71 -15 557 599 ;
+C 36 ; WX 489 ; N existential ; B 22 0 622 629 ;
+C 37 ; WX 741 ; N percent ; B 147 -32 766 583 ;
+C 38 ; WX 692 ; N ampersand ; B 68 -16 745 589 ;
+C 39 ; WX 391 ; N suchthat ; B 44 -15 450 444 ;
+C 40 ; WX 296 ; N parenleft ; B 89 -170 449 599 ;
+C 41 ; WX 296 ; N parenright ; B -22 -170 339 600 ;
+C 42 ; WX 445 ; N asteriskmath ; B 126 119 500 490 ;
+C 43 ; WX 489 ; N plus ; B 76 0 562 474 ;
+C 44 ; WX 223 ; N comma ; B 9 -136 183 93 ;
+C 45 ; WX 489 ; N minus ; B 74 207 556 256 ;
+C 46 ; WX 223 ; N period ; B 70 -15 174 85 ;
+C 47 ; WX 247 ; N slash ; B -5 -15 405 575 ;
+C 48 ; WX 445 ; N zero ; B 90 -15 537 610 ;
+C 49 ; WX 445 ; N one ; B 107 0 451 599 ;
+C 50 ; WX 445 ; N two ; B 22 0 524 611 ;
+C 51 ; WX 445 ; N three ; B 56 -16 510 611 ;
+C 52 ; WX 445 ; N four ; B 58 0 530 610 ;
+C 53 ; WX 445 ; N five ; B 36 -15 583 610 ;
+C 54 ; WX 445 ; N six ; B 87 -16 588 610 ;
+C 55 ; WX 445 ; N seven ; B 151 -15 585 599 ;
+C 56 ; WX 445 ; N eight ; B 82 -16 536 611 ;
+C 57 ; WX 445 ; N nine ; B 52 -15 535 609 ;
+C 58 ; WX 247 ; N colon ; B 81 -15 286 409 ;
+C 59 ; WX 247 ; N semicolon ; B 33 -136 296 409 ;
+C 60 ; WX 489 ; N less ; B 87 0 610 464 ;
+C 61 ; WX 489 ; N equal ; B 49 126 586 347 ;
+C 62 ; WX 489 ; N greater ; B 23 0 547 464 ;
+C 63 ; WX 395 ; N question ; B 163 -15 517 610 ;
+C 64 ; WX 489 ; N congruent ; B 10 0 597 423 ;
+C 65 ; WX 643 ; N Alpha ; B 3 0 614 599 ;
+C 66 ; WX 594 ; N Beta ; B 26 0 645 598 ;
+C 67 ; WX 643 ; N Chi ; B -8 0 798 599 ;
+C 68 ; WX 545 ; N Delta ; B 5 0 541 612 ;
+C 69 ; WX 544 ; N Epsilon ; B 28 0 688 599 ;
+C 70 ; WX 679 ; N Phi ; B 105 0 761 598 ;
+C 71 ; WX 537 ; N Gamma ; B 31 0 714 599 ;
+C 72 ; WX 643 ; N Eta ; B 35 0 836 599 ;
+C 73 ; WX 296 ; N Iota ; B 28 0 468 599 ;
+C 74 ; WX 562 ; N theta1 ; B 108 -15 645 614 ;
+C 75 ; WX 643 ; N Kappa ; B 31 0 778 598 ;
+C 76 ; WX 611 ; N Lambda ; B 5 0 610 612 ;
+C 77 ; WX 791 ; N Mu ; B 28 0 974 599 ;
+C 78 ; WX 643 ; N Nu ; B 26 -7 827 599 ;
+C 79 ; WX 643 ; N Omicron ; B 112 -15 747 610 ;
+C 80 ; WX 684 ; N Pi ; B 22 0 847 599 ;
+C 81 ; WX 659 ; N Theta ; B 112 -15 747 610 ;
+C 82 ; WX 495 ; N Rho ; B 25 0 645 599 ;
+C 83 ; WX 527 ; N Sigma ; B 5 0 663 599 ;
+C 84 ; WX 544 ; N Tau ; B 159 0 723 599 ;
+C 85 ; WX 614 ; N Upsilon ; B 175 0 804 599 ;
+C 86 ; WX 391 ; N sigma1 ; B 78 -208 492 445 ;
+C 87 ; WX 684 ; N Omega ; B 30 0 760 612 ;
+C 88 ; WX 574 ; N Xi ; B 36 0 700 598 ;
+C 89 ; WX 708 ; N Psi ; B 188 0 885 608 ;
+C 90 ; WX 544 ; N Zeta ; B 39 0 725 599 ;
+C 91 ; WX 296 ; N bracketleft ; B 34 -138 453 599 ;
+C 92 ; WX 768 ; N therefore ; B 160 0 645 426 ;
+C 93 ; WX 296 ; N bracketright ; B -14 -138 405 599 ;
+C 94 ; WX 586 ; N perpendicular ; B 13 0 596 600 ;
+C 95 ; WX 445 ; N underscore ; B -72 -224 390 -183 ;
+C 96 ; WX 445 ; N radicalex ; B 672 784 1224 816 ;
+C 97 ; WX 562 ; N alpha ; B 84 -15 658 445 ;
+C 98 ; WX 489 ; N beta ; B -7 -198 578 659 ;
+C 99 ; WX 489 ; N chi ; B -48 -206 573 445 ;
+C 100 ; WX 440 ; N delta ; B 83 -16 571 658 ;
+C 101 ; WX 391 ; N epsilon ; B 49 -17 468 447 ;
+C 102 ; WX 464 ; N phi ; B 78 -200 517 596 ;
+C 103 ; WX 366 ; N gamma ; B 92 -200 568 444 ;
+C 104 ; WX 537 ; N eta ; B 100 -180 555 457 ;
+C 105 ; WX 293 ; N iota ; B 97 -16 296 448 ;
+C 106 ; WX 537 ; N phi1 ; B 92 -199 604 444 ;
+C 107 ; WX 489 ; N kappa ; B 106 0 621 447 ;
+C 108 ; WX 489 ; N lambda ; B 21 -16 530 658 ;
+C 109 ; WX 513 ; N mu ; B -18 -198 533 445 ;
+C 110 ; WX 464 ; N nu ; B 119 -15 548 451 ;
+C 111 ; WX 489 ; N omicron ; B 86 -17 526 444 ;
+C 112 ; WX 489 ; N pi ; B 58 -18 599 433 ;
+C 113 ; WX 464 ; N theta ; B 103 -16 554 614 ;
+C 114 ; WX 489 ; N rho ; B -19 -205 521 444 ;
+C 115 ; WX 537 ; N sigma ; B 87 -19 662 445 ;
+C 116 ; WX 391 ; N tau ; B 95 -16 511 445 ;
+C 117 ; WX 513 ; N upsilon ; B 105 -15 558 451 ;
+C 118 ; WX 635 ; N omega1 ; B 78 -15 758 519 ;
+C 119 ; WX 611 ; N omega ; B 85 -16 687 445 ;
+C 120 ; WX 439 ; N xi ; B 70 -200 515 681 ;
+C 121 ; WX 611 ; N psi ; B 141 -203 759 445 ;
+C 122 ; WX 440 ; N zeta ; B 100 -200 580 673 ;
+C 123 ; WX 427 ; N braceleft ; B 116 -163 540 599 ;
+C 124 ; WX 178 ; N bar ; B 9 -158 307 599 ;
+C 125 ; WX 427 ; N braceright ; B 19 -163 444 599 ;
+C 126 ; WX 489 ; N similar ; B 78 181 549 273 ;
+C 161 ; WX 552 ; N Upsilon1 ; B 134 0 710 609 ;
+C 162 ; WX 220 ; N minute ; B 156 408 393 654 ;
+C 163 ; WX 489 ; N lessequal ; B 26 0 645 569 ;
+C 164 ; WX 149 ; N fraction ; B -164 -11 490 603 ;
+C 165 ; WX 635 ; N infinity ; B 91 111 692 360 ;
+C 166 ; WX 445 ; N florin ; B -36 -172 614 612 ;
+C 167 ; WX 670 ; N club ; B 119 -23 645 474 ;
+C 168 ; WX 670 ; N diamond ; B 198 -32 605 490 ;
+C 169 ; WX 670 ; N heart ; B 205 -29 679 473 ;
+C 170 ; WX 670 ; N spade ; B 132 -32 604 488 ;
+C 171 ; WX 927 ; N arrowboth ; B 90 -13 980 455 ;
+C 172 ; WX 878 ; N arrowleft ; B 97 -13 915 455 ;
+C 173 ; WX 537 ; N arrowup ; B 223 0 691 810 ;
+C 174 ; WX 878 ; N arrowright ; B 105 -13 922 455 ;
+C 175 ; WX 537 ; N arrowdown ; B 104 -20 572 790 ;
+C 176 ; WX 356 ; N degree ; B 187 343 466 609 ;
+C 177 ; WX 489 ; N plusminus ; B 9 0 593 574 ;
+C 178 ; WX 366 ; N second ; B 150 408 560 656 ;
+C 179 ; WX 489 ; N greaterequal ; B 26 0 582 569 ;
+C 180 ; WX 489 ; N multiply ; B 28 7 609 466 ;
+C 181 ; WX 635 ; N proportional ; B 90 110 667 360 ;
+C 182 ; WX 440 ; N partialdiff ; B 62 -18 542 664 ;
+C 183 ; WX 409 ; N bullet ; B 118 101 454 421 ;
+C 184 ; WX 489 ; N divide ; B 74 63 558 406 ;
+C 185 ; WX 489 ; N notequal ; B 51 -22 587 489 ;
+C 186 ; WX 489 ; N equivalence ; B 35 73 602 394 ;
+C 187 ; WX 489 ; N approxequal ; B 57 120 572 351 ;
+C 188 ; WX 890 ; N ellipsis ; B 107 -15 804 85 ;
+C 189 ; WX 537 ; N arrowvertex ; B 216 -107 579 899 ;
+C 190 ; WX 890 ; N arrowhorizex ; B 8 196 1011 246 ;
+C 191 ; WX 586 ; N carriagereturn ; B 40 -14 710 560 ;
+C 192 ; WX 732 ; N aleph ; B 159 -16 740 586 ;
+C 193 ; WX 611 ; N Ifraktur ; B 26 -47 684 659 ;
+C 194 ; WX 708 ; N Rfraktur ; B 71 -13 833 653 ;
+C 195 ; WX 878 ; N weierstrass ; B 112 -188 878 510 ;
+C 196 ; WX 684 ; N circlemultiply ; B 114 -15 758 599 ;
+C 197 ; WX 684 ; N circleplus ; B 115 -13 759 601 ;
+C 198 ; WX 732 ; N emptyset ; B 38 -21 884 640 ;
+C 199 ; WX 684 ; N intersection ; B 36 0 714 453 ;
+C 200 ; WX 684 ; N union ; B 110 -15 788 438 ;
+C 201 ; WX 635 ; N propersuperset ; B 18 0 675 418 ;
+C 202 ; WX 635 ; N reflexsuperset ; B -17 -111 674 418 ;
+C 203 ; WX 635 ; N notsubset ; B 87 -62 744 481 ;
+C 204 ; WX 635 ; N propersubset ; B 87 0 744 418 ;
+C 205 ; WX 635 ; N reflexsubset ; B 16 -111 744 418 ;
+C 206 ; WX 635 ; N element ; B 93 0 579 417 ;
+C 207 ; WX 635 ; N notelement ; B 74 -52 579 494 ;
+C 208 ; WX 684 ; N angle ; B 23 0 833 599 ;
+C 209 ; WX 635 ; N gradient ; B 231 -17 805 639 ;
+C 210 ; WX 703 ; N registerserif ; B 120 -18 763 596 ;
+C 211 ; WX 703 ; N copyrightserif ; B 122 -13 766 601 ;
+C 212 ; WX 792 ; N trademarkserif ; B 169 261 947 599 ;
+C 213 ; WX 732 ; N product ; B -6 -90 920 668 ;
+C 214 ; WX 489 ; N radical ; B 134 -34 711 816 ;
+C 215 ; WX 223 ; N dotmath ; B 131 187 225 276 ;
+C 216 ; WX 635 ; N logicalnot ; B 78 0 685 256 ;
+C 217 ; WX 537 ; N logicaland ; B 21 0 519 404 ;
+C 218 ; WX 537 ; N logicalor ; B 151 0 639 424 ;
+C 219 ; WX 927 ; N arrowdblboth ; B 92 -18 978 454 ;
+C 220 ; WX 878 ; N arrowdblleft ; B 96 -13 942 457 ;
+C 221 ; WX 537 ; N arrowdblup ; B 152 2 688 811 ;
+C 222 ; WX 878 ; N arrowdblright ; B 71 -18 917 452 ;
+C 223 ; WX 537 ; N arrowdbldown ; B 103 -17 639 792 ;
+C 224 ; WX 440 ; N lozenge ; B 121 0 519 663 ;
+C 225 ; WX 293 ; N angleleft ; B 98 -176 472 664 ;
+C 226 ; WX 703 ; N registersans ; B 120 -18 763 596 ;
+C 227 ; WX 703 ; N copyrightsans ; B 120 -13 764 601 ;
+C 228 ; WX 700 ; N trademarksans ; B 179 261 832 599 ;
+C 229 ; WX 635 ; N summation ; B -15 -96 756 669 ;
+C 230 ; WX 342 ; N parenlefttp ; B -46 -261 642 824 ;
+C 231 ; WX 342 ; N parenleftex ; B 12 -76 338 823 ;
+C 232 ; WX 342 ; N parenleftbt ; B 113 -261 339 824 ;
+C 233 ; WX 342 ; N bracketlefttp ; B -22 -71 560 824 ;
+C 234 ; WX 342 ; N bracketleftex ; B -22 -70 305 823 ;
+C 235 ; WX 342 ; N bracketleftbt ; B -22 -71 306 824 ;
+C 236 ; WX 440 ; N bracelefttp ; B 158 -67 648 824 ;
+C 237 ; WX 440 ; N braceleftmid ; B 126 -76 486 832 ;
+C 238 ; WX 440 ; N braceleftbt ; B 219 -62 484 824 ;
+C 239 ; WX 440 ; N braceex ; B 157 -71 486 832 ;
+C 241 ; WX 293 ; N angleright ; B -29 -176 345 664 ;
+C 242 ; WX 244 ; N integral ; B -13 -95 499 815 ;
+C 243 ; WX 611 ; N integraltp ; B 272 -74 873 820 ;
+C 244 ; WX 611 ; N integralex ; B 271 -78 640 868 ;
+C 245 ; WX 611 ; N integralbt ; B 30 -72 625 820 ;
+C 246 ; WX 342 ; N parenrighttp ; B 273 -261 498 824 ;
+C 247 ; WX 342 ; N parenrightex ; B 331 -76 657 823 ;
+C 248 ; WX 342 ; N parenrightbt ; B -30 -261 657 824 ;
+C 249 ; WX 342 ; N bracketrighttp ; B 249 -71 577 824 ;
+C 250 ; WX 342 ; N bracketrightex ; B 250 -70 577 823 ;
+C 251 ; WX 342 ; N bracketrightbt ; B -4 -71 577 824 ;
+C 252 ; WX 440 ; N bracerighttp ; B 158 -67 425 824 ;
+C 253 ; WX 440 ; N bracerightmid ; B 155 -76 517 832 ;
+C 254 ; WX 440 ; N bracerightbt ; B -4 -62 484 824 ;
+C -1 ; WX 703 ; N apple ; B 136 -2 784 719 ;
+EndCharMetrics
+EndFontMetrics
diff --git a/gnu/usr.bin/groff/devices/devps/generate/textmap b/gnu/usr.bin/groff/devices/devps/generate/textmap
new file mode 100644
index 000000000000..9001d3657ee4
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/generate/textmap
@@ -0,0 +1,449 @@
+a a
+b b
+c c
+d d
+e e
+f f
+g g
+h h
+i i
+j j
+k k
+l l
+m m
+n n
+o o
+p p
+q q
+r r
+s s
+t t
+u u
+v v
+w w
+x x
+y y
+z z
+A A
+B B
+C C
+D D
+E E
+F F
+G G
+H H
+I I
+J J
+K K
+L L
+M M
+N N
+O O
+P P
+Q Q
+R R
+S S
+T T
+U U
+V V
+W W
+X X
+Y Y
+Z Z
+AE AE
+Aacute 'A
+Acircumflex ^A
+Adieresis :A
+Agrave `A
+Aring oA
+Atilde ~A
+Cacute 'C
+Ccedilla ,C
+Eacute 'E
+Ecircumflex ^E
+Edieresis :E
+Egrave `E
+Eth -D
+IJ IJ
+Iacute 'I
+Icircumflex ^I
+Idieresis :I
+Ifraktur Im
+Igrave `I
+Lslash /L
+Ntilde ~N
+OE OE
+Oacute 'O
+Ocircumflex ^O
+Odieresis :O
+Ograve `O
+Oslash /O
+Otilde ~O
+Rfraktur Re
+Scaron vS
+Thorn TP
+Uacute 'U
+Ucircumflex ^U
+Udieresis :U
+Ugrave `U
+Yacute 'Y
+Ydieresis :Y
+Zcaron vZ
+aacute 'a
+acircumflex ^a
+acute aa
+adieresis :a
+ae ae
+agrave `a
+angle /_
+angleleft la
+angleright ra
+aleph Ah
+ampersand &
+approxequal ~~
+aring oa
+arrowboth <>
+arrowdblboth hA
+arrowdbldown dA
+arrowdblleft lA
+arrowdblright rA
+arrowdblup uA
+arrowdown da
+arrowleft <-
+arrowright ->
+arrowup ua
+asciicircum ha
+asciitilde ti
+asterisk *
+asteriskmath **
+at @
+at at
+atilde ~a
+backslash \
+backslash rs
+bar ba
+bar |
+bell bs
+braceleft lC
+braceleft {
+braceright rC
+braceright }
+bracketleft [
+bracketleft lB
+bracketright ]
+bracketright rB
+breve ab
+brokenbar bb
+bullet bu
+cacute 'c
+caron ah
+ccedilla ,c
+cedilla ac
+cent ct
+checkmark OK
+circle ci
+circlemultiply c*
+circleplus c+
+circumflex a^
+circumflex ^
+colon :
+comma ,
+congruent =~
+copyright co
+currency Cs
+dagger dg
+daggerdbl dd
+degree de
+dieresis ad
+dollar $
+dollar Do
+dotaccent a.
+dotlessi .i
+dotlessj .j
+dotmath md
+eacute 'e
+ecircumflex ^e
+edieresis :e
+egrave `e
+eight 8
+element mo
+emdash em
+emptyset es
+endash en
+equal =
+equalmath eq
+equivalence ==
+eth Sd
+exclam !
+exclamdown r!
+existential te
+ff ff
+ffi Fi
+ffl Fl
+fi fi
+five 5
+fl fl
+florin Fn
+four 4
+germandbls ss
+gradient gr
+grave ga
+greater >
+greaterequal >=
+guillemotleft Fo
+guillemotright Fc
+guilsinglleft fo
+guilsinglright fc
+handleft lh
+handright rh
+hbar -h
+hungarumlaut a"
+hyphen -
+hyphen hy
+iacute 'i
+icircumflex ^i
+idieresis :i
+igrave `i
+ij ij
+infinity if
+integral is
+intersection ca
+less <
+lessequal <=
+logicaland AN
+logicalnot no
+logicalor OR
+lozenge lz
+lslash /l
+macron a-
+minus \-
+minusplus -+
+minute fm
+nine 9
+notelement nm
+notequal !=
+notequivalence ne
+notpropersuperset nc
+ntilde ~n
+numbersign #
+numbersign sh
+oacute 'o
+ocircumflex ^o
+odieresis :o
+oe oe
+ogonek ho
+ograve `o
+one 1
+onehalf 12
+onequarter 14
+onesuperior S1
+ordfeminine Of
+ordmasculine Om
+oslash /o
+otilde ~o
+paragraph ps
+parenleft (
+parenright )
+partialdiff pd
+percent %
+period .
+perthousand %0
+perpendicular pp
+plus +
+plusmath pl
+propersubset sb
+propersuperset sp
+proportional pt
+question ?
+questiondown r?
+quotedbl "
+quotedblbase Bq
+quotedblleft lq
+quotedblright rq
+quoteleft `
+quoteleft oq
+quoteright '
+quotesingle aq
+quotesinglbase bq
+reflexsubset ib
+reflexsuperset ip
+registered rg
+ring ao
+scaron vs
+second sd
+section sc
+semicolon ;
+seven 7
+similar ap
+similarequal ~=
+six 6
+slash /
+slash sl
+square sq
+sterling Po
+therefore 3d
+therefore tf
+thorn Tp
+three 3
+threequarters 34
+threesuperior S3
+tilde a~
+tilde ~
+trademark tm
+two 2
+twosuperior S2
+uacute 'u
+ucircumflex ^u
+udieresis :u
+ugrave `u
+underscore _
+union cu
+universal fa
+weierstrass wp
+yacute 'y
+ydieresis :y
+yen Ye
+zcaron vz
+zero 0
+exclamdown char161
+cent char162
+sterling char163
+currency char164
+yen char165
+brokenbar char166
+section char167
+dieresis char168
+copyright char169
+ordfeminine char170
+guillemotleft char171
+logicalnot char172
+hyphen char173
+registered char174
+macron char175
+degree char176
+plusminus char177
+twosuperior char178
+threesuperior char179
+acute char180
+mu char181
+paragraph char182
+periodcentered char183
+cedilla char184
+onesuperior char185
+ordmasculine char186
+guillemotright char187
+onequarter char188
+onehalf char189
+threequarters char190
+questiondown char191
+Agrave char192
+Aacute char193
+Acircumflex char194
+Atilde char195
+Adieresis char196
+Aring char197
+AE char198
+Ccedilla char199
+Egrave char200
+Eacute char201
+Ecircumflex char202
+Edieresis char203
+Igrave char204
+Iacute char205
+Icircumflex char206
+Idieresis char207
+Eth char208
+Ntilde char209
+Ograve char210
+Oacute char211
+Ocircumflex char212
+Otilde char213
+Odieresis char214
+multiply char215
+Oslash char216
+Ugrave char217
+Uacute char218
+Ucircumflex char219
+Udieresis char220
+Yacute char221
+Thorn char222
+germandbls char223
+agrave char224
+aacute char225
+acircumflex char226
+atilde char227
+adieresis char228
+aring char229
+ae char230
+ccedilla char231
+egrave char232
+eacute char233
+ecircumflex char234
+edieresis char235
+igrave char236
+iacute char237
+icircumflex char238
+idieresis char239
+eth char240
+ntilde char241
+ograve char242
+oacute char243
+ocircumflex char244
+otilde char245
+odieresis char246
+divide char247
+oslash char248
+ugrave char249
+uacute char250
+ucircumflex char251
+udieresis char252
+yacute char253
+thorn char254
+ydieresis char255
+fraction f/
+club CL
+diamond DI
+heart HE
+spade SP
+carriagereturn CR
+suchthat st
+bracelefttp bracelefttp
+braceleftmid braceleftmid
+braceleftbt braceleftbt
+braceex braceex
+braceex bracerightex
+braceex braceleftex
+braceex barex
+bracerighttp bracerighttp
+bracerightmid bracerightmid
+bracerightbt bracerightbt
+parenlefttp parenlefttp
+parenleftbt parenleftbt
+parenleftex parenleftex
+parenrighttp parenrighttp
+parenrightbt parenrightbt
+parenrightex parenrightex
+bracketlefttp bracketlefttp
+bracketleftbt bracketleftbt
+bracketleftex bracketleftex
+bracketrighttp bracketrighttp
+bracketrightbt bracketrightbt
+bracketrightex bracketrightex
+radical sr
+radicalex rn
+approxequal ~=
+bracketlefttp lc
+bracketleftbt lf
+bracketrighttp rc
+bracketrightbt rf
+bracelefttp lt
+braceleftmid lk
+braceleftbt lb
+braceex bv
+bracerighttp rt
+bracerightmid rk
+bracerightbt rb
+summation sum
+product product
+arrowvertex arrowvertex
+arrowhorizex an
diff --git a/gnu/usr.bin/groff/devices/devps/prologue b/gnu/usr.bin/groff/devices/devps/prologue
new file mode 100644
index 000000000000..1f984c5067d2
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/prologue
@@ -0,0 +1,152 @@
+%!PS-Adobe-3.0 Resource-ProcSet
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
diff --git a/gnu/usr.bin/groff/devices/devps/symbol.afm b/gnu/usr.bin/groff/devices/devps/symbol.afm
new file mode 100644
index 000000000000..eccf6c2aaca6
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/symbol.afm
@@ -0,0 +1,215 @@
+(c) 1987, 1988, 1989, 1990, 1991 Adobe Systems Incorporated.
+All rights reserved.
+
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Wed Jan 17 21:48:26 1990
+Comment UniqueID 27004
+Comment VMusage 28489 37622
+FontName Symbol
+FullName Symbol
+FamilyName Symbol
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -180 -293 1090 1010
+UnderlinePosition -98
+UnderlineThickness 54
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+EncodingScheme FontSpecific
+StartCharMetrics 189
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 128 -17 240 672 ;
+C 34 ; WX 713 ; N universal ; B 31 0 681 705 ;
+C 35 ; WX 500 ; N numbersign ; B 20 -16 481 673 ;
+C 36 ; WX 549 ; N existential ; B 25 0 478 707 ;
+C 37 ; WX 833 ; N percent ; B 63 -36 771 655 ;
+C 38 ; WX 778 ; N ampersand ; B 41 -18 750 661 ;
+C 39 ; WX 439 ; N suchthat ; B 48 -17 414 500 ;
+C 40 ; WX 333 ; N parenleft ; B 53 -191 300 673 ;
+C 41 ; WX 333 ; N parenright ; B 30 -191 277 673 ;
+C 42 ; WX 500 ; N asteriskmath ; B 65 134 427 551 ;
+C 43 ; WX 549 ; N plus ; B 10 0 539 533 ;
+C 44 ; WX 250 ; N comma ; B 56 -152 194 104 ;
+C 45 ; WX 549 ; N minus ; B 11 233 535 288 ;
+C 46 ; WX 250 ; N period ; B 69 -17 181 95 ;
+C 47 ; WX 278 ; N slash ; B 0 -18 254 646 ;
+C 48 ; WX 500 ; N zero ; B 23 -17 471 685 ;
+C 49 ; WX 500 ; N one ; B 117 0 390 673 ;
+C 50 ; WX 500 ; N two ; B 25 0 475 686 ;
+C 51 ; WX 500 ; N three ; B 39 -17 435 685 ;
+C 52 ; WX 500 ; N four ; B 16 0 469 685 ;
+C 53 ; WX 500 ; N five ; B 29 -17 443 685 ;
+C 54 ; WX 500 ; N six ; B 36 -17 467 685 ;
+C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ;
+C 56 ; WX 500 ; N eight ; B 54 -18 440 685 ;
+C 57 ; WX 500 ; N nine ; B 31 -18 460 685 ;
+C 58 ; WX 278 ; N colon ; B 81 -17 193 460 ;
+C 59 ; WX 278 ; N semicolon ; B 83 -152 221 460 ;
+C 60 ; WX 549 ; N less ; B 26 0 523 522 ;
+C 61 ; WX 549 ; N equal ; B 11 141 537 390 ;
+C 62 ; WX 549 ; N greater ; B 26 0 523 522 ;
+C 63 ; WX 444 ; N question ; B 70 -17 412 686 ;
+C 64 ; WX 549 ; N congruent ; B 11 0 537 475 ;
+C 65 ; WX 722 ; N Alpha ; B 4 0 684 673 ;
+C 66 ; WX 667 ; N Beta ; B 29 0 592 673 ;
+C 67 ; WX 722 ; N Chi ; B -9 0 704 673 ;
+C 68 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C 69 ; WX 611 ; N Epsilon ; B 32 0 617 673 ;
+C 70 ; WX 763 ; N Phi ; B 26 0 741 673 ;
+C 71 ; WX 603 ; N Gamma ; B 24 0 609 673 ;
+C 72 ; WX 722 ; N Eta ; B 39 0 729 673 ;
+C 73 ; WX 333 ; N Iota ; B 32 0 316 673 ;
+C 74 ; WX 631 ; N theta1 ; B 18 -18 623 689 ;
+C 75 ; WX 722 ; N Kappa ; B 35 0 722 673 ;
+C 76 ; WX 686 ; N Lambda ; B 6 0 680 688 ;
+C 77 ; WX 889 ; N Mu ; B 28 0 887 673 ;
+C 78 ; WX 722 ; N Nu ; B 29 -8 720 673 ;
+C 79 ; WX 722 ; N Omicron ; B 41 -17 715 685 ;
+C 80 ; WX 768 ; N Pi ; B 25 0 745 673 ;
+C 81 ; WX 741 ; N Theta ; B 41 -17 715 685 ;
+C 82 ; WX 556 ; N Rho ; B 28 0 563 673 ;
+C 83 ; WX 592 ; N Sigma ; B 5 0 589 673 ;
+C 84 ; WX 611 ; N Tau ; B 33 0 607 673 ;
+C 85 ; WX 690 ; N Upsilon ; B -8 0 694 673 ;
+C 86 ; WX 439 ; N sigma1 ; B 40 -233 436 500 ;
+C 87 ; WX 768 ; N Omega ; B 34 0 736 688 ;
+C 88 ; WX 645 ; N Xi ; B 40 0 599 673 ;
+C 89 ; WX 795 ; N Psi ; B 15 0 781 684 ;
+C 90 ; WX 611 ; N Zeta ; B 44 0 636 673 ;
+C 91 ; WX 333 ; N bracketleft ; B 86 -155 299 674 ;
+C 92 ; WX 863 ; N therefore ; B 163 0 701 478 ;
+C 93 ; WX 333 ; N bracketright ; B 33 -155 246 674 ;
+C 94 ; WX 658 ; N perpendicular ; B 15 0 652 674 ;
+C 95 ; WX 500 ; N underscore ; B -2 -252 502 -206 ;
+C 96 ; WX 500 ; N radicalex ; B 480 881 1090 917 ;
+C 97 ; WX 631 ; N alpha ; B 41 -18 622 500 ;
+C 98 ; WX 549 ; N beta ; B 61 -223 515 741 ;
+C 99 ; WX 549 ; N chi ; B 12 -231 522 499 ;
+C 100 ; WX 494 ; N delta ; B 40 -19 481 740 ;
+C 101 ; WX 439 ; N epsilon ; B 22 -19 427 502 ;
+C 102 ; WX 521 ; N phi ; B 27 -224 490 671 ;
+C 103 ; WX 411 ; N gamma ; B 5 -225 484 499 ;
+C 104 ; WX 603 ; N eta ; B 0 -202 527 514 ;
+C 105 ; WX 329 ; N iota ; B 0 -17 301 503 ;
+C 106 ; WX 603 ; N phi1 ; B 36 -224 587 499 ;
+C 107 ; WX 549 ; N kappa ; B 33 0 558 501 ;
+C 108 ; WX 549 ; N lambda ; B 24 -17 548 739 ;
+C 109 ; WX 576 ; N mu ; B 33 -223 567 500 ;
+C 110 ; WX 521 ; N nu ; B -9 -16 475 507 ;
+C 111 ; WX 549 ; N omicron ; B 35 -19 501 499 ;
+C 112 ; WX 549 ; N pi ; B 10 -19 530 487 ;
+C 113 ; WX 521 ; N theta ; B 43 -17 485 690 ;
+C 114 ; WX 549 ; N rho ; B 50 -230 490 499 ;
+C 115 ; WX 603 ; N sigma ; B 30 -21 588 500 ;
+C 116 ; WX 439 ; N tau ; B 10 -19 418 500 ;
+C 117 ; WX 576 ; N upsilon ; B 7 -18 535 507 ;
+C 118 ; WX 713 ; N omega1 ; B 12 -18 671 583 ;
+C 119 ; WX 686 ; N omega ; B 42 -17 684 500 ;
+C 120 ; WX 493 ; N xi ; B 27 -224 469 766 ;
+C 121 ; WX 686 ; N psi ; B 12 -228 701 500 ;
+C 122 ; WX 494 ; N zeta ; B 60 -225 467 756 ;
+C 123 ; WX 480 ; N braceleft ; B 58 -183 397 673 ;
+C 124 ; WX 200 ; N bar ; B 65 -177 135 673 ;
+C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ;
+C 126 ; WX 549 ; N similar ; B 17 203 529 307 ;
+C 161 ; WX 620 ; N Upsilon1 ; B -2 0 610 685 ;
+C 162 ; WX 247 ; N minute ; B 27 459 228 735 ;
+C 163 ; WX 549 ; N lessequal ; B 29 0 526 639 ;
+C 164 ; WX 167 ; N fraction ; B -180 -12 340 677 ;
+C 165 ; WX 713 ; N infinity ; B 26 124 688 404 ;
+C 166 ; WX 500 ; N florin ; B 2 -193 494 686 ;
+C 167 ; WX 753 ; N club ; B 86 -26 660 533 ;
+C 168 ; WX 753 ; N diamond ; B 142 -36 600 550 ;
+C 169 ; WX 753 ; N heart ; B 117 -33 631 532 ;
+C 170 ; WX 753 ; N spade ; B 113 -36 629 548 ;
+C 171 ; WX 1042 ; N arrowboth ; B 24 -15 1024 511 ;
+C 172 ; WX 987 ; N arrowleft ; B 32 -15 942 511 ;
+C 173 ; WX 603 ; N arrowup ; B 45 0 571 910 ;
+C 174 ; WX 987 ; N arrowright ; B 49 -15 959 511 ;
+C 175 ; WX 603 ; N arrowdown ; B 45 -22 571 888 ;
+C 176 ; WX 400 ; N degree ; B 50 385 350 685 ;
+C 177 ; WX 549 ; N plusminus ; B 10 0 539 645 ;
+C 178 ; WX 411 ; N second ; B 20 459 413 737 ;
+C 179 ; WX 549 ; N greaterequal ; B 29 0 526 639 ;
+C 180 ; WX 549 ; N multiply ; B 17 8 533 524 ;
+C 181 ; WX 713 ; N proportional ; B 27 123 639 404 ;
+C 182 ; WX 494 ; N partialdiff ; B 26 -20 462 746 ;
+C 183 ; WX 460 ; N bullet ; B 50 113 410 473 ;
+C 184 ; WX 549 ; N divide ; B 10 71 536 456 ;
+C 185 ; WX 549 ; N notequal ; B 15 -25 540 549 ;
+C 186 ; WX 549 ; N equivalence ; B 14 82 538 443 ;
+C 187 ; WX 549 ; N approxequal ; B 14 135 527 394 ;
+C 188 ; WX 1000 ; N ellipsis ; B 111 -17 889 95 ;
+C 189 ; WX 603 ; N arrowvertex ; B 280 -120 336 1010 ;
+C 190 ; WX 1000 ; N arrowhorizex ; B -60 220 1050 276 ;
+C 191 ; WX 658 ; N carriagereturn ; B 15 -16 602 629 ;
+C 192 ; WX 823 ; N aleph ; B 175 -18 661 658 ;
+C 193 ; WX 686 ; N Ifraktur ; B 10 -53 578 740 ;
+C 194 ; WX 795 ; N Rfraktur ; B 26 -15 759 734 ;
+C 195 ; WX 987 ; N weierstrass ; B 159 -211 870 573 ;
+C 196 ; WX 768 ; N circlemultiply ; B 43 -17 733 673 ;
+C 197 ; WX 768 ; N circleplus ; B 43 -15 733 675 ;
+C 198 ; WX 823 ; N emptyset ; B 39 -24 781 719 ;
+C 199 ; WX 768 ; N intersection ; B 40 0 732 509 ;
+C 200 ; WX 768 ; N union ; B 40 -17 732 492 ;
+C 201 ; WX 713 ; N propersuperset ; B 20 0 673 470 ;
+C 202 ; WX 713 ; N reflexsuperset ; B 20 -125 673 470 ;
+C 203 ; WX 713 ; N notsubset ; B 36 -70 690 540 ;
+C 204 ; WX 713 ; N propersubset ; B 37 0 690 470 ;
+C 205 ; WX 713 ; N reflexsubset ; B 37 -125 690 470 ;
+C 206 ; WX 713 ; N element ; B 45 0 505 468 ;
+C 207 ; WX 713 ; N notelement ; B 45 -58 505 555 ;
+C 208 ; WX 768 ; N angle ; B 26 0 738 673 ;
+C 209 ; WX 713 ; N gradient ; B 36 -19 681 718 ;
+C 210 ; WX 790 ; N registerserif ; B 50 -17 740 673 ;
+C 211 ; WX 790 ; N copyrightserif ; B 51 -15 741 675 ;
+C 212 ; WX 890 ; N trademarkserif ; B 18 293 855 673 ;
+C 213 ; WX 823 ; N product ; B 25 -101 803 751 ;
+C 214 ; WX 549 ; N radical ; B 10 -38 515 917 ;
+C 215 ; WX 250 ; N dotmath ; B 69 210 169 310 ;
+C 216 ; WX 713 ; N logicalnot ; B 15 0 680 288 ;
+C 217 ; WX 603 ; N logicaland ; B 23 0 583 454 ;
+C 218 ; WX 603 ; N logicalor ; B 30 0 578 477 ;
+C 219 ; WX 1042 ; N arrowdblboth ; B 27 -20 1023 510 ;
+C 220 ; WX 987 ; N arrowdblleft ; B 30 -15 939 513 ;
+C 221 ; WX 603 ; N arrowdblup ; B 39 2 567 911 ;
+C 222 ; WX 987 ; N arrowdblright ; B 45 -20 954 508 ;
+C 223 ; WX 603 ; N arrowdbldown ; B 44 -19 572 890 ;
+C 224 ; WX 494 ; N lozenge ; B 18 0 466 745 ;
+C 225 ; WX 329 ; N angleleft ; B 25 -198 306 746 ;
+C 226 ; WX 790 ; N registersans ; B 50 -20 740 670 ;
+C 227 ; WX 790 ; N copyrightsans ; B 49 -15 739 675 ;
+C 228 ; WX 786 ; N trademarksans ; B 5 293 725 673 ;
+C 229 ; WX 713 ; N summation ; B 14 -108 695 752 ;
+C 230 ; WX 384 ; N parenlefttp ; B 40 -293 436 926 ;
+C 231 ; WX 384 ; N parenleftex ; B 40 -80 92 920 ;
+C 232 ; WX 384 ; N parenleftbt ; B 40 -293 436 920 ;
+C 233 ; WX 384 ; N bracketlefttp ; B 0 -75 341 925 ;
+C 234 ; WX 384 ; N bracketleftex ; B 0 -75 55 925 ;
+C 235 ; WX 384 ; N bracketleftbt ; B 0 -75 340 925 ;
+C 236 ; WX 494 ; N bracelefttp ; B 201 -75 439 925 ;
+C 237 ; WX 494 ; N braceleftmid ; B 14 -75 255 925 ;
+C 238 ; WX 494 ; N braceleftbt ; B 201 -75 439 925 ;
+C 239 ; WX 494 ; N braceex ; B 201 -75 255 925 ;
+C 241 ; WX 329 ; N angleright ; B 21 -198 302 746 ;
+C 242 ; WX 274 ; N integral ; B 2 -107 291 916 ;
+C 243 ; WX 686 ; N integraltp ; B 332 -83 715 921 ;
+C 244 ; WX 686 ; N integralex ; B 332 -88 415 975 ;
+C 245 ; WX 686 ; N integralbt ; B 39 -81 415 921 ;
+C 246 ; WX 384 ; N parenrighttp ; B 54 -293 450 926 ;
+C 247 ; WX 384 ; N parenrightex ; B 398 -80 450 920 ;
+C 248 ; WX 384 ; N parenrightbt ; B 54 -293 450 920 ;
+C 249 ; WX 384 ; N bracketrighttp ; B 22 -75 360 925 ;
+C 250 ; WX 384 ; N bracketrightex ; B 305 -75 360 925 ;
+C 251 ; WX 384 ; N bracketrightbt ; B 20 -75 360 925 ;
+C 252 ; WX 494 ; N bracerighttp ; B 17 -75 255 925 ;
+C 253 ; WX 494 ; N bracerightmid ; B 201 -75 442 925 ;
+C 254 ; WX 494 ; N bracerightbt ; B 17 -75 255 925 ;
+C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ;
+EndCharMetrics
+italicCorrection integral 67
+leftItalicCorrection integral 52
+subscriptCorrection integral -10
+EndFontMetrics
diff --git a/gnu/usr.bin/groff/devices/devps/symbolsl.pfa b/gnu/usr.bin/groff/devices/devps/symbolsl.pfa
new file mode 100644
index 000000000000..5b335ca0ce1c
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/symbolsl.pfa
@@ -0,0 +1,29 @@
+%!PS-Adobe-3.0 Resource-Font
+%%DocumentNeededResources: font Symbol
+/MakeTransformedFont{
+findfont dup maxlength dict begin
+{
+exch dup dup/FID ne exch/UniqueID ne and{
+exch def
+}{
+pop pop
+}ifelse
+}forall
+/FontBBox
+currentdict/FontBBox get
+4 array copy def
+FontBBox aload pop
+4 index transform 4 2 roll
+4 index transform 4 2 roll
+FontBBox astore pop
+FontMatrix exch matrix concatmatrix
+/FontMatrix exch def
+dup/FontName exch def
+currentdict end
+definefont pop
+}bind def
+%%IncludeResource: font Symbol
+/Symbol-Slanted
+[.89 0.0 15.5 dup sin exch cos div .89 0.0 0.0]
+/Symbol
+MakeTransformedFont
diff --git a/gnu/usr.bin/groff/devices/devps/text.enc b/gnu/usr.bin/groff/devices/devps/text.enc
new file mode 100644
index 000000000000..dde5bb7c04db
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/text.enc
@@ -0,0 +1,231 @@
+asciicircum 0
+asciitilde 1
+Scaron 2
+Zcaron 3
+scaron 4
+zcaron 5
+Ydieresis 6
+trademark 7
+quotesingle 8
+space 32
+exclam 33
+quotedbl 34
+numbersign 35
+dollar 36
+percent 37
+ampersand 38
+quoteright 39
+parenleft 40
+parenright 41
+asterisk 42
+plus 43
+comma 44
+hyphen 45
+period 46
+slash 47
+zero 48
+one 49
+two 50
+three 51
+four 52
+five 53
+six 54
+seven 55
+eight 56
+nine 57
+colon 58
+semicolon 59
+less 60
+equal 61
+greater 62
+question 63
+at 64
+A 65
+B 66
+C 67
+D 68
+E 69
+F 70
+G 71
+H 72
+I 73
+J 74
+K 75
+L 76
+M 77
+N 78
+O 79
+P 80
+Q 81
+R 82
+S 83
+T 84
+U 85
+V 86
+W 87
+X 88
+Y 89
+Z 90
+bracketleft 91
+backslash 92
+bracketright 93
+circumflex 94
+underscore 95
+quoteleft 96
+a 97
+b 98
+c 99
+d 100
+e 101
+f 102
+g 103
+h 104
+i 105
+j 106
+k 107
+l 108
+m 109
+n 110
+o 111
+p 112
+q 113
+r 114
+s 115
+t 116
+u 117
+v 118
+w 119
+x 120
+y 121
+z 122
+braceleft 123
+bar 124
+braceright 125
+tilde 126
+quotesinglbase 128
+guillemotleft 129
+guillemotright 130
+bullet 131
+florin 132
+fraction 133
+perthousand 134
+dagger 135
+daggerdbl 136
+endash 137
+emdash 138
+ff 139
+fi 140
+fl 141
+ffi 142
+ffl 143
+dotlessi 144
+dotlessj 145
+grave 146
+hungarumlaut 147
+dotaccent 148
+breve 149
+caron 150
+ring 151
+ogonek 152
+quotedblleft 153
+quotedblright 154
+oe 155
+lslash 156
+quotedblbase 157
+OE 158
+Lslash 159
+exclamdown 161
+cent 162
+sterling 163
+currency 164
+yen 165
+brokenbar 166
+section 167
+dieresis 168
+copyright 169
+ordfeminine 170
+guilsinglleft 171
+logicalnot 172
+registered 174
+minus 173
+macron 175
+degree 176
+plusminus 177
+twosuperior 178
+threesuperior 179
+acute 180
+mu 181
+paragraph 182
+periodcentered 183
+cedilla 184
+onesuperior 185
+ordmasculine 186
+guilsinglright 187
+onequarter 188
+onehalf 189
+threequarters 190
+questiondown 191
+Agrave 192
+Aacute 193
+Acircumflex 194
+Atilde 195
+Adieresis 196
+Aring 197
+AE 198
+Ccedilla 199
+Egrave 200
+Eacute 201
+Ecircumflex 202
+Edieresis 203
+Igrave 204
+Iacute 205
+Icircumflex 206
+Idieresis 207
+Eth 208
+Ntilde 209
+Ograve 210
+Oacute 211
+Ocircumflex 212
+Otilde 213
+Odieresis 214
+multiply 215
+Oslash 216
+Ugrave 217
+Uacute 218
+Ucircumflex 219
+Udieresis 220
+Yacute 221
+Thorn 222
+germandbls 223
+agrave 224
+aacute 225
+acircumflex 226
+atilde 227
+adieresis 228
+aring 229
+ae 230
+ccedilla 231
+egrave 232
+eacute 233
+ecircumflex 234
+edieresis 235
+igrave 236
+iacute 237
+icircumflex 238
+idieresis 239
+eth 240
+ntilde 241
+ograve 242
+oacute 243
+ocircumflex 244
+otilde 245
+odieresis 246
+divide 247
+oslash 248
+ugrave 249
+uacute 250
+ucircumflex 251
+udieresis 252
+yacute 253
+thorn 254
+ydieresis 255
diff --git a/gnu/usr.bin/groff/devices/devps/zapfdr.afm b/gnu/usr.bin/groff/devices/devps/zapfdr.afm
new file mode 100644
index 000000000000..ce216de44a6f
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/zapfdr.afm
@@ -0,0 +1,222 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1988, 1989 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Fri Dec 1 12:57:42 1989
+Comment UniqueID 26200
+Comment VMusage 39281 49041
+FontName ZapfDingbats-Reverse
+FullName ITC Zapf Dingbats
+FamilyName ITC Zapf Dingbats
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -1 -143 981 820
+UnderlinePosition -98
+UnderlineThickness 54
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1988, 1989 Adobe Systems Incorporated. All rights reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
+EncodingScheme FontSpecific
+StartCharMetrics 202
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 974 ; N a1 ; B 35 72 939 621 ;
+C 34 ; WX 961 ; N a2 ; B 35 81 927 611 ;
+C 35 ; WX 974 ; N a202 ; B 35 72 939 621 ;
+C 36 ; WX 980 ; N a3 ; B 35 0 945 692 ;
+C 37 ; WX 719 ; N a4 ; B 34 139 685 566 ;
+C 38 ; WX 789 ; N a5 ; B 35 -14 755 705 ;
+C 39 ; WX 790 ; N a119 ; B 35 -14 755 705 ;
+C 40 ; WX 791 ; N a118 ; B 35 -13 761 705 ;
+C 41 ; WX 690 ; N a117 ; B 35 138 655 553 ;
+C 42 ; WX 960 ; N a11 ; B 35 123 925 568 ;
+C 43 ; WX 939 ; N a12 ; B 35 134 904 559 ;
+C 44 ; WX 549 ; N a13 ; B 29 -11 516 705 ;
+C 45 ; WX 855 ; N a14 ; B 34 59 820 632 ;
+C 46 ; WX 911 ; N a15 ; B 35 50 876 642 ;
+C 47 ; WX 933 ; N a16 ; B 35 139 899 550 ;
+C 48 ; WX 911 ; N a105 ; B 35 50 876 642 ;
+C 49 ; WX 945 ; N a17 ; B 35 139 909 553 ;
+C 50 ; WX 974 ; N a18 ; B 35 104 938 587 ;
+C 51 ; WX 755 ; N a19 ; B 34 -13 721 705 ;
+C 52 ; WX 846 ; N a20 ; B 36 -14 811 705 ;
+C 53 ; WX 762 ; N a21 ; B 35 0 727 692 ;
+C 54 ; WX 761 ; N a22 ; B 35 0 727 692 ;
+C 55 ; WX 571 ; N a23 ; B -1 -68 571 661 ;
+C 56 ; WX 677 ; N a24 ; B 36 -13 642 705 ;
+C 57 ; WX 763 ; N a25 ; B 35 0 728 692 ;
+C 58 ; WX 760 ; N a26 ; B 35 0 726 692 ;
+C 59 ; WX 759 ; N a27 ; B 35 0 725 692 ;
+C 60 ; WX 754 ; N a28 ; B 35 0 720 692 ;
+C 61 ; WX 494 ; N a6 ; B 35 0 460 692 ;
+C 62 ; WX 552 ; N a7 ; B 35 0 517 692 ;
+C 63 ; WX 537 ; N a8 ; B 35 0 503 692 ;
+C 64 ; WX 577 ; N a9 ; B 35 96 542 596 ;
+C 65 ; WX 692 ; N a10 ; B 35 -14 657 705 ;
+C 66 ; WX 786 ; N a29 ; B 35 -14 751 705 ;
+C 67 ; WX 788 ; N a30 ; B 35 -14 752 705 ;
+C 68 ; WX 788 ; N a31 ; B 35 -14 753 705 ;
+C 69 ; WX 790 ; N a32 ; B 35 -14 756 705 ;
+C 70 ; WX 793 ; N a33 ; B 35 -13 759 705 ;
+C 71 ; WX 794 ; N a34 ; B 35 -13 759 705 ;
+C 72 ; WX 816 ; N a35 ; B 35 -14 782 705 ;
+C 73 ; WX 823 ; N a36 ; B 35 -14 787 705 ;
+C 74 ; WX 789 ; N a37 ; B 35 -14 754 705 ;
+C 75 ; WX 841 ; N a38 ; B 35 -14 807 705 ;
+C 76 ; WX 823 ; N a39 ; B 35 -14 789 705 ;
+C 77 ; WX 833 ; N a40 ; B 35 -14 798 705 ;
+C 78 ; WX 816 ; N a41 ; B 35 -13 782 705 ;
+C 79 ; WX 831 ; N a42 ; B 35 -14 796 705 ;
+C 80 ; WX 923 ; N a43 ; B 35 -14 888 705 ;
+C 81 ; WX 744 ; N a44 ; B 35 0 710 692 ;
+C 82 ; WX 723 ; N a45 ; B 35 0 688 692 ;
+C 83 ; WX 749 ; N a46 ; B 35 0 714 692 ;
+C 84 ; WX 790 ; N a47 ; B 34 -14 756 705 ;
+C 85 ; WX 792 ; N a48 ; B 35 -14 758 705 ;
+C 86 ; WX 695 ; N a49 ; B 35 -14 661 706 ;
+C 87 ; WX 776 ; N a50 ; B 35 -6 741 699 ;
+C 88 ; WX 768 ; N a51 ; B 35 -7 734 699 ;
+C 89 ; WX 792 ; N a52 ; B 35 -14 757 705 ;
+C 90 ; WX 759 ; N a53 ; B 35 0 725 692 ;
+C 91 ; WX 707 ; N a54 ; B 35 -13 672 704 ;
+C 92 ; WX 708 ; N a55 ; B 35 -14 672 705 ;
+C 93 ; WX 682 ; N a56 ; B 35 -14 647 705 ;
+C 94 ; WX 701 ; N a57 ; B 35 -14 666 705 ;
+C 95 ; WX 826 ; N a58 ; B 35 -14 791 705 ;
+C 96 ; WX 815 ; N a59 ; B 35 -14 780 705 ;
+C 97 ; WX 789 ; N a60 ; B 35 -14 754 705 ;
+C 98 ; WX 789 ; N a61 ; B 35 -14 754 705 ;
+C 99 ; WX 707 ; N a62 ; B 34 -14 673 705 ;
+C 100 ; WX 687 ; N a63 ; B 36 0 651 692 ;
+C 101 ; WX 696 ; N a64 ; B 35 0 661 691 ;
+C 102 ; WX 689 ; N a65 ; B 35 0 655 692 ;
+C 103 ; WX 786 ; N a66 ; B 34 -14 751 705 ;
+C 104 ; WX 787 ; N a67 ; B 35 -14 752 705 ;
+C 105 ; WX 713 ; N a68 ; B 35 -14 678 705 ;
+C 106 ; WX 791 ; N a69 ; B 35 -14 756 705 ;
+C 107 ; WX 785 ; N a70 ; B 36 -14 751 705 ;
+C 108 ; WX 791 ; N a71 ; B 35 -14 757 705 ;
+C 109 ; WX 873 ; N a72 ; B 35 -14 838 705 ;
+C 110 ; WX 761 ; N a73 ; B 35 0 726 692 ;
+C 111 ; WX 762 ; N a74 ; B 35 0 727 692 ;
+C 112 ; WX 762 ; N a203 ; B 35 0 727 692 ;
+C 113 ; WX 759 ; N a75 ; B 35 0 725 692 ;
+C 114 ; WX 759 ; N a204 ; B 35 0 725 692 ;
+C 115 ; WX 892 ; N a76 ; B 35 0 858 705 ;
+C 116 ; WX 892 ; N a77 ; B 35 -14 858 692 ;
+C 117 ; WX 788 ; N a78 ; B 35 -14 754 705 ;
+C 118 ; WX 784 ; N a79 ; B 35 -14 749 705 ;
+C 119 ; WX 438 ; N a81 ; B 35 -14 403 705 ;
+C 120 ; WX 138 ; N a82 ; B 35 0 104 692 ;
+C 121 ; WX 277 ; N a83 ; B 35 0 242 692 ;
+C 122 ; WX 415 ; N a84 ; B 35 0 380 692 ;
+C 123 ; WX 392 ; N a97 ; B 35 263 357 705 ;
+C 124 ; WX 392 ; N a98 ; B 34 263 357 705 ;
+C 125 ; WX 668 ; N a99 ; B 35 263 633 705 ;
+C 126 ; WX 668 ; N a100 ; B 36 263 634 705 ;
+C 161 ; WX 732 ; N a101 ; B 35 -143 697 806 ;
+C 162 ; WX 544 ; N a102 ; B 56 -14 488 706 ;
+C 163 ; WX 544 ; N a103 ; B 34 -14 508 705 ;
+C 164 ; WX 910 ; N a104 ; B 35 40 875 651 ;
+C 165 ; WX 667 ; N a106 ; B 35 -14 633 705 ;
+C 166 ; WX 760 ; N a107 ; B 35 -14 726 705 ;
+C 167 ; WX 760 ; N a108 ; B 0 121 758 569 ;
+C 168 ; WX 776 ; N a112 ; B 35 0 741 705 ;
+C 169 ; WX 595 ; N a111 ; B 34 -14 560 705 ;
+C 170 ; WX 694 ; N a110 ; B 35 -14 659 705 ;
+C 171 ; WX 626 ; N a109 ; B 34 0 591 705 ;
+C 172 ; WX 788 ; N a120 ; B 35 -14 754 705 ;
+C 173 ; WX 788 ; N a121 ; B 35 -14 754 705 ;
+C 174 ; WX 788 ; N a122 ; B 35 -14 754 705 ;
+C 175 ; WX 788 ; N a123 ; B 35 -14 754 705 ;
+C 176 ; WX 788 ; N a124 ; B 35 -14 754 705 ;
+C 177 ; WX 788 ; N a125 ; B 35 -14 754 705 ;
+C 178 ; WX 788 ; N a126 ; B 35 -14 754 705 ;
+C 179 ; WX 788 ; N a127 ; B 35 -14 754 705 ;
+C 180 ; WX 788 ; N a128 ; B 35 -14 754 705 ;
+C 181 ; WX 788 ; N a129 ; B 35 -14 754 705 ;
+C 182 ; WX 788 ; N a130 ; B 35 -14 754 705 ;
+C 183 ; WX 788 ; N a131 ; B 35 -14 754 705 ;
+C 184 ; WX 788 ; N a132 ; B 35 -14 754 705 ;
+C 185 ; WX 788 ; N a133 ; B 35 -14 754 705 ;
+C 186 ; WX 788 ; N a134 ; B 35 -14 754 705 ;
+C 187 ; WX 788 ; N a135 ; B 35 -14 754 705 ;
+C 188 ; WX 788 ; N a136 ; B 35 -14 754 705 ;
+C 189 ; WX 788 ; N a137 ; B 35 -14 754 705 ;
+C 190 ; WX 788 ; N a138 ; B 35 -14 754 705 ;
+C 191 ; WX 788 ; N a139 ; B 35 -14 754 705 ;
+C 192 ; WX 788 ; N a140 ; B 35 -14 754 705 ;
+C 193 ; WX 788 ; N a141 ; B 35 -14 754 705 ;
+C 194 ; WX 788 ; N a142 ; B 35 -14 754 705 ;
+C 195 ; WX 788 ; N a143 ; B 35 -14 754 705 ;
+C 196 ; WX 788 ; N a144 ; B 35 -14 754 705 ;
+C 197 ; WX 788 ; N a145 ; B 35 -14 754 705 ;
+C 198 ; WX 788 ; N a146 ; B 35 -14 754 705 ;
+C 199 ; WX 788 ; N a147 ; B 35 -14 754 705 ;
+C 200 ; WX 788 ; N a148 ; B 35 -14 754 705 ;
+C 201 ; WX 788 ; N a149 ; B 35 -14 754 705 ;
+C 202 ; WX 788 ; N a150 ; B 35 -14 754 705 ;
+C 203 ; WX 788 ; N a151 ; B 35 -14 754 705 ;
+C 204 ; WX 788 ; N a152 ; B 35 -14 754 705 ;
+C 205 ; WX 788 ; N a153 ; B 35 -14 754 705 ;
+C 206 ; WX 788 ; N a154 ; B 35 -14 754 705 ;
+C 207 ; WX 788 ; N a155 ; B 35 -14 754 705 ;
+C 208 ; WX 788 ; N a156 ; B 35 -14 754 705 ;
+C 209 ; WX 788 ; N a157 ; B 35 -14 754 705 ;
+C 210 ; WX 788 ; N a158 ; B 35 -14 754 705 ;
+C 211 ; WX 788 ; N a159 ; B 35 -14 754 705 ;
+C 212 ; WX 894 ; N a160 ; B 35 58 860 634 ;
+C 213 ; WX 838 ; N a161 ; B 35 152 803 540 ;
+C 214 ; WX 1016 ; N a163 ; B 34 152 981 540 ;
+C 215 ; WX 458 ; N a164 ; B 35 -127 422 820 ;
+C 216 ; WX 748 ; N a196 ; B 35 94 698 597 ;
+C 217 ; WX 924 ; N a165 ; B 35 140 890 552 ;
+C 218 ; WX 748 ; N a192 ; B 35 94 698 597 ;
+C 219 ; WX 918 ; N a166 ; B 35 166 884 526 ;
+C 220 ; WX 927 ; N a167 ; B 35 32 892 660 ;
+C 221 ; WX 928 ; N a168 ; B 35 129 891 562 ;
+C 222 ; WX 928 ; N a169 ; B 35 128 893 563 ;
+C 223 ; WX 834 ; N a170 ; B 35 155 799 537 ;
+C 224 ; WX 873 ; N a171 ; B 35 93 838 599 ;
+C 225 ; WX 828 ; N a172 ; B 35 104 791 588 ;
+C 226 ; WX 924 ; N a173 ; B 35 98 889 594 ;
+C 227 ; WX 924 ; N a162 ; B 35 98 889 594 ;
+C 228 ; WX 917 ; N a174 ; B 35 0 882 692 ;
+C 229 ; WX 930 ; N a175 ; B 35 84 896 608 ;
+C 230 ; WX 931 ; N a176 ; B 35 84 896 608 ;
+C 231 ; WX 463 ; N a177 ; B 35 -99 429 791 ;
+C 232 ; WX 883 ; N a178 ; B 35 71 848 623 ;
+C 233 ; WX 836 ; N a179 ; B 35 44 802 648 ;
+C 234 ; WX 836 ; N a193 ; B 35 44 802 648 ;
+C 235 ; WX 867 ; N a180 ; B 35 101 832 591 ;
+C 236 ; WX 867 ; N a199 ; B 35 101 832 591 ;
+C 237 ; WX 696 ; N a181 ; B 35 44 661 648 ;
+C 238 ; WX 696 ; N a200 ; B 35 44 661 648 ;
+C 239 ; WX 874 ; N a182 ; B 35 77 840 619 ;
+C 241 ; WX 874 ; N a201 ; B 35 73 840 615 ;
+C 242 ; WX 760 ; N a183 ; B 35 0 725 692 ;
+C 243 ; WX 946 ; N a184 ; B 35 160 911 533 ;
+C 244 ; WX 771 ; N a197 ; B 34 37 736 655 ;
+C 245 ; WX 865 ; N a185 ; B 35 207 830 481 ;
+C 246 ; WX 771 ; N a194 ; B 34 37 736 655 ;
+C 247 ; WX 888 ; N a198 ; B 34 -19 853 712 ;
+C 248 ; WX 967 ; N a186 ; B 35 124 932 568 ;
+C 249 ; WX 888 ; N a195 ; B 34 -19 853 712 ;
+C 250 ; WX 831 ; N a187 ; B 35 113 796 579 ;
+C 251 ; WX 873 ; N a188 ; B 36 118 838 578 ;
+C 252 ; WX 927 ; N a189 ; B 35 150 891 542 ;
+C 253 ; WX 970 ; N a190 ; B 35 76 931 616 ;
+C 254 ; WX 918 ; N a191 ; B 34 99 884 593 ;
+C -1 ; WX 410 ; N a86 ; B 35 0 375 692 ;
+C -1 ; WX 509 ; N a85 ; B 35 0 475 692 ;
+C -1 ; WX 334 ; N a95 ; B 35 0 299 692 ;
+C -1 ; WX 509 ; N a205 ; B 35 0 475 692 ;
+C -1 ; WX 390 ; N a89 ; B 35 -14 356 705 ;
+C -1 ; WX 234 ; N a87 ; B 35 -14 199 705 ;
+C -1 ; WX 276 ; N a91 ; B 35 0 242 692 ;
+C -1 ; WX 390 ; N a90 ; B 35 -14 355 705 ;
+C -1 ; WX 410 ; N a206 ; B 35 0 375 692 ;
+C -1 ; WX 317 ; N a94 ; B 35 0 283 692 ;
+C -1 ; WX 317 ; N a93 ; B 35 0 283 692 ;
+C -1 ; WX 276 ; N a92 ; B 35 0 242 692 ;
+C -1 ; WX 334 ; N a96 ; B 35 0 299 692 ;
+C -1 ; WX 234 ; N a88 ; B 35 -14 199 705 ;
+EndCharMetrics
+EndFontMetrics
diff --git a/gnu/usr.bin/groff/devices/devps/zapfdr.pfa b/gnu/usr.bin/groff/devices/devps/zapfdr.pfa
new file mode 100644
index 000000000000..51df4cb4f9b8
--- /dev/null
+++ b/gnu/usr.bin/groff/devices/devps/zapfdr.pfa
@@ -0,0 +1,218 @@
+%!PS-Adobe-3.0 Resource-Font
+%%DocumentNeededResources: font ZapfDingbats
+%%IncludeResource: font ZapfDingbats
+/ZapfDingbats findfont[-1 0 0 1 0 0]makefont
+dup length 1 add dict begin
+{
+exch dup dup/FID ne exch/UniqueID ne and{
+exch def
+}{
+pop pop
+}ifelse
+}forall
+/FontName/ZapfDingbats-Reverse def
+/Metrics 202 dict dup begin
+/space[0 -278]def
+/a1[-939 -974]def
+/a2[-926 -961]def
+/a202[-939 -974]def
+/a3[-945 -980]def
+/a4[-685 -719]def
+/a5[-754 -789]def
+/a119[-755 -790]def
+/a118[-756 -791]def
+/a117[-655 -690]def
+/a11[-925 -960]def
+/a12[-904 -939]def
+/a13[-520 -549]def
+/a14[-821 -855]def
+/a15[-876 -911]def
+/a16[-898 -933]def
+/a105[-876 -911]def
+/a17[-910 -945]def
+/a18[-939 -974]def
+/a19[-721 -755]def
+/a20[-811 -846]def
+/a21[-727 -762]def
+/a22[-726 -761]def
+/a23[-572 -571]def
+/a24[-641 -677]def
+/a25[-728 -763]def
+/a26[-725 -760]def
+/a27[-724 -759]def
+/a28[-719 -754]def
+/a6[-459 -494]def
+/a7[-517 -552]def
+/a8[-502 -537]def
+/a9[-542 -577]def
+/a10[-657 -692]def
+/a29[-751 -786]def
+/a30[-753 -788]def
+/a31[-753 -788]def
+/a32[-755 -790]def
+/a33[-758 -793]def
+/a34[-759 -794]def
+/a35[-781 -816]def
+/a36[-788 -823]def
+/a37[-754 -789]def
+/a38[-806 -841]def
+/a39[-788 -823]def
+/a40[-798 -833]def
+/a41[-781 -816]def
+/a42[-796 -831]def
+/a43[-888 -923]def
+/a44[-709 -744]def
+/a45[-688 -723]def
+/a46[-714 -749]def
+/a47[-756 -790]def
+/a48[-757 -792]def
+/a49[-660 -695]def
+/a50[-741 -776]def
+/a51[-733 -768]def
+/a52[-757 -792]def
+/a53[-724 -759]def
+/a54[-672 -707]def
+/a55[-673 -708]def
+/a56[-647 -682]def
+/a57[-666 -701]def
+/a58[-791 -826]def
+/a59[-780 -815]def
+/a60[-754 -789]def
+/a61[-754 -789]def
+/a62[-673 -707]def
+/a63[-651 -687]def
+/a64[-661 -696]def
+/a65[-654 -689]def
+/a66[-752 -786]def
+/a67[-752 -787]def
+/a68[-678 -713]def
+/a69[-756 -791]def
+/a70[-749 -785]def
+/a71[-756 -791]def
+/a72[-838 -873]def
+/a73[-726 -761]def
+/a74[-727 -762]def
+/a203[-727 -762]def
+/a75[-724 -759]def
+/a204[-724 -759]def
+/a76[-857 -892]def
+/a77[-857 -892]def
+/a78[-753 -788]def
+/a79[-749 -784]def
+/a81[-403 -438]def
+/a82[-103 -138]def
+/a83[-242 -277]def
+/a84[-380 -415]def
+/a97[-357 -392]def
+/a98[-358 -392]def
+/a99[-633 -668]def
+/a100[-632 -668]def
+/a101[-697 -732]def
+/a102[-488 -544]def
+/a103[-510 -544]def
+/a104[-875 -910]def
+/a106[-632 -667]def
+/a107[-725 -760]def
+/a108[-760 -760]def
+/a112[-741 -776]def
+/a111[-561 -595]def
+/a110[-659 -694]def
+/a109[-592 -626]def
+/a120[-753 -788]def
+/a121[-753 -788]def
+/a122[-753 -788]def
+/a123[-753 -788]def
+/a124[-753 -788]def
+/a125[-753 -788]def
+/a126[-753 -788]def
+/a127[-753 -788]def
+/a128[-753 -788]def
+/a129[-753 -788]def
+/a130[-753 -788]def
+/a131[-753 -788]def
+/a132[-753 -788]def
+/a133[-753 -788]def
+/a134[-753 -788]def
+/a135[-753 -788]def
+/a136[-753 -788]def
+/a137[-753 -788]def
+/a138[-753 -788]def
+/a139[-753 -788]def
+/a140[-753 -788]def
+/a141[-753 -788]def
+/a142[-753 -788]def
+/a143[-753 -788]def
+/a144[-753 -788]def
+/a145[-753 -788]def
+/a146[-753 -788]def
+/a147[-753 -788]def
+/a148[-753 -788]def
+/a149[-753 -788]def
+/a150[-753 -788]def
+/a151[-753 -788]def
+/a152[-753 -788]def
+/a153[-753 -788]def
+/a154[-753 -788]def
+/a155[-753 -788]def
+/a156[-753 -788]def
+/a157[-753 -788]def
+/a158[-753 -788]def
+/a159[-753 -788]def
+/a160[-859 -894]def
+/a161[-803 -838]def
+/a163[-982 -1016]def
+/a164[-423 -458]def
+/a196[-713 -748]def
+/a165[-889 -924]def
+/a192[-713 -748]def
+/a166[-883 -918]def
+/a167[-892 -927]def
+/a168[-893 -928]def
+/a169[-893 -928]def
+/a170[-799 -834]def
+/a171[-838 -873]def
+/a172[-793 -828]def
+/a173[-889 -924]def
+/a162[-889 -924]def
+/a174[-882 -917]def
+/a175[-895 -930]def
+/a176[-896 -931]def
+/a177[-428 -463]def
+/a178[-848 -883]def
+/a179[-801 -836]def
+/a193[-801 -836]def
+/a180[-832 -867]def
+/a199[-832 -867]def
+/a181[-661 -696]def
+/a200[-661 -696]def
+/a182[-839 -874]def
+/a201[-839 -874]def
+/a183[-725 -760]def
+/a184[-911 -946]def
+/a197[-737 -771]def
+/a185[-830 -865]def
+/a194[-737 -771]def
+/a198[-854 -888]def
+/a186[-932 -967]def
+/a195[-854 -888]def
+/a187[-796 -831]def
+/a188[-837 -873]def
+/a189[-892 -927]def
+/a190[-935 -970]def
+/a191[-884 -918]def
+/a205[-474 -509]def
+/a206[-375 -410]def
+/a85[-474 -509]def
+/a86[-375 -410]def
+/a87[-199 -234]def
+/a88[-199 -234]def
+/a89[-355 -390]def
+/a90[-355 -390]def
+/a91[-241 -276]def
+/a92[-241 -276]def
+/a93[-282 -317]def
+/a94[-282 -317]def
+/a95[-299 -334]def
+/a96[-299 -334]def
+end def
+/ZapfDingbats-Reverse currentdict end definefont pop
diff --git a/gnu/usr.bin/groff/doc/Makefile b/gnu/usr.bin/groff/doc/Makefile
new file mode 100644
index 000000000000..0d4088decfa7
--- /dev/null
+++ b/gnu/usr.bin/groff/doc/Makefile
@@ -0,0 +1,55 @@
+#Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff is free software; you can redistribute 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.
+#
+#groff is distributed in the hope that it will be useful, but WITHOUT ANY
+#WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+#for more details.
+#
+#You should have received a copy of the GNU General Public License along
+#with groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+FFLAG=-F..
+TROFF=../troff/troff -M../tmac $(FFLAG)
+GROPS=../grops/grops $(FFLAG)
+DOCS=meref.PS meintro.PS
+MEMACROS=../macros/tmac.e
+SOELIM=../soelim/soelim
+
+all: $(DOCS)
+
+.SUFFIXES: .tr .me .PS .dit
+
+.dit.PS:
+ $(GROPS) $< >$@
+
+.me.dit:
+ $(SOELIM) $< \
+ | sed -e "s;@VERSION@;`cat ../VERSION`;" \
+ | $(TROFF) -Tps $(FFLAG) -me >$@
+
+.tr.dit:
+ $(TROFF) -Tps $< >$@
+
+meref.PS: meref.dit
+meintro.PS: meintro.dit
+
+install:
+
+clean:
+ -rm -f *.PS *.dit core
+
+distclean: clean
+
+realclean: distclean
+
+extraclean: clean
+ -rm -f core *~ \#* junk temp grot
diff --git a/gnu/usr.bin/groff/doc/meintro.me b/gnu/usr.bin/groff/doc/meintro.me
new file mode 100644
index 000000000000..192edb7b77c5
--- /dev/null
+++ b/gnu/usr.bin/groff/doc/meintro.me
@@ -0,0 +1,2246 @@
+.\" Copyright (c) 1986 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley. The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" @(#)intro.me 6.4 (Berkeley) 7/17/89
+.\"
+.\" Modified for groff by jjc@jclark.com.
+.\"UC 7
+.ll 6.5i
+.lt 6.5i
+.ds MO @VERSION@
+.nr si 3n
+.he 'USING GROFF AND \-ME''%'
+.\"eh 'USD:22-%''Writing Papers with NROFF using \-me'
+.\"oh 'Writing Papers with NROFF using \-me''USD:22-%'
+.ds U \s-1UNIX\s0
+.ds N \s-1NROFF\s0
+.ds T \s-1TROFF\s0
+.ds G \s-1GROFF\s0
+.+c
+.(l C
+.sz 14
+.b "Writing Papers with GROFF using \-me"
+.sz
+.sp 2
+.ul
+Eric P. Allman*
+.(f
+*Author's current address:
+Britton Lee, Inc.,
+1919 Addison Suite 105,
+Berkeley, California 94704.
+.)f
+.sp
+Project INGRES
+Electronics Research Laboratory
+University of California, Berkeley
+Berkeley, California 94720
+.sp 2
+.i "Modified for \*G by James Clark"
+.)l
+.sp 4
+.pp
+This document describes
+the text processing facilities
+available on the \*U\(dg
+.(f
+\(dg\*U is a trademark
+of AT&T Bell Laboratories
+.)f
+operating system
+via \*G and the
+\-me
+macro package.
+It is assumed
+that the reader
+already is generally familiar
+with the \*U operating system
+and a text editor
+such as
+.b ex .
+This is intended to be a casual introduction,
+and
+as such not all material is covered.
+In particular,
+many variations and additional features
+of the \-me macro package
+are not explained.
+For a complete discussion of this
+and other issues,
+see
+.ul
+The \-me Reference Manual
+and
+.ul
+The \*N/\*T Reference Manual.
+.pp
+\*G, a computer program
+that runs on the \*U operating system,
+reads an input file
+prepared by the user
+and outputs a formatted paper
+suitable for publication or framing.
+The input consists of
+.i text ,
+or words to be printed,
+and
+.i requests ,
+which give instructions
+to the \*G program
+telling how to format the printed copy.
+.pp
+Section 1
+describes the basics
+of text processing.
+Section 2
+describes the basic requests.
+Section 3
+introduces displays.
+Annotations,
+such as footnotes,
+are handled in
+section 4.
+The more complex requests
+which are not discussed in section 2
+are covered in section 5.
+Finally,
+section 6
+discusses things you will need
+to know
+if you want to typeset documents.
+If you are a novice,
+you probably won't want to read beyond section 4
+until you have tried some of the basic features out.
+.pp
+When you have your raw text ready,
+call the \*G formatter by typing
+as a request to the \*U shell:
+.(b
+groff \-me \-T\c
+.i "type files"
+.)b
+where
+.i type
+describes the type of
+output device you are using.
+A complete description of options
+to the \*G command can be found in
+.b groff (1).
+.pp
+The word
+.i argument
+is used in this manual
+to mean a word or number
+which appears on the same line
+as a request
+which modifies the meaning
+of that request.
+For example,
+the request
+.(b
+\&.sp
+.)b
+spaces one line,
+but
+.(b
+\&.sp 4
+.)b
+spaces four lines.
+The number
+.b 4
+is an
+.i argument
+to the
+.b .sp
+request
+which says to space four lines
+instead of one.
+Arguments are separated from the request
+and from each other
+by spaces.
+.sh 1 "Basics of Text Processing"
+.pp
+The primary function
+of \*G
+is to
+.i collect
+words from input lines,
+.i fill
+output lines with those words,
+.i justify
+the right hand margin by inserting extra spaces
+in the line,
+and output the result.
+For example,
+the input:
+.(b
+Now is the time
+for all good men
+to come to the aid
+of their party.
+Four score and seven
+years ago,...
+.)b
+will be read,
+packed onto output lines,
+and justified
+to produce:
+.(b F
+Now is the time
+for all good men
+to come to the aid
+of their party.
+Four score and seven
+years ago,...
+.)b
+Sometimes you may want to start a new output line
+even though the line you are on
+is not yet full;
+for example,
+at the end of a paragraph.
+To do this
+you can cause a
+.i break ,
+which
+starts a new output line.
+Some requests
+cause a break automatically,
+as do blank input lines
+and input lines beginning with a space.
+.pp
+Not all input lines
+are text to be formatted.
+Some of the input lines
+are
+.i requests
+which describe
+how to format the text.
+Requests always have a period
+or an apostrophe
+(\c
+.q "\|\(aa\|" )
+as the first character
+of the input line.
+.pp
+The text formatter
+also does more complex things,
+such as automatically numbering pages,
+skipping over page folds,
+putting footnotes in the correct place,
+and so forth.
+.pp
+I can offer you a few hints
+for preparing text
+for input to \*G.
+First,
+keep the input lines short.
+Short input lines are easier to edit,
+and \*G will pack words onto longer lines
+for you anyhow.
+In keeping with this,
+it is helpful
+to begin a new line
+after every period,
+comma,
+or phrase,
+since common corrections
+are to add or delete sentences
+or phrases.
+Second,
+do not put spaces at the end of lines,
+since this can sometimes confuse the \*N
+processor.
+Third,
+do not hyphenate words at the end of lines
+(except words that should have hyphens in them,
+such as
+.q mother-in-law );
+\*G is smart enough to hyphenate words
+for you as needed,
+but is not smart enough
+to take hyphens out
+and join a word back together.
+Also,
+words such as
+.q mother-in-law
+should not be broken
+over a line,
+since then you will get a space
+where not wanted,
+such as
+.tr @-
+.nh
+.q "mother@\ in@law" .
+.br
+.tr @@
+.hy 14
+.sh 1 "Basic Requests"
+.sh 2 "Paragraphs"
+.pp
+Paragraphs are begun
+by using the
+.b .pp
+request.
+For example,
+the input:
+.(b
+\&.pp
+Now is the time for all good men
+to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+produces a blank line
+followed by an indented first line.
+The result is:
+.(b F
+.ti +\n(piu
+Now is the time for all good men
+to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+.pp
+Notice that the sentences
+of the paragraphs
+.i "must not"
+begin with a space,
+since blank lines
+and lines beginning with spaces
+cause a break.
+For example,
+if I had typed:
+.(b
+\&.pp
+Now is the time for all good men
+ to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+The output would be:
+.(b F
+.ti +\n(piu
+Now is the time for all good men
+ to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+A new line begins after the word
+.q men
+because the second line began with a space character.
+.pp
+There are many
+fancier
+types of paragraphs,
+which will be described later.
+.sh 2 "Headers and Footers"
+.pp
+Arbitrary headers and footers
+can be put
+at the top and bottom
+of every page.
+Two requests
+of the form
+.b .he \ \c
+.i title
+and
+.b .fo \ \c
+.i title
+define the titles to put at the head and the foot
+of every page,
+respectively.
+The titles are called
+.i three-part
+titles,
+that is,
+there is a left-justified part,
+a centered part,
+and a right-justified part.
+To separate these three parts
+the first character of
+.i title
+(whatever it may be)
+is used as a delimiter.
+Any character may be used,
+but
+backslash
+and double quote marks
+should be avoided.
+The percent sign
+is replaced by the current page number
+whenever found in the title.
+For example,
+the input:
+.(b
+\&.he \(aa\(aa%\(aa\(aa
+\&.fo \(aaJane Jones\(aa\(aaMy Book\(aa
+.)b
+results in the page number
+centered at the top
+of each page,
+.q "Jane Jones"
+in the lower left corner,
+and
+.q "My Book"
+in the lower right corner.
+.sh 2 "Double Spacing"
+.pp
+.ls 2
+\*G will double space output text automatically if you
+use the request
+.b ".ls\ 2" ,
+as is done in this section.
+You can revert to single spaced mode
+by typing
+.b ".ls\ 1" .
+.ls 1
+.sh 2 "Page Layout"
+.pp
+A number of requests allow
+you to change the way the printed copy looks,
+sometimes called the
+.i layout
+of the output page.
+Most of these requests adjust the placing
+of
+.q "white space"
+(blank lines or spaces).
+In these explanations,
+characters in italics
+should be replaced with values you wish to use;
+bold characters
+represent characters which should actually be typed.
+.pp
+The
+.b .bp
+request
+starts a new page.
+.pp
+The request
+.b .sp \ \c
+.i N
+leaves
+.i N
+lines of blank space.
+.i N
+can be omitted
+(meaning skip a single line)
+or can be of the form
+.i N \^\c
+.b i
+(for
+.i N
+inches)
+or
+.i N \^\c
+.b c
+(for
+.i N
+centimeters).
+For example, the input:
+.(b
+\&.sp 1.5i
+My thoughts on the subject
+\&.sp
+.)b
+leaves one and a half inches of space,
+followed by the line
+.q "My thoughts on the subject" ,
+followed by a single blank line.
+.pp
+The
+.b .in \ \c
+.i +N
+request
+changes the amount of white space
+on the left of the page
+(the
+.i indent ).
+The argument
+.i N
+can be of the form
+.b + \c
+.i N
+(meaning leave
+.i N
+spaces more than you are already leaving),
+.b \- \c
+.i N
+(meaning leave less than you do now),
+or just
+.i N
+(meaning leave exactly
+.i N
+spaces).
+.i N
+can be of the form
+.i N \^\c
+.b i
+or
+.i N \^\c
+.b c
+also.
+For example,
+the input:
+.(b
+initial text
+\&.in 5
+some text
+\&.in +1i
+more text
+\&.in \-2c
+final text
+.)b
+produces
+.q "some text"
+indented exactly five spaces
+from the left margin,
+.q "more text"
+indented five spaces
+plus one inch
+from the left margin
+(fifteen spaces
+on a pica typewriter),
+and
+.q "final text"
+indented five spaces
+plus one inch
+minus two centimeters
+from the margin.
+That is,
+the output is:
+.(b
+initial text
+.in +5
+some text
+.in +1i
+more text
+.in -2c
+final text
+.)b
+.pp
+The
+.b .ti \ \c
+.i +N
+(temporary indent)
+request is used like
+.b .in \ \c
+.i +N
+when the indent
+should apply to one line only,
+after which it should revert
+to the previous indent.
+For example,
+the input:
+.(b
+\&.in 1i
+\&.ti 0
+Ware, James R. The Best of Confucius,
+Halcyon House, 1950.
+An excellent book containing translations of
+most of Confucius\(aa most delightful sayings.
+A definite must for anyone interested in the early foundations
+of Chinese philosophy.
+.)b
+produces:
+.in 1i+\n($iu
+.ti \n($iu
+Ware, James R. The Best of Confucius,
+Halcyon House, 1950.
+An excellent book containing translations of
+most of Confucius' most delightful sayings.
+A definite must for anyone interested in the early foundations
+of Chinese philosophy.
+.pp
+Text lines can be centered
+by using the
+.b .ce
+request.
+The line after the
+.b .ce
+is centered
+(horizontally)
+on the page.
+To center more than one line,
+use
+.b .ce \ \c
+.i N
+(where
+.i N
+is the number of lines to center),
+followed by the
+.i N
+lines.
+If you want to center many lines
+but don't want to count them,
+type:
+.(b
+\&.ce 1000
+lines to center
+\&.ce 0
+.)b
+The
+.b ".ce\ 0"
+request tells \*G to center zero more lines,
+in other words,
+stop centering.
+.pp
+All of these requests
+cause a break;
+that is,
+they always start
+a new line.
+If you want to start a new line
+without performing any other action,
+use
+.b .br .
+.sh 1 "Displays"
+.pp
+Displays are sections of text
+to be set off
+from the body of the paper.
+Major quotes,
+tables,
+and figures
+are types of displays,
+as are all the examples
+used in this document.
+All displays
+except centered blocks
+are output
+single spaced.
+.sh 2 "Major Quotes"
+.pp
+Major quotes
+are quotes which are several lines long,
+and hence are set in from the rest
+of the text
+without quote marks
+around them.
+These can be generated
+using the commands
+.b .(q
+and
+.b .)q
+to surround the quote.
+For example,
+the input:
+.(b
+As Weizenbaum points out:
+\&.(q
+It is said that to explain is to explain away.
+This maxim is nowhere so well fulfilled
+as in the areas of computer programming,...
+\&.)q
+.)b
+generates as output:
+.lp
+As Weizenbaum points out:
+.(q
+It is said that to explain is to explain away.
+This maxim is nowhere so well fulfilled
+as in the areas of computer programming,...
+.)q
+.sh 2 "Lists"
+.pp
+A
+.i list
+is an indented,
+single spaced,
+unfilled display.
+Lists should be used
+when the material to be printed
+should not be filled and justified
+like normal text,
+such as columns of figures
+or the examples used in this paper.
+Lists are surrounded
+by the requests
+.b .(l
+and
+.b .)l .
+For example,
+type:
+.(b
+Alternatives to avoid deadlock are:
+\&.(l
+Lock in a specified order
+Detect deadlock and back out one process
+Lock all resources needed before proceeding
+\&.)l
+.)b
+will produce:
+.br
+Alternatives to avoid deadlock are:
+.(l
+Lock in a specified order
+Detect deadlock and back out one process
+Lock all resources needed before proceeding
+.)l
+.sh 2 "Keeps"
+.pp
+A
+.i keep
+is a display of lines
+which are kept on a single page
+if possible.
+An example of where you would use a keep
+might be a diagram.
+Keeps differ from lists
+in that lists may be broken
+over a page boundary
+whereas keeps will not.
+.pp
+Blocks are the basic kind of keep.
+They begin with the request
+.b .(b
+and end with the request
+.b .)b .
+If there is not room on the current page
+for everything in the block,
+a new page is begun.
+This has the unpleasant effect
+of leaving blank space
+at the bottom of the page.
+When this is not appropriate,
+you can use the alternative,
+called
+.i "floating keeps" .
+.pp
+.i "Floating keeps"
+move relative to the text.
+Hence,
+they are good for things
+which will be referred to
+by name,
+such as
+.q "See figure 3" .
+A floating keep will appear
+at the bottom of the current page
+if it will fit;
+otherwise,
+it will appear at the top
+of the next page.
+Floating keeps begin with the line
+.b .(z
+and end with the line
+.b .)z .
+For an example of a floating keep,
+see figure 1.
+.(z
+.in 1i
+.xl -1i
+.hl
+\&.(z
+\&.hl
+Text of keep to be floated.
+\&.sp
+\&.ce
+Figure 1. Example of a Floating Keep.
+\&.hl
+\&.)z
+.sp
+.ce
+Figure 1. Example of a Floating Keep.
+.hl
+.)z
+The
+.b .hl
+request is used
+to draw a horizontal line
+so that the figure
+stands out from the text.
+.sh 2 "Fancier Displays"
+.pp
+Keeps and lists are normally collected in
+.i nofill
+mode,
+so that they are good for tables and such.
+If you want a display
+in fill mode
+(for text),
+type
+.b ".(l\ F"
+(Throughout this section,
+comments applied to
+.b .(l
+also apply to
+.b .(b
+and
+.b .(z ).
+This kind of display
+will be indented from both margins.
+For example,
+the input:
+.(b
+\&.(l F
+And now boys and girls,
+a newer, bigger, better toy than ever before!
+Be the first on your block to have your own computer!
+Yes kids, you too can have one of these modern
+data processing devices.
+You too can produce beautifully formatted papers
+without even batting an eye!
+\&.)l
+.)b
+will be output as:
+.(b F
+And now boys and girls,
+a newer, bigger, better toy than ever before!
+Be the first on your block to have your own computer!
+Yes kids, you too can have one of these modern
+data processing devices.
+You too can produce beautifully formatted papers
+without even batting an eye!
+.)b
+.pp
+Lists and blocks are also normally indented
+(floating keeps are normally left justified).
+To get a left-justified list,
+type
+.b ".(l\ L" .
+To get a list centered
+line-for-line,
+type
+.b ".(l C" .
+For example,
+to get a filled,
+left justified list, enter:
+.(b
+\&.(l L F
+text of block
+\&.)l
+.)b
+The input:
+.(b
+\&.(l
+first line of unfilled display
+more lines
+\&.)l
+.)b
+produces the indented text:
+.(b
+first line of unfilled display
+more lines
+.)b
+Typing the character
+.b L
+after the
+.b .(l
+request produces the left justified result:
+.(b L
+first line of unfilled display
+more lines
+.)b
+Using
+.b C
+instead of
+.b L
+produces the line-at-a-time centered output:
+.(b C
+first line of unfilled display
+more lines
+.)b
+.pp
+Sometimes it may be
+that you want to center several lines
+as a group,
+rather than centering them
+one line at a time.
+To do this
+use centered blocks,
+which are surrounded by the requests
+.b .(c
+and
+.b .)c .
+All the lines are centered as a unit,
+such that the longest line is centered
+and the rest are
+lined up around that line.
+Notice that lines
+do not move
+relative to each other
+using centered blocks,
+whereas they do
+using the
+.b C
+argument to keeps.
+.pp
+Centered blocks are
+.i not
+keeps,
+and may be used
+in conjunction
+with keeps.
+For example,
+to center a group of lines
+as a unit
+and keep them
+on one page,
+use:
+.(b
+\&.(b L
+\&.(c
+first line of unfilled display
+more lines
+\&.)c
+\&.)b
+.)b
+to produce:
+.(b L
+.(c
+first line of unfilled display
+more lines
+.)c
+.)b
+If the block requests
+(\c
+.b .(b
+and
+.b .)b )
+had been omitted
+the result would have been the same,
+but with no guarantee
+that the lines of the centered block
+would have all been on one page.
+Note the use of the
+.b L
+argument to
+.b .(b ;
+this causes the centered block
+to center within the entire line
+rather than within the line
+minus the indent.
+Also,
+the center requests
+must
+be nested
+.i inside
+the keep requests.
+.sh 1 "Annotations"
+.pp
+There are a number of requests
+to save text
+for later printing.
+.i Footnotes
+are printed at the bottom of the current page.
+.i "Delayed text"
+is intended to be a variant form
+of footnote;
+the text is printed only
+when explicitly called for,
+such as at the end of each chapter.
+.i Indexes
+are a type of delayed text
+having a tag
+(usually the page number)
+attached to each entry
+after a row of dots.
+Indexes are also saved
+until called for explicitly.
+.sh 2 "Footnotes"
+.pp
+Footnotes begin with the request
+.b .(f
+and end with the request
+.b .)f .
+The current footnote number is maintained
+automatically,
+and can be used by typing \e**,
+to produce a footnote number\**.
+.(f
+\**Like this.
+.)f
+The number is automatically incremented
+after every footnote.
+For example,
+the input:
+.(b
+\&.(q
+A man who is not upright
+and at the same time is presumptuous;
+one who is not diligent and at the same time is ignorant;
+one who is untruthful and at the same time is incompetent;
+such men I do not count among acquaintances.\e**
+\&.(f
+\e**James R. Ware,
+\&.ul
+The Best of Confucius,
+Halcyon House, 1950.
+Page 77.
+\&.)f
+\&.)q
+.)b
+generates the result:
+.(q
+A man who is not upright
+and at the same time is presumptuous;
+one who is not diligent and at the same time is ignorant;
+one who is untruthful and at the same time is incompetent;
+such men I do not count among acquaintances.\**
+.(f
+\**James R. Ware,
+.ul
+The Best of Confucius,
+Halcyon House, 1950.
+Page 77.
+.)f
+.)q
+It is important
+that the footnote
+appears
+.i inside
+the quote,
+so that you can be sure
+that the footnote
+will appear
+on the same page
+as the quote.
+.sh 2 "Delayed Text"
+.pp
+Delayed text
+is very similar to a footnote
+except that it is printed
+when called for explicitly.
+This allows a list of
+references to
+appear
+(for example)
+at the end of each chapter,
+as is the convention in some disciplines.
+Use
+.b \e*#
+on delayed text
+instead of
+.b \e**
+as on footnotes.
+.pp
+If you are using delayed text
+as your standard reference mechanism,
+you can still use footnotes,
+except that you may want to reference them
+with special characters*
+.(f
+*Such as an asterisk.
+.)f
+rather than numbers.
+.sh 2 "Indexes"
+.pp
+An
+.q index
+(actually more like a table of contents,
+since the entries are not sorted alphabetically)
+resembles delayed text,
+in that it is saved until called for.
+However,
+each entry has the page number
+(or some other tag)
+appended to the last line
+of the index entry
+after a row of dots.
+.pp
+Index entries begin with the request
+.b .(x
+and end with
+.b .)x .
+The
+.b .)x
+request may have a argument,
+which is the value to print
+as the
+.q "page number" .
+It defaults to the current page number.
+If the page number given is an underscore
+(\c
+.q _ )
+no page number
+or line of dots
+is printed at all.
+To get the line of dots
+without a page number,
+type
+.b ".)x """"" ,
+which specifies an explicitly null page number.
+.pp
+The
+.b .xp
+request prints the index.
+.pp
+For example,
+the input:
+.(b
+\&.(x
+Sealing wax
+\&.)x
+\&.(x
+Cabbages and kings
+\&.)x _
+\&.(x
+Why the sea is boiling hot
+\&.)x 2.5a
+\&.(x
+Whether pigs have wings
+\&.)x ""
+\&.(x
+This is a terribly long index entry, such as might be used
+for a list of illustrations, tables, or figures; I expect it to
+take at least two lines.
+\&.)x
+\&.xp
+.)b
+generates:
+.(x
+Sealing wax
+.)x
+.(x
+Cabbages and kings
+.)x _
+.(x
+Why the sea is boiling hot
+.)x 2.5a
+.(x
+Whether pigs have wings
+.)x ""
+.(x
+This is a terribly long index entry, such as might be used
+for a list of illustrations, tables, or figures; I expect it to
+take at least two lines.
+.)x
+.xp
+.pp
+The
+.b .(x
+request may have a single character
+argument,
+specifying the
+.q name
+of the index;
+the normal index is
+.b x .
+Thus,
+several
+.q indices
+may be maintained simultaneously
+(such as a list of tables, table of contents, etc.).
+.pp
+Notice that the index must be printed
+at the
+.i end
+of the paper,
+rather than at the beginning
+where it will probably appear
+(as a table of contents);
+the pages may have to be physically rearranged
+after printing.
+.sh 1 "Fancier Features"
+.pp
+A large number of fancier requests
+exist,
+notably requests to provide other sorts of paragraphs,
+numbered sections of the form
+.b 1.2.3
+(such as used in this document),
+and multicolumn output.
+.sh 2 "More Paragraphs"
+.pp
+Paragraphs generally start with
+a blank line
+and with the first line
+indented.
+It is possible to get
+left-justified block-style paragraphs
+by using
+.b .lp
+instead of
+.b .pp ,
+as demonstrated by the next paragraph.
+.lp
+Sometimes you want to use paragraphs
+that have the
+.i body
+indented,
+and the first line
+exdented
+(opposite of indented)
+with a label.
+This can be done with the
+.b .ip
+request.
+A word specified on the same line as
+.b .ip
+is printed in the margin,
+and the body is lined up
+at a prespecified position
+(normally five spaces).
+For example,
+the input:
+.(b
+\&.ip one
+This is the first paragraph.
+Notice how the first line
+of the resulting paragraph lines up
+with the other lines in the paragraph.
+\&.ip two
+And here we are at the second paragraph already.
+You may notice that the argument to \c
+.b .ip
+appears
+in the margin.
+\&.lp
+We can continue text...
+.)b
+produces as output:
+.ip one
+This is the first paragraph.
+Notice how the first line of the resulting paragraph lines up
+with the other lines in the paragraph.
+.ip two
+And here we are at the second paragraph already.
+You may notice that the argument to
+.b .ip
+appears
+in the margin.
+.lp
+We can continue text without starting a new indented
+paragraph
+by using the
+.b .lp
+request.
+.pp
+If you have spaces in the label of a
+.b .ip
+request,
+you must use an
+.q "unpaddable space"
+instead of a regular space.
+This is typed as a backslash character
+(\c
+.q \e )
+followed by a space.
+For example,
+to print the label
+.q "Part 1" ,
+enter:
+.(b
+\&.ip "Part\e 1"
+.)b
+.pp
+If a label of an indented paragraph
+(that is, the argument to
+.b .ip )
+is longer than the space allocated for the label,
+.b .ip
+will begin a new line after the label.
+For example,
+the input:
+.(b
+\&.ip longlabel
+This paragraph had a long label.
+The first character of text on the first line
+will not line up with the text on second and subsequent lines,
+although they will line up with each other.
+.)b
+will produce:
+.ip longlabel
+This paragraph had a long label.
+The first character of text on the first line
+will not line up with the text on second and subsequent lines,
+although they will line up with each other.
+.pp
+It is possible to change the size of the label
+by using a second argument
+which is the size of the label.
+For example,
+the above example could be done correctly
+by saying:
+.(b
+\&.ip longlabel 10
+.)b
+which will make the paragraph indent
+10 spaces for this paragraph only.
+If you have many paragraphs to indent
+all the same amount,
+use the
+.i "number register"
+.b ii .
+For example, to leave one inch of space
+for the label,
+type:
+.(b
+\&.nr ii 1i
+.)b
+somewhere before the first call to
+.b .ip .
+Refer to the reference manual
+for more information.
+.pp
+If
+.b .ip
+is used
+with no argument at all
+no hanging tag will be printed.
+For example,
+the input:
+.(b
+\&.ip [a]
+This is the first paragraph of the example.
+We have seen this sort of example before.
+\&.ip
+This paragraph is lined up with the previous paragraph,
+but it has no tag in the margin.
+.)b
+produces as output:
+.ip [a]
+This is the first paragraph of the example.
+We have seen this sort of example before.
+.ip
+This paragraph is lined up with the previous paragraph,
+but it has no tag in the margin.
+.pp
+A special case of
+.b .ip
+is
+.b .np ,
+which automatically
+numbers paragraphs sequentially from 1.
+The numbering is reset at the next
+.b .pp ,
+.b .lp ,
+or
+.b .sh
+(to be described in the next section)
+request.
+For example,
+the input:
+.(b
+\&.np
+This is the first point.
+\&.np
+This is the second point.
+Points are just regular paragraphs
+which are given sequence numbers automatically
+by the .np request.
+\&.pp
+This paragraph will reset numbering by .np.
+\&.np
+For example,
+we have reverted to numbering from one now.
+.)b
+generates:
+.np
+This is the first point.
+.np
+This is the second point.
+Points are just regular paragraphs
+which are given sequence numbers automatically
+by the .np request.
+.pp
+This paragraph will reset numbering by .np.
+.np
+For example,
+we have reverted to numbering from one now.
+.pp
+The
+.b .bu
+request gives lists of this sort that are identified with
+bullets rather than numbers.
+The paragraphs are also crunched together.
+For example,
+the input:
+.(b
+\&.bu
+\&One egg yolk
+\&.bu
+\&One tablespoon cream or top milk
+\&.bu
+\&Salt, cayenne, and lemon juice to taste
+\&.bu
+\&A generous two tablespoonfuls of butter
+.)b
+produces\**:
+.(f
+\**By the way,
+if you put the first three ingredients in a a heavy, deep pan
+and whisk the ingredients madly over a medium flame
+(never taking your hand off the handle of the pot)
+until the mixture reaches the consistency of custard
+(just a minute or two),
+then mix in the butter off-heat,
+you will have a wonderful Hollandaise sauce.
+.)f
+.bu
+One egg yolk
+.bu
+One tablespoon cream or top milk
+.bu
+Salt, cayenne, and lemon juice to taste
+.bu
+A generous two tablespoonfuls of butter
+.sh 2 "Section Headings"
+.pp
+Section numbers
+(such as the ones used in this document)
+can be automatically generated
+using the
+.b .sh
+request.
+You must tell
+.b .sh
+the
+.i depth
+of the section number
+and a section title.
+The depth
+specifies how many numbers
+are to appear
+(separated by decimal points)
+in the section number.
+For example,
+the section number
+.b 4.2.5
+has a depth of three.
+.pp
+Section numbers
+are incremented
+in a fairly intuitive fashion.
+If you add a number
+(increase the depth),
+the new number starts out
+at one.
+If you subtract section numbers
+(or keep the same number)
+the final number is incremented.
+For example,
+the input:
+.(b
+\&.sh 1 "The Preprocessor"
+\&.sh 2 "Basic Concepts"
+\&.sh 2 "Control Inputs"
+\&.sh 3
+\&.sh 3
+\&.sh 1 "Code Generation"
+\&.sh 3
+.)b
+produces as output the result:
+.(b
+.b
+1. The Preprocessor
+1.1. Basic Concepts
+1.2. Control Inputs
+1.2.1.
+1.2.2.
+2. Code Generation
+2.1.1.
+.)b
+.pp
+You can specify the section number to begin
+by placing the section number after the section title,
+using spaces instead of dots.
+For example,
+the request:
+.(b
+\&.sh 3 "Another section" 7 3 4
+.)b
+will begin the section numbered
+.b 7.3.4 ;
+all subsequent
+.b .sh
+requests will number relative to this number.
+.pp
+There are more complex features
+which will cause each section to be indented
+proportionally to the depth of the section.
+For example, if you enter:
+.(b
+\&.nr si \c
+.i N
+.)b
+each section will be indented by an amount
+.i N .
+.i N
+must have a scaling factor attached,
+that is, it must be of the form
+.i Nx ,
+where
+.i x
+is a character telling what units
+.i N
+is in.
+Common values for
+.i x
+are
+.b i
+for inches,
+.b c
+for centimeters,
+and
+.b n
+for
+.i ens
+(the width of a single character).
+For example,
+to indent each section
+one-half inch,
+type:
+.(b
+\&.nr si 0.5i
+.)b
+After this,
+sections will be indented by
+one-half inch
+per level of depth in the section number.
+For example,
+this document was produced
+using the request
+.(b
+\&.nr si 3n
+.)b
+at the beginning of the input file,
+giving three spaces of indent
+per section depth.
+.pp
+Section headers without automatically generated numbers
+can be done using:
+.(b
+\&.uh "Title"
+.)b
+which will do a section heading,
+but will put no number on the section.
+.sh 2 "Parts of the Basic Paper"
+.pp
+There are some requests
+which assist in setting up
+papers.
+The
+.b .tp
+request
+initializes for a title page.
+There are no headers or footers
+on a title page,
+and unlike other pages
+you can space down
+and leave blank space
+at the top.
+For example,
+a typical title page might appear as:
+.(b
+\&.tp
+\&.sp 2i
+\&.(l C
+THE GROWTH OF TOENAILS
+IN UPPER PRIMATES
+\&.sp
+by
+\&.sp
+Frank N. Furter
+\&.)l
+\&.bp
+.)b
+.pp
+The
+.b .+c \ \c
+.i T
+request can be used
+to start chapters.
+Each chapter is automatically numbered
+from one,
+and a heading is printed at the top of each chapter
+with the chapter number
+and the chapter name
+.i T .
+For example,
+to begin a chapter called
+.q Conclusions ,
+use the request:
+.(b
+\&.+c "CONCLUSIONS"
+.)b
+which will produce,
+on a new page,
+the lines
+.(b C
+CHAPTER 5
+CONCLUSIONS
+.)b
+with appropriate spacing for a thesis.
+Also, the header is moved to the foot of the page
+on the first page of a chapter.
+Although the
+.b .+c
+request was not designed to work only with the
+.b .th
+request,
+it is tuned for the format acceptable
+for a PhD thesis
+at Berkeley.
+.pp
+If the
+title parameter
+.i T
+is omitted from the
+.b .+c
+request,
+the result is a chapter with no heading.
+This can also be used at the beginning
+of a paper;
+for example,
+.b .+c
+was used to generate page one
+of this document.
+.pp
+Although
+papers traditionally have the abstract,
+table of contents,
+and so forth at the front of the paper,
+it is more convenient to format
+and print them last
+when using \*G.
+This is so that index entries
+can be collected and then printed
+for the table of contents
+(or whatever).
+At the end of the paper,
+issue the
+.b ".++ P"
+request,
+which begins the preliminary part
+of the paper.
+After issuing this request,
+the
+.b .+c
+request will begin a preliminary section
+of the paper.
+Most notably,
+this prints the page number
+restarted from one
+in lower case Roman numbers.
+.b .+c
+may be used repeatedly
+to begin different parts of the
+front material
+for example,
+the abstract,
+the table of contents,
+acknowledgments,
+list of illustrations,
+etc.
+The request
+.b ".++ B"
+may also be used
+to begin the bibliographic section
+at the end of the paper.
+For example,
+the paper might appear
+as outlined in figure 2.
+(In this figure,
+comments begin with the sequence
+.b \e" .)
+.(z
+.hl
+.if t .in 0.5i
+.if t .ta 2i
+.if n .ta 3i
+\&.th \e" set for thesis mode
+\&.fo \(aa\(aaDRAFT\(aa\(aa \e" define footer for each page
+\&.tp \e" begin title page
+\&.(l C \e" center a large block
+THE GROWTH OF TOENAILS
+IN UPPER PRIMATES
+\&.sp
+by
+\&.sp
+Frank Furter
+\&.)l \e" end centered part
+\&.+c INTRODUCTION \e" begin chapter named "INTRODUCTION"
+\&.(x t \e" make an entry into index `t'
+Introduction
+\&.)x \e" end of index entry
+text of chapter one
+\&.+c "NEXT CHAPTER" \e" begin another chapter
+\&.(x t \e" enter into index `t' again
+Next Chapter
+\&.)x
+text of chapter two
+\&.+c CONCLUSIONS
+\&.(x t
+Conclusions
+\&.)x
+text of chapter three
+\&.++ B \e" begin bibliographic information
+\&.+c BIBLIOGRAPHY \e" begin another `chapter'
+\&.(x t
+Bibliography
+\&.)x
+text of bibliography
+\&.++ P \e" begin preliminary material
+\&.+c "TABLE OF CONTENTS"
+\&.xp t \e" print index `t' collected above
+\&.+c PREFACE \e" begin another preliminary section
+text of preface
+.sp 2
+.in 0
+.ce
+Figure 2. Outline of a Sample Paper
+.hl
+.)z
+.sh 2 "Equations and Tables"
+.pp
+Two special \*U programs exist
+to format special types of material.
+.b Eqn
+sets equations.
+.b Tbl
+arranges to print
+extremely pretty tables
+in a variety of formats.
+This document will only describe
+the embellishments
+to the standard features;
+consult the reference manuals
+for those processors
+for a description of their use.
+.pp
+The
+.b eqn
+program is described fully
+in the document
+.ul
+Typesetting Mathematics \- User's Guide
+by Brian W. Kernighan
+and Lorinda L. Cherry.
+Equations are centered,
+and are kept on one page.
+They are introduced by the
+.b .EQ
+request and terminated by the
+.b .EN
+request.
+.pp
+The
+.b .EQ
+request may take an
+equation number as an
+optional argument,
+which is printed vertically centered
+on the right hand side
+of the equation.
+If the equation becomes too long
+it should be split
+between two lines.
+To do this, type:
+.(b
+\&.EQ (eq 34)
+text of equation 34
+\&.EN C
+\&.EQ
+continuation of equation 34
+\&.EN
+.)b
+The
+.b C
+on the
+.b .EN
+request
+specifies that the equation
+will be continued.
+.pp
+The
+.b tbl
+program produces tables.
+It is fully described
+(including numerous examples)
+in the document
+.ul
+Tbl \- A Program to Format Tables
+by M. E. Lesk.
+Tables begin with the
+.b .TS
+request
+and end with the
+.b .TE
+request.
+Tables are normally kept on a single page.
+If you have a table which is too big
+to fit on a single page,
+so that you know it will extend
+to several pages,
+begin the table with the request
+.b ".TS\ H"
+and put the request
+.b .TH
+after the part of the table
+which you want
+duplicated at the top of every page
+that the table is printed on.
+For example, a table definition
+for a long table might look like:
+.ds TA \|\h'.4n'\v'-.2n'\s-4\zT\s0\v'.2n'\h'-.4n'\(ci\|
+.if n .ds TA \ \o'-T'\ \"
+.(b
+\&.TS H
+c s s
+n n n.
+THE TABLE TITLE
+\&.TH
+text of the table
+\&.TE
+.)b
+.pp
+.sh 2 "Two Column Output"
+.pp
+You can get two column output
+automatically
+by using the request
+.b .2c .
+This causes everything after it
+to be output in two-column form.
+The request
+.b .bc
+will start a new column;
+it differs from
+.b .bp
+in that
+.b .bp
+may leave a totally blank column
+when it starts a new page.
+To revert to single column output,
+use
+.b .1c .
+.sh 2 "Defining Macros"
+.pp
+A
+.i macro
+is a collection of requests and text
+which may be used
+by stating a simple request.
+Macros begin with the line
+.b ".de" \ \c
+.i xx
+(where
+.i xx
+is the name of the macro to be defined)
+and end with the line consisting of two dots.
+After defining the macro,
+stating the line
+.b . \c
+.i xx
+is the same as stating all the other lines.
+For example,
+to define a macro
+that spaces 3 lines
+and then centers the next input line,
+enter:
+.(b
+\&.de SS
+\&.sp 3
+\&.ce
+\&..
+.)b
+and use it by typing:
+.(b
+\&.SS
+\&Title Line
+(beginning of text)
+.)b
+.pp
+Macro names may be one or two characters.
+In order to avoid conflicts
+with names in \-me,
+always use upper case letters as names.
+The only names to avoid are
+.b TS ,
+.b TH ,
+.b TE ,
+.b EQ ,
+and
+.b EN .
+.sh 2 "Annotations Inside Keeps"
+.pp
+Sometimes you may want to put
+a footnote
+or index entry inside a keep.
+For example,
+if you want to maintain a
+.q "list of figures"
+you will want to do something like:
+.(b
+\&.(z
+\&.(c
+text of figure
+\&.)c
+\&.ce
+Figure 5.
+\&.(x f
+Figure 5
+\&.)x
+\&.)z
+.)b
+which you may hope
+will give you a figure
+with a label
+and an entry in the index
+.b f
+(presumably a list of figures index).
+Unfortunately,
+the
+index entry
+is read and interpreted
+when the keep is read,
+not when it is printed,
+so the page number in the index is likely to be wrong.
+The solution is to use the magic string
+.b \e!
+at the beginning of all the lines dealing with the index.
+In other words,
+you should use:
+.(b
+\&.(z
+\&.(c
+Text of figure
+\&.)c
+\&.ce
+Figure 5.
+\e!.(x f
+\e!Figure 5
+\e!.)x
+\&.)z
+.)b
+which will defer the processing of the index
+until the figure is output.
+This will guarantee
+that the page number in the index
+is correct.
+The same comments apply
+to
+blocks
+(with
+.b .(b
+and
+.b .)b )
+as well.
+.sh 1 "\*T and the Photosetter"
+.pp
+With a little care,
+you can prepare
+documents that
+will print nicely
+on either a regular terminal
+or when phototypeset
+using the \*T formatting program.
+.sh 2 "Fonts"
+.pp
+A
+.i font
+is a style of type.
+There are three fonts
+that are available simultaneously,
+Times Roman,
+Times Italic,
+and Times Bold,
+plus the special math font.
+The normal font is Roman.
+.pp
+There are ways of switching between fonts.
+The requests
+.b .r ,
+.b .i ,
+.b .b ,
+and
+.b .bi
+switch to Roman,
+italic,
+bold,
+and bold-italic fonts respectively.
+You can set a single word
+in some font
+by typing (for example):
+.(b
+\&.i word
+.)b
+which will set
+.i word
+in italics
+but does not affect the surrounding text.
+.pp
+Notice that if you are setting more than one word
+in whatever font,
+you must surround that word with double quote marks
+(`\|"\|')
+so that it will appear to the \*G processor as a single word.
+The quote marks will not appear in the formatted text.
+If you do want a quote mark to appear,
+you should quote the entire string
+(even if a single word),
+and use
+.i two
+quote marks where you want one to appear.
+For example,
+if you want to produce the text:
+.(b
+.i """Master Control\|"""
+.)b
+in italics, you must type:
+.(b
+\&.i """Master Control\e|"""
+.)b
+The
+.b \e|
+produces a very narrow space
+so that the
+.q l
+does not overlap the quote sign in \*G,
+like this:
+.(b
+.i """Master Control"""
+.)b
+.pp
+There are also some
+.q pseudo-fonts
+available.
+The input:
+.(b
+\&.(b
+\&.u underlined
+\&.bx "words in a box"
+\&.)b
+.)b
+generates
+.(b
+.u underlined
+.bx "words in a box"
+.)b
+Notice that pseudo font requests
+set only the single parameter in the pseudo font;
+ordinary font requests will begin setting all text
+in the special font
+if you do not provide a parameter.
+No more than one word
+should appear
+with these three font requests
+in the middle of lines.
+This is because
+of the way \*G justifies text.
+For example,
+if you were to issue the requests:
+.(b
+\&.u "some bold italics"
+and
+\&.bx "words in a box"
+.)b
+in the middle of a line
+\*G would produce
+.u "some bold italics"
+and
+.bx "words in a box" ,\p
+which I think you will agree does not look good.
+.pp
+The second parameter
+of all font requests
+is set in the original font.
+For example,
+the font request:
+.(b
+\&.b bold face
+.)b
+generates
+.q bold
+in bold font,
+but sets
+.q face
+in the font of the surrounding text,
+resulting in:
+.(b
+.b bold face.
+.)b
+To set the two words
+.b bold
+and
+.b face
+both in
+.b "bold face" ,
+type:
+.(b
+\&.b "bold face"
+.)b
+.pp
+You can mix fonts in a word by using the
+special sequence
+.b \ec
+at the end of a line
+to indicate
+.q "continue text processing" ;
+this allows input lines
+to be joined together
+without a space between them.
+For example, the input:
+.(b
+\&.u under \ec
+\&.i italics
+.)b
+generates
+.u under \c
+.i italics ,
+but if we had typed:
+.(b
+\&.u under
+\&.i italics
+.)b
+the result would have been
+.u under
+.i italics
+as two words.
+.sh 2 "Point Sizes"
+.pp
+The phototypesetter
+supports different sizes of type,
+measured in points.
+The default point size
+is 10 points
+for most text,
+8 points for footnotes.
+To change the pointsize,
+type:
+.(b
+\&.sz \c
+.i +N
+.)b
+where
+.i N
+is the size wanted in points.
+The
+.i "vertical spacing"
+(distance between the bottom of most letters
+(the
+.i baseline )
+between adjacent lines)
+is set to be proportional
+to the type size.
+.pp
+These pointsize changes are
+.i temporary !!!
+For example,
+to reset the pointsize of basic text to twelve point, use:
+.(b
+\&.nr pp 12
+\&.nr sp 12
+\&.nr tp 12
+.)b
+to reset the default pointsize of
+paragraphs,
+section headers,
+and titles respectively.
+If you only want to set the names of sections in a larger pointsize,
+use:
+.(b
+\&.nr sp 11
+.)b
+alone \*- this sets section titles
+(e.g.,
+.b "Point Sizes"
+above)
+in a larger font than the default.
+.pp
+A single word or phrase can be set in a smaller pointsize
+than the surrounding text
+using the
+.b .sm
+request.
+This is especially convenient for words that are all capitals,
+due to the optical illusion that makes them look even larger
+than they actually are.
+For example:
+.(b
+\&.sm UNIX
+.)b
+prints as
+.sm UNIX
+rather than
+UNIX.
+.pp
+Warning:
+changing point sizes
+on the phototypesetter
+is a slow mechanical operation.
+On laser printers it may require loading new fonts.
+Size changes
+should be considered carefully.
+.sh 2 "Quotes"
+.pp
+It is conventional when using
+the typesetter to
+use pairs of grave and acute accents
+to generate double quotes,
+rather than the
+double quote character
+(`\|"\|').
+This is because it looks better
+to use grave and acute accents;
+for example, compare
+"quote" to
+``quote''.
+.pp
+You may use the sequences
+.b \e*(lq
+and
+.b \e*(rq
+to stand for the left and right quote
+respectively.
+For example,
+use:
+.(b
+\e*(lqSome things aren\(aat true
+even if they did happen.\e*(rq
+.)b
+to generate the result:
+.(b
+.q "Some things aren't true even if they did happen."
+.)b
+As a shorthand,
+the special font request:
+.(b
+\&.q "quoted text"
+.)b
+will generate
+.q "quoted text" .
+Notice that you must surround
+the material to be quoted
+with double quote marks
+if it is more than one word.
+.sh 0
+.sp 1i
+.b Acknowledgments
+.pp
+I would like to thank
+Bob Epstein,
+Bill Joy,
+and Larry Rowe
+for having the courage
+to use the \-me macros
+to produce non-trivial papers
+during the development stages;
+Ricki Blau,
+Pamela Humphrey,
+and Jim Joyce
+for their help with the documentation phase;
+peter kessler
+for numerous complaints years after I was
+.q done
+with this project,
+most accompanied by fixes
+(hence forcing me to fix several small bugs);
+and the plethora of people who have contributed ideas
+and have given support for the project.
+.sp 1i
+This document was
+\*G'ed
+on \*(td
+and applies to the version of the \-me macros
+included with \*G version \*(MO.
diff --git a/gnu/usr.bin/groff/doc/meref.me b/gnu/usr.bin/groff/doc/meref.me
new file mode 100644
index 000000000000..9cc2c76e8245
--- /dev/null
+++ b/gnu/usr.bin/groff/doc/meref.me
@@ -0,0 +1,2194 @@
+.\" Copyright (c) 1986 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley. The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" @(#)ref.me 6.4 (Berkeley) 7/17/89
+.\"
+.\" Modified by jjc@jclark.com for groff.
+.\"UC 7
+.ll 6.5i
+.lt 6.5i
+.\"pn 0
+.ds MO @VERSION@
+.de TL \" *** title line
+.lp
+.di XX
+..
+.ie \n(.g \{\
+.de DE
+\?\h'|\\n(DIu'\c\?
+..
+.\}
+.el \{\
+.de DE
+\\\\h'|\\\\n(DIu'\\\\c
+..
+.\}
+.am DE
+.br
+.di
+.in +\\n(DIu
+.ti 0
+.cu 1000
+.XX
+.rm XX
+.cu 0
+..
+.ds G \s-1GROFF\s0
+.ds N \s-1NROFF\s0
+.ds T \s-1TROFF\s0
+.nr DI 1.5i
+.he '\-ME REFERENCE MANUAL''%'
+.de NR
+.b "\en\\$1" "\\$2"
+..
+.de ST
+.b "\e*\\$1" "\\$2"
+..
+.\"sc
+.\"eh 'USD:23-%''\-me Reference Manual'
+.\"oh '\-me Reference Manual''USD:23-%'
+.+c
+.ce 20
+.sz 14
+.b "\-ME REFERENCE MANUAL"
+.sz
+.sp
+.i "\*G Version \*(MO\(dg"
+.(f
+\(dgBased on Berkeley Release 2.31.
+.)f
+.sp 2
+.ul
+Eric P. Allman*
+.(f
+*Author's current address:
+Britton Lee, Inc.,
+1919 Addison Suite 105,
+Berkeley, California 94704.
+.)f
+.sp
+Project INGRES
+Electronics Research Laboratory
+University of California, Berkeley
+Berkeley, California 94720
+.sp 2
+.i "Modified for \*G by James Clark"
+.ce 0
+.sp 4
+.pp
+This document describes
+in extremely terse form
+the features
+of the
+.b \-me
+macro package
+for \*G.
+Some familiarity is assumed
+with
+\*G.
+Specifically,
+the reader should understand
+breaks,
+fonts,
+pointsizes,
+the use and definition of number registers
+and strings,
+how to define macros,
+and scaling factors for ens, points,
+.b v 's
+(vertical line spaces),
+etc.
+.pp
+For a more casual introduction
+to text processing
+using \*G,
+refer to the document
+.ul
+Writing Papers with \*G using \-me.
+.pp
+There are a number of macro parameters
+that may be adjusted.
+Fonts may be set to a font number only.
+Font 0 is no font change;
+the font of the surrounding text
+is used instead.
+Notice that font 0 is a
+.q pseudo-font ;
+that is,
+it is simulated by the macros.
+This means that although it is legal to set a font register
+to zero,
+it is not legal to use the escape character form,
+such as:
+.(b
+\ef0
+.)b
+.pp
+All distances
+are in basic units,
+so it is nearly always necessary
+to use a scaling factor.
+For example,
+the request
+to set the paragraph indent
+to eight one-en spaces is:
+.(b
+\&.nr pi 8n
+.)b
+and not
+.(b
+\&.nr pi 8
+.)b
+which would set the paragraph indent to eight basic units,
+or about 0.02 inch.
+Default parameter values are given in brackets
+in the remainder of this document.
+.pp
+Registers and strings
+of the form
+.b $ \c
+.i x
+may be used in expressions
+but should not be changed.
+Macros of the form
+.b $ \c
+.i x
+perform some function
+(as described)
+and may be redefined
+to change this function.
+This may be a sensitive operation;
+look at the body of the original macro
+before changing it.
+.pp
+All names in \-me
+follow a rigid naming convention.
+The user may define number registers,
+strings,
+and macros,
+provided that s/he
+uses single character upper case names
+or double character names
+consisting of letters and digits,
+with at least one upper case letter.
+In no case should special characters
+be used in user-defined names.
+Locally defined macros
+should all be of the form
+.b .* \c
+.i X ,
+where
+.i X
+is any letter
+(upper or lower case)
+or digit.
+.pp
+This documentation was \*G'ed
+on \*(td
+and applies to \*G version
+\*(MO
+of the \-me macros.
+.sh 1 "Paragraphing"
+.pp
+These macros are used
+to begin paragraphs.
+The standard paragraph macro
+is
+.b .pp ;
+the others are all variants
+to be used for special purposes.
+.pp
+After the first call to one of the paragraphing macros
+defined in this section
+or the
+.b .sh
+macro
+(defined in the next session),
+the effects of changing parameters
+which will have a global effect
+on the format of the page
+(notably page length and header and footer margins)
+are not well defined
+and should be avoided.
+.TL
+.b .lp
+.DE
+Begin left-justified paragraph.
+Centering and underlining
+are turned off if they were on,
+the font is set to
+.NR (pf
+[1]
+the type size
+is set to
+.NR (pp
+[10p],
+and a
+.NR (ps
+space is inserted
+before the paragraph
+[0.35v]
+The indent is reset
+to
+.NR ($i
+[0]
+plus
+.NR (po
+[0]
+unless the paragraph
+is inside a display.
+(see
+.b .ba ).
+At least
+the first two lines
+of the paragraph
+are kept together
+on a page.
+.TL
+.b .pp
+.DE
+Like
+.b .lp ,
+except that it puts
+.NR (pi
+[5n]
+units of indent.
+This is the standard paragraph macro.
+.TL
+.b .ip
+.i T
+.i I
+.DE
+Indented paragraph
+with hanging tag.
+The body of the following paragraph
+is indented
+.i I
+spaces
+(or
+.NR (ii
+[5n]
+spaces
+if
+.i I
+is not specified)
+more than a non-indented paragraph
+(such as with
+.b .pp )
+is.
+The title
+.i T
+is exdented (opposite of indented).
+The result is a paragraph
+with an even left edge
+and
+.i T
+printed in the margin.
+Any spaces in
+.i T
+must be unpaddable.
+If
+.i T
+will not fit in the space provided,
+.b .ip
+will start a new line.
+.TL
+.b .np
+.DE
+A variant of .ip which numbers paragraphs.
+Numbering is reset
+after a
+.b .lp ,
+.b .pp ,
+or
+.b .sh .
+The current paragraph number
+is in
+.NR ($p .
+.TL
+.b .bu
+.DE
+Like
+.b .np
+except that paragraphs are marked with bullets (\(bu).
+Leading space is eliminated to create compact lists.
+.sh 1 "Section Headings"
+.pp
+Numbered sections
+are similar to paragraphs
+except that a
+section number
+is automatically
+generated for each one.
+The section numbers are of the form
+.b 1.2.3 .
+The
+.i depth
+of the section
+is the count of numbers
+(separated by decimal points)
+in the section number.
+.pp
+Unnumbered section headings are similar,
+except that no number is attached
+to the heading.
+.TL
+.b .sh
+.i +N
+.i T
+.i "a b c d e f"
+.DE
+Begin numbered section
+of depth
+.i N .
+If
+.i N
+is missing
+the current depth
+(maintained in
+the number register
+.NR ($0 )
+is used.
+The values of
+the individual parts of the section number
+are maintained in
+.NR ($1
+through
+.NR ($6 .
+There is a
+.NR (ss
+[1v]
+space before the section.
+.i T
+is printed
+as a section title
+in font
+.NR (sf
+[8]
+and size
+.NR (sp
+[10p].
+The
+.q name
+of the section may be accessed via
+.ST ($n .
+If
+.NR (si
+is non-zero,
+the base indent
+is set to
+.NR (si
+times the section depth,
+and the section title
+is exdented.
+(See
+.b .ba .)
+Also,
+an additional indent of
+.NR (so
+[0]
+is added to the section title
+(but not to the body of the section).
+The font is then set
+to the paragraph font,
+so that more information may occur
+on the line
+with the section number
+and title.
+.b .sh
+insures that there is enough room
+to print the section head
+plus the beginning of a paragraph
+(about 3 lines total).
+If
+.i a
+through
+.i f
+are specified,
+the section number is set to that number
+rather than incremented automatically.
+If any of
+.i a
+through
+.i f
+are a hyphen
+that number is not reset.
+If
+.i T
+is a single underscore
+(\c
+.q _ )
+then the section depth and numbering is reset,
+but the base indent is not reset
+and nothing is printed out.
+This is useful to automatically
+coordinate section numbers with
+chapter numbers.
+.TL
+.b .sx
+.i +N
+.DE
+Go to section depth
+.i N
+[\c
+.b \-1 ],
+but do not print the number
+and title,
+and do not increment the section number
+at level
+.i N .
+This has the effect
+of starting a new paragraph
+at level
+.i N .
+.TL
+.b .uh
+.i T
+.DE
+Unnumbered section heading.
+The title
+.i T
+is printed
+with the same rules for spacing,
+font, etc.,
+as for
+.b .sh .
+.TL
+.b .$p
+.i T
+.i B
+.i N
+.DE
+Print section heading.
+May be redefined
+to get fancier headings.
+.i T
+is the title passed on the
+.b .sh
+or
+.b .uh
+line;
+.i B
+is the section number for this section,
+and
+.i N
+is the depth of this section.
+These parameters are not always present;
+in particular,
+.b .sh
+passes all three,
+.b .uh
+passes only the first,
+and
+.b .sx
+passes three,
+but the first two
+are null strings.
+Care should be taken if this macro
+is redefined;
+it is quite complex and subtle.
+.TL
+.b .$0
+.i T
+.i B
+.i N
+.DE
+This macro is called automatically
+after every call to
+.b .$p .
+It is normally undefined,
+but may be used
+to automatically put
+every section title
+into the table of contents
+or for some similar function.
+.i T
+is the section title
+for the section title which was just printed,
+.i B
+is the section number,
+and
+.i N
+is the section depth.
+.TL
+.b .$1
+\-
+.b .$6
+.DE
+Traps called just before printing that depth section.
+May be defined to
+(for example)
+give variable spacing
+before sections.
+These macros are called from
+.b .$p ,
+so if you redefine that macro
+you may lose this feature.
+.sh 1 "Headers and Footers"
+.ds TP \fI\(aal\|\(aam\^\(aar\^\(aa\fP
+.pp
+Headers and footers
+are put at the top and bottom
+of every page
+automatically.
+They are set in font
+.NR (tf
+[3]
+and size
+.NR (tp
+[10p].
+Each of the definitions
+apply as of the
+.i next
+page.
+Three-part titles
+must be quoted
+if there are two blanks adjacent
+anywhere in the title
+or more than eight blanks total.
+.pp
+The spacing
+of headers and footers
+are controlled by three number registers.
+.NR (hm
+[4v]
+is the distance from the top of the page
+to the top of the header,
+.NR (fm
+[3v]
+is the distance from the bottom of the page
+to the bottom of the footer,
+.NR (tm
+[7v]
+is the distance from the top of the page
+to the top of the text,
+and
+.NR (bm
+[6v]
+is the distance from the bottom of the page
+to the bottom of the text
+(nominal).
+The macros
+.b .m1 ,
+.b .m2 ,
+.b .m3 ,
+and
+.b .m4
+are also supplied for compatibility
+with
+\s-1ROFF\s0 documents.
+.TL
+.b .he
+\*(TP
+.DE
+Define three-part header,
+to be printed on the top
+of every page.
+.TL
+.b .fo
+\*(TP
+.DE
+Define footer,
+to be printed at the bottom
+of every page.
+.TL
+.b .eh
+\*(TP
+.DE
+Define header,
+to be printed at the top of every
+even-numbered page.
+.TL
+.b .oh
+\*(TP
+.DE
+Define header,
+to be printed at the top of every
+odd-numbered page.
+.TL
+.b .ef
+\*(TP
+.DE
+Define footer,
+to be printed at the bottom
+of every even-numbered page.
+.TL
+.b .of
+\*(TP
+.DE
+Define footer,
+to be printed at the bottom
+of every odd-numbered page.
+.TL
+.b .hx
+.DE
+Suppress headers and footers
+on the next page.
+.TL
+.b .m1
+.i +N
+.DE
+Set the space between the top of the page
+and the header
+[4v].
+.TL
+.b .m2
+.i +N
+.DE
+Set the space between the header
+and the first line of text
+[2v].
+.TL
+.b .m3
+.i +N
+.DE
+Set the space
+between the bottom of the text
+and the footer
+[2v].
+.TL
+.b .m4
+.i +N
+.DE
+Set the space
+between the footer
+and the bottom of the page
+[4v].
+.TL
+.b .ep
+.DE
+End this page,
+but do not begin the next page.
+Useful for forcing out footnotes,
+but other than
+that hardly every used.
+Must be followed by a
+.b .bp
+or the end of input.
+.TL
+.b .$h
+.DE
+Called at every page
+to print the header.
+May be redefined
+to provide fancy
+(e.g.,
+multi-line)
+headers,
+but doing so
+loses the function of the
+.b .he ,
+.b .fo ,
+.b .eh ,
+.b .oh ,
+.b .ef ,
+and
+.b .of
+requests,
+as well as the chapter-style title feature
+of
+.b .+c .
+.TL
+.b .$f
+.DE
+Print footer;
+same comments apply
+as in
+.b .$h .
+.TL
+.b .$H
+.DE
+A normally undefined macro
+which is called
+at the top of each page
+(after putting out
+the header,
+initial saved floating keeps,
+etc.);
+in other words,
+this macro is called immediately before
+printing text
+on a page.
+It can be used for column headings
+and the like.
+.sh 1 "Displays"
+.pp
+All displays except centered blocks
+and block quotes
+are preceded and followed
+by an extra
+.NR (bs
+[same as
+.NR (ps ]
+space.
+Quote spacing is stored in a separate register;
+centered blocks have no default initial or trailing space.
+The vertical spacing of all displays except quotes
+and centered blocks
+is stored in register
+.NR ($V
+instead of
+.NR ($v .
+.TL
+.b .(l
+.i m
+.i f
+.DE
+Begin list.
+Lists are single spaced,
+unfilled text.
+If
+.i f
+is
+.b F ,
+the list will be filled.
+If
+.i m
+[\c
+.b I ]
+is
+.b I
+the list is indented by
+.NR (bi
+[4m];
+if
+.b M
+the list is indented to the left margin;
+if
+.b L
+the list is left justified with respect to the text
+(different from
+.b M
+only if the base indent
+(stored in
+.NR ($i
+and set with
+.b .ba )
+is not zero);
+and if
+.b C
+the list is centered on a line-by-line basis.
+The list is set in font
+.NR (df
+[0].
+Must be matched by a
+.b .)l .
+This macro is almost like
+.b .(b
+except that no attempt is made
+to keep the display on one page.
+.TL
+.b .)l
+.DE
+End list.
+.TL
+.b .(q
+.DE
+Begin major quote.
+These are single spaced,
+filled,
+moved in from the text
+on both sides
+by
+.NR (qi
+[4n],
+preceded and followed
+by
+.NR (qs
+[same as
+.NR (bs ]
+space,
+and are set in point size
+.NR (qp
+[one point smaller than surrounding text].
+.TL
+.b .)q
+.DE
+End major quote.
+.TL
+.b .(b
+.i m
+.i f
+.DE
+Begin block.
+Blocks are a form of
+.i keep ,
+where the text of a keep
+is kept together on one page
+if possible
+(keeps are useful
+for tables and figures
+which should not be broken
+over a page).
+If the block will not fit
+on the current page
+a new page is begun,
+.i unless
+that would leave more than
+.NR (bt
+[0]
+white space
+at the bottom of the text.
+If
+.NR (bt
+is zero, the threshold feature
+is turned off.
+Blocks are not filled
+unless
+.i f
+is
+.b F ,
+when they are filled.
+The block will be left-justified
+if
+.i m
+is
+.b L ,
+indented by
+.NR (bi
+[4m]
+if
+.i m
+is
+.b I
+or absent,
+centered
+(line-for-line)
+if
+.i m
+is
+.b C ,
+and left justified to the margin
+(not to the base indent)
+if
+.i m
+is
+.b M .
+The block is set in font
+.NR (df
+[0].
+.TL
+.b .)b
+.DE
+End block.
+.TL
+.b .(z
+.i m
+.i f
+.DE
+Begin floating keep.
+Like
+.b .(b
+except that the keep is
+.i floated
+to the bottom of the page
+or the top of the next page.
+Therefore,
+its position relative to the text changes.
+The floating keep is preceded and followed
+by
+.NR (zs
+[1v]
+space.
+Also,
+it defaults to mode
+.b M .
+.TL
+.b .)z
+.DE
+End floating keep.
+.TL
+.b .(c
+.DE
+Begin centered block.
+The next keep
+is centered as a block,
+rather than on a line-by-line basis
+as with
+.b ".(b C" .
+This call may be nested
+inside keeps.
+.TL
+.b .)c
+.DE
+End centered block.
+.sh 1 Annotations
+.TL
+.b .(d
+.DE
+Begin delayed text.
+Everything in the next keep
+is saved for output
+later with
+.b .pd ,
+in a manner
+similar to footnotes.
+.TL
+.b .)d
+.i n
+.DE
+End delayed text.
+The delayed text number register
+.NR ($d
+and the associated string
+.ST #
+are incremented if
+.ST #
+has been referenced.
+.TL
+.b .pd
+.DE
+Print delayed text.
+Everything diverted via
+.b .(d
+is printed and truncated.
+This might be used
+at the end of each chapter.
+.TL
+.b .(f
+.DE
+Begin footnote.
+The text of the footnote
+is floated to the bottom
+of the page
+and set in font
+.NR (ff
+[1]
+and size
+.NR (fp
+[8p].
+Each entry
+is preceded by
+.NR (fs
+[0.2v]
+space,
+is indented
+.NR (fi
+[3n]
+on the first line,
+and is indented
+.NR (fu
+[0]
+from the right margin.
+Footnotes line up underneath
+two column output.
+If the text of the footnote
+will not all fit on one page
+it will be carried over
+to the next page.
+.TL
+.b .)f
+.i n
+.DE
+End footnote.
+The number register
+.NR ($f
+and the associated string
+.ST *
+are incremented
+if they have been referenced.
+.TL
+.b .$s
+.DE
+The macro to output the footnote separator.
+This macro may be redefined
+to give other size lines or other types
+of separators.
+Currently
+it draws a 1.5i line.
+.TL
+.b .(x
+.i x
+.DE
+Begin index entry.
+Index entries are saved in the index
+.i x
+[\c
+.b x ]
+until called up with
+.b .xp.
+Each entry is preceded
+by a
+.NR (xs
+[0.2v]
+space.
+Each entry is
+.q undented
+by
+.NR (xu
+[0.5i];
+this register tells how far the page number
+extends into the right margin.
+.TL
+.b .)x
+.i P
+.i A
+.DE
+End index entry.
+The index entry
+is finished with a row of dots
+with
+.i A
+[null]
+right justified on the last line
+(such as for an author's name),
+followed by P
+[\c
+.NR % ].
+If
+.i A
+is specified,
+.i P
+must be specified;
+.NR %
+can be used to print the current page number.
+If
+.i P
+is an underscore,
+no page number
+and no row of dots
+are printed.
+.TL
+.b .xp
+.i x
+.DE
+Print index
+.i x
+[\c
+.b x ].
+The index is formatted in the font, size, and so forth
+in effect at the time it is printed,
+rather than at the time it is collected.
+.sh 1 "Columned Output"
+.TL
+.b .2c
+.i +S
+.i N
+.DE
+Enter two-column mode.
+The column separation is set to
+.i +S
+[4n, 0.5i in ACM mode]
+(saved in
+.NR ($s ).
+The column width,
+calculated to fill the single column line length
+with both columns,
+is stored in
+.NR ($l .
+The current column
+is in
+.NR ($c .
+You can test register
+.NR ($m
+[1]
+to see if you are in single column
+or double column mode.
+Actually,
+the request enters
+.i N
+[2]
+column output.
+.TL
+.b .1c
+.DE
+Revert to single-column mode.
+.TL
+.b .bc
+.DE
+Begin column.
+This is like
+.b .bp
+except that it begins a new column
+on a new page
+only if necessary,
+rather than forcing a whole new page
+if there is another column left
+on the current page.
+.sh 1 "Fonts and Sizes"
+.TL
+.b .sz
+.i +P
+.DE
+The pointsize is set to
+.i P
+[10p],
+and the line spacing is set proportionally.
+The line spacing as a percentage of the pointsize expressed in units
+is stored in
+.NR ($v .
+The percentage used internally
+by displays and annotations
+is stored in
+.NR ($V
+(although this is not used by
+.b .sz ).
+This size is
+.i not
+sticky beyond many macros:
+in particular,
+.NR (pp
+(paragraph pointsize)
+modifies the pointsize every time a new paragraph is begun
+using the
+.b \&.pp ,
+.b \&.lp ,
+.b \&.ip ,
+.b \&.np ,
+or
+.b \&.bu
+macros.
+Also,
+.NR (fp
+(footnote pointsize),
+.NR (qp
+(quote pointsize),
+.NR (sp
+(section header pointsize),
+and
+.NR (tp
+(title pointsize)
+may modify the pointsize.
+.TL
+.b .r
+.i W
+.i X
+.DE
+Set
+.i W
+in roman font,
+appending
+.i X
+in the previous font.
+To append different font requests,
+use
+.i X
+=
+.b \ec .
+If no parameters,
+change to roman font.
+.TL
+.b .i
+.i W
+.i X
+.DE
+Set
+.i W
+in italics,
+appending
+.i X
+in the previous font.
+If no parameters,
+change to italic font.
+.TL
+.b .b
+.i W
+.i X
+.DE
+Set
+.i W
+in bold font
+and append
+.i X
+in the previous font.
+If no parameters,
+switch to bold font.
+.TL
+.b .u
+.i W
+.i X
+.DE
+Underline
+.i W
+and append
+.i X .
+This is a true underlining,
+as opposed to the
+.b .ul
+request,
+which changes to
+.q "underline font"
+(usually italics in \*G).
+It won't work right
+if
+.i W
+is spread or broken (including hyphenated).
+In other words,
+it is safe in nofill mode only.
+.TL
+.b .q
+.i W
+.i X
+.DE
+Quote
+.i W
+and append
+.i X .
+In \*G
+this surrounds
+.i W
+with
+.b \*(lq ,
+and
+.b \*(rq .
+.TL
+.b .bi
+.i W
+.i X
+.DE
+Set
+.i W
+in bold italics
+and append
+.i X .
+.TL
+.b .bx
+.i W
+.i X
+.DE
+Sets
+.i W
+in a box,
+with
+.i X
+appended.
+It won't work right
+if
+.i W
+is spread or broken (including hyphenated).
+In other words,
+it is safe in nofill mode only.
+.TL
+.b sm
+.i W
+.i X
+.DE
+Sets
+.i W
+in a smaller pointsize,
+with
+.i X
+appended.
+.sh 1 "Roff Support"
+.TL
+.b .ix
+.i +N
+.DE
+Indent,
+no break.
+Equivalent to
+.b \(aain
+.i N .
+.TL
+.b .bl
+.i N
+.DE
+Leave
+.i N
+contiguous white space,
+on the next page if not enough room
+on this page.
+Equivalent to a
+.b .sp
+.i N
+inside a block.
+.TL
+.b .pa
+.i +N
+.DE
+Equivalent to
+.b .bp .
+.TL
+.b .ro
+.DE
+Set page number
+in roman numerals.
+Equivalent to
+.b ".af % i" .
+.TL
+.b .ar
+.DE
+Set page number in Arabic.
+Equivalent to
+.b ".af % 1" .
+.TL
+.b .n1
+.DE
+Number lines in margin from one
+on each page.
+.TL
+.b .n2
+.i N
+.DE
+Number lines from
+.i N ,
+stop if
+.i N
+= 0.
+.TL
+.b .sk
+.DE
+Leave the next output page blank,
+except for headers and footers.
+This is used to leave space
+for a full-page diagram
+which is produced externally
+and pasted in later.
+To get a partial-page paste-in display,
+say
+.b .sv \ \c
+.i N ,
+where
+.i N
+is the amount of space
+to leave;
+this space will be output immediately
+if there is room,
+and will otherwise be output
+at the top of the next page.
+However, be warned:
+if
+.i N
+is greater than the amount of available space
+on an empty page,
+no space will ever be output.
+.sh 1 "Preprocessor Support"
+.TL
+.b .EQ
+.i m
+.i T
+.DE
+Begin equation.
+The equation is centered
+if
+.i m
+is
+.b C
+or omitted,
+indented
+.NR (bi
+[4m]
+if
+.i m
+is
+.b I ,
+and left justified if
+.i m
+is
+.b L .
+.i T
+is a title printed on the right margin
+next to the equation.
+See
+.i "Typesetting Mathematics \- User's Guide"
+by Brian W. Kernighan
+and Lorinda L. Cherry.
+.TL
+.b .EN
+.i c
+.DE
+End equation.
+If
+.i c
+is
+.b C
+the equation must be continued
+by immediately following
+with another
+.b .EQ ,
+the text of which
+can be centered
+along with this one.
+Otherwise,
+the equation is printed,
+always on one page,
+with
+.NR (es
+[0.5v]
+space
+above and below it.
+.TL
+.b .TS
+.i h
+.DE
+Table start.
+Tables are single spaced
+and kept on one page
+if possible.
+If you have a large table
+which will not fit on one page,
+use
+.i h
+=
+.b H
+and follow the header part
+(to be printed on every page of the table)
+with a
+.b .TH .
+See
+.i "Tbl \- A Program to Format Tables"
+by M. E. Lesk.
+.TL
+.b .TH
+.DE
+With
+.b ".TS H" ,
+ends the header portion of the table.
+.TL
+.b .TE
+.DE
+Table end.
+Note that this table
+does not float,
+in fact,
+it is not even guaranteed to stay on one page
+if you use requests such as
+.b .sp
+intermixed with the text
+of the table.
+If you want it to float
+(or if you use requests
+inside the table),
+surround the entire table
+(including the
+.b .TS
+and
+.b .TE
+requests)
+with the requests
+.b .(z
+and
+.b .)z .
+.TL
+.b .PS
+.i h
+.i w
+.DE
+Begin
+.i pic
+picture.
+.i H
+is the height and
+.i w
+is the width,
+both in basic units.
+.TL
+.b .PE
+.DE
+End picture.
+.TL
+.b .IS
+.DE
+Begin
+.i ideal
+picture.
+.TL
+.b .IE
+.DE
+End
+.i ideal
+picture.
+.TL
+.b .IF
+.DE
+End
+.i ideal
+picture (alternate form).
+.TL
+.b .GS
+.DE
+Begin
+.i gremlin
+picture.
+.TL
+.b .GE
+.DE
+End
+.i gremlin
+picture.
+.TL
+.b .GF
+.DE
+End
+.i gremlin
+picture (alternate form).
+.sh 1 "Miscellaneous"
+.TL
+.b .re
+.DE
+Reset tabs every 0.5i.
+.TL
+.b .ba
+.i +N
+.DE
+Set the base indent
+to
+.i +N
+[0]
+(saved in
+.NR ($i ).
+All paragraphs,
+sections,
+and displays
+come out indented by this amount.
+Titles and footnotes
+are unaffected.
+The
+.b .sh
+request performs a
+.b .ba
+request
+if
+.NR (si
+[0] is not zero,
+and sets the base indent to
+.NR (si \c
+.b * \c
+.NR ($0 .
+.TL
+.b .xl
+.i +N
+.DE
+Set the line length to
+.i N
+[6.0i].
+This differs
+from
+.b .ll
+because it only affects the current environment.
+.TL
+.b .ll
+.i +N
+.DE
+Set line length in all environments
+to
+.i N
+[6.0i].
+This should not be used
+after output has begun,
+and particularly not in two-column output.
+The current line length is stored in
+.NR ($l .
+.TL
+.b .hl
+.DE
+Draws a horizontal line
+the length of the page.
+This is useful
+inside floating keeps
+to differentiate
+between the text
+and the figure.
+.sh 1 "Standard Papers"
+.TL
+.b .tp
+.DE
+Begin title page.
+Spacing at the top of the page
+can occur,
+and headers and footers are suppressed.
+Also,
+the page number
+is not incremented
+for this page.
+.TL
+.b .++
+.i m
+.i H
+.DE
+This request defines the section of the paper
+which we are entering.
+The section type is defined by
+.i m .
+.b C
+means that we are entering the chapter portion
+of the paper,
+.b A
+means that we are entering the appendix portion
+of the paper,
+.b P
+means that the material following
+should be the preliminary portion
+(abstract, table of contents, etc.)
+portion of the paper,
+.b AB
+means that we are entering the abstract
+(numbered independently from 1
+in Arabic numerals),
+and
+.b B
+means that we are entering the bibliographic
+portion at the end of the paper.
+Also, the variants
+.b RC
+and
+.b RA
+are allowed,
+which specify renumbering of pages
+from one at the beginning of each
+chapter or appendix,
+respectively.
+The
+.i H
+parameter defines the new header.
+If there are any spaces in it,
+the entire header must be quoted.
+If you want the header to have the chapter number
+in it,
+Use the string
+.b "\e\e\e\en(ch" .
+For example, to number appendixes
+.b A.1
+etc.,
+type
+.b ".++ RA \(aa\(aa\(aa\e\e\e\en(ch.%\(aa" .
+Each section
+(chapter, appendix, etc.)
+should be preceded by the
+.b .+c
+request.
+It should be mentioned
+that it is easier when using
+\*T to put the front material
+at the end of the paper,
+so that the table of contents
+can be collected and put out;
+this material can then be physically
+moved to the beginning of the paper.
+.TL
+.b .+c
+.i T
+.DE
+Begin chapter with title
+.i T .
+The chapter number
+is maintained in
+.NR (ch .
+This register is incremented
+every time
+.b .+c
+is called with a parameter.
+The title and chapter number
+are printed by
+.b .$c .
+The header is moved to the footer
+on the first page
+of each chapter.
+If
+.i T
+is omitted,
+.b .$c
+is not called;
+this is useful for doing your own
+.q "title page"
+at the beginning of papers
+without a title page proper.
+.b .$c
+calls
+.b .$C
+as a hook so that chapter titles can be inserted
+into a table of contents automatically.
+The footnote numbering is reset to one.
+.TL
+.b .$c
+.i T
+.DE
+Print chapter number
+(from
+.NR (ch )
+and
+.i T .
+This macro can be redefined to your liking.
+It is defined by default
+to be acceptable
+for a PhD thesis
+at Berkeley.
+This macro calls
+.b $C ,
+which can be defined to make index entries,
+or whatever.
+.TL
+.b .$C
+.i K
+.i N
+.i T
+.DE
+This macro is called by
+.b .$c .
+It is normally undefined,
+but can be used to automatically insert
+index entries,
+or whatever.
+.i K
+is a keyword,
+either
+.q Chapter
+or
+.q Appendix
+(depending on the
+.b .++
+mode);
+.i N
+is the chapter or appendix number,
+and
+.i T
+is the chapter or appendix title.
+.sh 1 "Predefined Strings"
+.TL
+.ST *
+.DE
+Footnote number, actually
+.ST [ \c
+.NR ($f \c
+.ST ] .
+This macro is incremented
+after each call to
+.b .)f .
+.TL
+.ST #
+.DE
+Delayed text number.
+Actually
+[\c
+.NR ($d ].
+.TL
+.ST {
+.DE
+Superscript.
+This string gives upward movement
+and a change to a smaller point size.
+Extra space is left above the line
+to allow room for the superscript.
+.TL
+.ST }
+.DE
+Unsuperscript.
+Inverse to
+.ST { .
+For example,
+to produce a superscript
+you might type
+.b x \c
+.ST { \c
+.b 2 \c
+.ST } ,
+which will produce
+.b x\*{2\*} .
+.TL
+.ST <
+.DE
+Subscript.
+Extra space is left below the line
+to allow for the subscript.
+.TL
+.ST >
+.DE
+Inverse to
+.ST < .
+.TL
+.ST (dw
+.DE
+The day of the week,
+as a word.
+.TL
+.ST (mo
+.DE
+The month,
+as a word.
+.TL
+.ST (td
+.DE
+Today's date,
+directly printable.
+The date is of the form \*(td.
+Other forms of the date can be used
+by using
+.NR (dy
+(the day of the month;
+for example, \n(dy),
+.ST (mo
+(as noted above)
+or
+.NR (mo
+(the same,
+but as an ordinal number;
+for example, \*(mo is \n(mo),
+and
+.NR (yr
+(the last two digits of the current year).
+.TL
+.ST (lq
+.DE
+Left quote marks.
+.TL
+.ST (rq
+.DE
+Right quote.
+.TL
+.ST \-
+.DE
+.ie \w'\(34'>0 \(34
+.el 3/4
+em dash.
+.sh 1 "Special Characters and Marks"
+.pp
+There are a number of special characters
+and diacritical marks
+(such as accents)
+available through \-me.
+.ta 15 +5 +6
+.nf
+Name Usage Example
+Acute accent \e*\(aa a\e*\(aa a\*'
+Grave accent \e*\(ga e\e*\(ga e\*`
+Umlaut \e*: u\e*: u\*:
+Tilde \e*~ n\e*~ n\*~
+Caret \e*^ e\e*^ e\*^
+Cedilla \e*, c\e*, c\*,
+Czech \e*v e\e*v e\*v
+Circle \e*o A\e*o A\*o
+There exists \e*(qe \*(qe
+For all \e*(qa \*(qa
+.fi
+.sp 1i
+.b Acknowledgments
+.pp
+I would like to thank
+Bob Epstein,
+Bill Joy,
+and Larry Rowe
+for having the courage
+to use the \-me macros
+to produce non-trivial papers
+during the development stages;
+Ricki Blau,
+Pamela Humphrey,
+and Jim Joyce
+for their help with the documentation phase;
+peter kessler
+for numerous complaints,
+most accompanied by fixes;
+and the plethora of people who have contributed ideas
+and have given support for the project.
+.bp
+.b Summary
+.pp
+This alphabetical list summarizes all macros, strings, and number registers
+available in the \-me macros.
+Selected
+.i troff
+commands, registers, and functions are included as well;
+those listed can generally be used with impunity.
+.pp
+The columns are the name of the
+command, macro, register, or string;
+the type of the object,
+and the description.
+Types are
+.b M
+for macro or builtin command
+(invoked with
+.b \&.
+or
+.b \&\'
+in the first input column),
+.b S
+for a string
+(invoked with
+.b \e*
+or
+.b \e*( ),
+.b R
+for a number register
+(invoked with
+.b \en
+or
+.b \en( ),
+and
+.b F
+for a
+.i troff
+builtin function
+(invoked by preceding it with a single backslash).
+.pp
+Lines marked with \(sc are
+.i troff
+internal codes.
+Lines marked with \(dg or \(dd
+may be defined by the user to get special functions;
+\(dd indicates that these are defined by default
+and changing them may have unexpected side effects.
+Lines marked with \(de
+are specific to
+.i ditroff
+(device-independent
+.i troff ).
+.de $H
+.ev 1
+.ta \w'\e(space)\(sc\ 'u +\w'TYPE 'u
+NAME TYPE DESCRIPTION
+.ev
+..
+.(l
+.$H
+\e(space) F\(sc unpaddable space
+\e" F\(sc comment (to end of line)
+\e*# S optional delayed text tag string
+\e$\fI\&N\fP F\(sc interpolate argument \fI\&N\fP
+\en($0 R section depth
+\&.$0 M\(dg invoked after section title printed
+\en($1 R first section number
+\&.$1 M\(dg invoked before printing depth 1 section
+\en($2 R second section number
+\&.$2 M\(dg invoked before printing depth 2 section
+\en($3 R third section number
+\&.$3 M\(dg invoked before printing depth 3 section
+\en($4 R fourth section number
+\&.$4 M\(dg invoked before printing depth 4 section
+\en($5 R fifth section number
+\&.$5 M\(dg invoked before printing depth 5 section
+\en($6 R sixth section number
+\&.$6 M\(dg invoked before printing depth 6 section
+\&.$C M\(dg called at beginning of chapter
+\&.$H M\(dg text header
+\en($V R\(dd relative vertical spacing in displays
+\en($c R current column number
+\&.$c M\(dd print chapter title
+\en($d R delayed text number
+\en($f R footnote number
+\&.$f M\(dd print footer
+\&.$h M\(dd print header
+\en($i R paragraph base indent
+\en($l R column width
+\en($m R number of columns in effect
+\e*($n S section name
+\en($p R numbered paragraph number
+\&.$p M\(dd print section heading (internal macro)
+\en($s R column indent
+\&.$s M\(dd footnote separator (from text)
+\en($v R\(dd relative vertical spacing in text
+\en% R\(sc current page number
+\e& F\(sc zero width character, useful for hiding controls
+\e(\fI\&xx\fP F\(sc interpolate special character \fI\&xx\fP
+\&.(b M begin block
+\&.(c M begin centered block
+\&.(d M begin delayed text
+\&.(f M begin footnote
+\&.(l M begin list
+\&.(q M begin quote
+\&.(x M begin index entry
+\&.(z M begin floating keep
+\&.)b M end block
+\&.)c M end centered block
+\&.)d M end delayed text
+\&.)f M end footnote
+\&.)l M end list
+\&.)q M end quote
+\&.)x M end index entry
+\&.)z M end floating keep
+\e*\fI\&x\fP F\(sc interpolate string \fI\&x\fP
+\e*(\fI\&xx\fP F\(sc interpolate string \fI\&xx\fP
+\e** S optional footnote tag string
+\&.++ M set paper section type
+\&.+c M begin chapter
+\e*, S cedilla
+\e\- F\(sc minus sign
+\e*\- S 3/4 em dash
+\e0 F\(sc unpaddable digit-width space
+\&.1c M revert to single column output
+\&.2c M begin two column output
+\e*: S umlat
+\e*< S begin subscript
+\e*> S end subscript
+\&.EN M end equation
+\&.EQ M begin equation
+\eL\'\fI\&d\fP\' F\(sc vertical line drawing function for distance \fI\&d\fP
+\&.GE M\(de end \fIgremlin\fP picture
+\&.GF M\(de end \fIgremlin\fP picture (with flyback)
+\&.GS M\(de start \fIgremlin\fP picture
+\&.IE M\(de end \fIideal\fP picture
+\&.IF M\(de end \fIideal\fP picture (with flyback)
+\&.IS M\(de start \fIideal\fP picture
+\&.PE M\(de end \fIpic\fP picture
+\&.PF M\(de end \fIpic\fP picture (with flyback)
+\&.PS M\(de start \fIpic\fP picture
+\&.TE M end table
+\&.TH M end header of table
+\&.TS M begin table
+\e*{ S begin superscript
+\en(\&.$ R\(sc number of arguments to macro
+\en(\&.i R\(sc current indent
+\en(\&.l R\(sc current line length
+\en(\&.s R\(sc current point size
+\e*(\&\' S acute accent
+\e*(\&\` S grave accent
+\e(\' F\(sc acute accent
+\e(\` F\(sc grave accent
+\e*} S end superscript
+\e^ F\(sc 1/12 em narrow space
+\e*^ S caret
+\&.ad M\(sc set text adjustment
+\&.af M\(sc assign format to register
+\&.am M\(sc append to macro
+\&.ar M set page numbers in Arabic
+\&.as M\(sc append to string
+\&.b M bold font
+\&.ba M set base indent
+\&.bc M begin new column
+\&.bi M bold italic
+\en(bi R display (block) indent
+\&.bl M blank lines (even at top of page)
+\en(bm R bottom title margin
+\&.bp M\(sc begin page
+\&.br M\(sc break (start new line)
+\en(bs R display (block) pre/post spacing
+\en(bt R block keep threshold
+\&.bx M boxed
+\ec F\(sc continue input
+\&.ce M\(sc center lines
+\en(ch R current chapter number
+\&.de M\(sc define macro
+\en(df R display font
+\&.ds M\(sc define string
+\en(dw R\(sc current day of week
+\e*(dw S current day of week
+\en(dy R\(sc day of month
+\ee F\(sc printable version of \e
+\&.ef M set footer (even numbered pages only)
+\&.eh M set header (even numbered pages only)
+\&.el M\(sc else part of conditional
+\&.ep M end page
+\en(es R equation pre/post space
+\ef\fI\&f\fP F\(sc inline font change to font \fI\&f\fP
+\ef(\fI\&ff\fP F\(sc inline font change to font \fI\&ff\fP
+\&.fc M\(sc set field characters
+\en(ff R footnote font
+\&.fi M\(sc fill output lines
+\en(fi R footnote indent (first line only)
+\en(fm R footer margin
+\&.fo M set footer
+\en(fp R footnote pointsize
+\en(fs R footnote prespace
+\en(fu R footnote undent (from right margin)
+\eh\'\fI\&d\fP\' F\(sc local horizontal motion for distance \fI\&d\fP
+\&.hc M\(sc set hyphenation character
+\&.he M set header
+\&.hl M draw horizontal line
+\en(hm R header margin
+\&.hx M suppress headers and footers on next page
+\&.hy M\(sc set hyphenation mode
+\&.i M italic font
+\&.ie M\(sc conditional with else
+\&.if M\(sc conditional
+\en(ii R indented paragraph indent
+\&.in M\(sc indent (transient, use .ba for pervasive)
+\&.ip M begin indented paragraph
+\&.ix M indent, no break
+\el\'\fI\&d\fP\' F\(sc horizontal line drawing function for distance \fI\&d\fP
+\&.lc M\(sc set leader repetition character
+\&.ll M set line length
+\&.lp M begin left justified paragraph
+\e*(lq S left quote marks
+\&.ls M\(sc set multi-line spacing
+\&.m1 M set space from top of page to header
+\&.m2 M set space from header to text
+\&.m3 M set space from text to footer
+\&.m4 M set space from footer to bottom of page
+\&.mc M\(sc insert margin character
+\&.mk M\(sc mark vertical position
+\en(mo R\(sc month of year
+\e*(mo S current month
+\en\fI\&x\fP F\(sc interpolate number register \fI\&x\fP
+\en(\fI\&xx\fP F\(sc interpolate number register \fI\&xx\fP
+\&.n1 M number lines in margin
+\&.n2 M number lines in margin
+\&.na M\(sc turn off text adjustment
+\&.ne M\(sc need vertical space
+\&.nf M\(sc don't fill output lines
+\&.nh M\(sc turn off hyphenation
+\&.np M begin numbered paragraph
+\&.nr M\(sc set number register
+\&.ns M\(sc no space mode
+\e*o S circle (e.g., for Norse A\*o)
+\&.of M set footer (odd numbered pages only)
+\&.oh M set header (odd numbered pages only)
+\&.pa M begin page
+\&.pd M print delayed text
+\en(pf R paragraph font
+\en(pi R paragraph indent
+\&.pl M\(sc set page length
+\&.pn M\(sc set next page number
+\&.po M\(sc page offset
+\en(po R simulated page offset
+\&.pp M begin paragraph
+\en(pp R paragraph pointsize
+\en(ps R paragraph prespace
+\&.q M quoted
+\e*(qa S for all
+\e*(qe S there exists
+\en(qi R quote indent (also shortens line)
+\en(qp R quote pointsize
+\en(qs R quote pre/post space
+\&.r M roman font
+\&.rb M real bold font
+\&.re M reset tabs
+\&.rm M\(sc remove macro or string
+\&.rn M\(sc rename macro or string
+\&.ro M set page numbers in roman
+\e*(rq S right quote marks
+\&.rr M\(sc remove register
+\&.rs M\(sc restore spacing
+\&.rt M\(sc return to vertical position
+\es\fI\&S\fP F\(sc inline size change to size \fI\&S\fP
+\en(sf R section title font
+\&.sh M begin numbered section
+\en(si R relative base indent per section depth
+\&.sk M skip next page
+\&.sm M set argument in a smaller pointsize
+\&.so M\(sc source input file
+\en(so R additional section title offset
+\&.sp M\(sc vertical space
+\en(sp R section title pointsize
+\en(ss R section prespace
+\&.sx M change section depth
+\&.sz M set pointsize and vertical spacing
+\&.ta M\(sc set tab stops
+\&.tc M\(sc set tab repetition character
+\e*(td S today's date
+\en(tf R title font
+\&.ti M\(sc temporary indent (next line only)
+\&.tl M\(sc three part title
+\en(tm R top title margin
+\&.tp M begin title page
+\en(tp R title pointsize
+\&.tr M\(sc translate
+\&.u M underlined
+\&.uh M unnumbered section
+\&.ul M\(sc underline next line
+\ev\'\fI\&d\fP\' F\(sc local vertical motion for distance \fI\&d\fP
+\e*v S inverted `v' for czeck ``e\*v''
+\ew\'\fI\&S\fP\' F\(sc return width of string \fI\&S\fP
+\&.xl M set line length (local)
+\&.xp M print index
+\en(xs R index entry prespace
+\en(xu R index undent (from right margin)
+\en(yr R\(sc year (last two digits only)
+\en(zs R floating keep pre/post space
+\e{ F\(sc begin conditional group
+\e| F\(sc 1/6 em narrow space
+\e} F\(sc end conditional group
+\e*~ S tilde
+.)l
+.rm $H
diff --git a/gnu/usr.bin/groff/eqn/Makefile b/gnu/usr.bin/groff/eqn/Makefile
new file mode 100644
index 000000000000..d3823ab34392
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/Makefile
@@ -0,0 +1,26 @@
+# Makefile for eqn
+
+PROG= eqn
+SRCS= 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
+OBJS= eqn.o
+CFLAGS+= -I. -I$(.CURDIR)/../include
+CXXFLAGS+= -I. -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF)
+DPADD+= $(LIBGROFF)
+
+CLEANFILES+= eqn.cc eqn.tab.h
+
+# XXX g=$(DESTDIR)$(BINDIR) quoted suitably for sed
+g=\/usr\/bin\/
+
+afterinstall:
+ sed -e 's/@g@/$(g)/g' $(.CURDIR)/neqn.sh > $(DESTDIR)$(BINDIR)/neqn
+ chown ${BINOWN}.${BINGRP} $(DESTDIR)$(BINDIR)/neqn
+ chmod ${BINMODE} $(DESTDIR)$(BINDIR)/neqn
+
+beforedepend: eqn.cc
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/eqn/TODO b/gnu/usr.bin/groff/eqn/TODO
new file mode 100644
index 000000000000..89b158e8a4c7
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/TODO
@@ -0,0 +1,41 @@
+Use the same size increases for sum prod int as eqn does.
+
+Perhaps chartype should be renamed.
+
+TeX makes {sub,super}script on a single character with an accent
+into an accent onto the (character with the script). Should we do this?
+
+Implement mark and lineups within scripts, matrices and piles, and accents.
+(Why would this be useful?)
+
+Perhaps push hmotions down through lists to avoid upsetting spacing
+adjustments.
+
+Possibly generate .lf commands during compute_metrics phase.
+
+Consider whether there shuld be extra space at the side of piles.
+
+Provide scriptstyle displaystyle etc.
+
+Provide a nicer matrix syntax, eg
+matrix ccc {
+a then b then c above
+e then f then g above
+h then i then k
+}
+
+Perhaps generate syntax error messages using the style of gpic.
+
+Wide accents.
+
+More use of \Z.
+
+Extensible square roots.
+
+Vphantom
+
+Smash.
+
+Provide a variant of vec that extends over the length of the accentee.
+
+Support vertical arrow delimiters.
diff --git a/gnu/usr.bin/groff/eqn/box.cc b/gnu/usr.bin/groff/eqn/box.cc
new file mode 100644
index 000000000000..08dbe07978ce
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/box.cc
@@ -0,0 +1,611 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+const char *current_roman_font;
+
+char *gfont = 0;
+char *grfont = 0;
+char *gbfont = 0;
+int gsize = 0;
+
+int script_size_reduction = -1; // negative means reduce by a percentage
+
+int positive_space = -1;
+int negative_space = -1;
+
+int minimum_size = 5;
+
+int fat_offset = 4;
+int body_height = 85;
+int body_depth = 35;
+
+int over_hang = 0;
+int accent_width = 31;
+int delimiter_factor = 900;
+int delimiter_shortfall = 50;
+
+int null_delimiter_space = 12;
+int script_space = 5;
+int thin_space = 17;
+int medium_space = 22;
+int thick_space = 28;
+
+int num1 = 70;
+int num2 = 40;
+// we don't use num3, because we don't have \atop
+int denom1 = 70;
+int denom2 = 36;
+int axis_height = 26; // in 100ths of an em
+int sup1 = 42;
+int sup2 = 37;
+int sup3 = 28;
+int default_rule_thickness = 4;
+int sub1 = 20;
+int sub2 = 23;
+int sup_drop = 38;
+int sub_drop = 5;
+int x_height = 45;
+int big_op_spacing1 = 11;
+int big_op_spacing2 = 17;
+int big_op_spacing3 = 20;
+int big_op_spacing4 = 60;
+int big_op_spacing5 = 10;
+
+// These are for piles and matrices.
+
+int baseline_sep = 140; // = num1 + denom1
+int shift_down = 26; // = axis_height
+int column_sep = 100; // = em space
+int matrix_side_sep = 17; // = thin space
+
+int nroff = 0; // should we grok ndefine or tdefine?
+
+struct {
+ const char *name;
+ int *ptr;
+} param_table[] = {
+"fat_offset", &fat_offset,
+"over_hang", &over_hang,
+"accent_width", &accent_width,
+"delimiter_factor", &delimiter_factor,
+"delimiter_shortfall", &delimiter_shortfall,
+"null_delimiter_space", &null_delimiter_space,
+"script_space", &script_space,
+"thin_space", &thin_space,
+"medium_space", &medium_space,
+"thick_space", &thick_space,
+"num1", &num1,
+"num2", &num2,
+"denom1", &denom1,
+"denom2", &denom2,
+"axis_height", &axis_height,
+"sup1", &sup1,
+"sup2", &sup2,
+"sup3", &sup3,
+"default_rule_thickness", &default_rule_thickness,
+"sub1", &sub1,
+"sub2", &sub2,
+"sup_drop", &sup_drop,
+"sub_drop", &sub_drop,
+"x_height", &x_height,
+"big_op_spacing1", &big_op_spacing1,
+"big_op_spacing2", &big_op_spacing2,
+"big_op_spacing3", &big_op_spacing3,
+"big_op_spacing4", &big_op_spacing4,
+"big_op_spacing5", &big_op_spacing5,
+"minimum_size", &minimum_size,
+"baseline_sep", &baseline_sep,
+"shift_down", &shift_down,
+"column_sep", &column_sep,
+"matrix_side_sep", &matrix_side_sep,
+"draw_lines", &draw_flag,
+"body_height", &body_height,
+"body_depth", &body_depth,
+"nroff", &nroff,
+0, 0
+};
+
+void set_param(const char *name, int value)
+{
+ for (int i = 0; param_table[i].name != 0; i++)
+ if (strcmp(param_table[i].name, name) == 0) {
+ *param_table[i].ptr = value;
+ return;
+ }
+ error("unrecognised parameter `%1'", name);
+}
+
+int script_style(int style)
+{
+ return style > SCRIPT_STYLE ? style - 2 : style;
+}
+
+int cramped_style(int style)
+{
+ return (style & 1) ? style - 1 : style;
+}
+
+void set_space(int n)
+{
+ if (n < 0)
+ negative_space = -n;
+ else
+ positive_space = n;
+}
+
+// Return 0 if the specified size is bad.
+// The caller is responsible for giving the error message.
+
+int set_gsize(const char *s)
+{
+ const char *p = (*s == '+' || *s == '-') ? s + 1 : s;
+ char *end;
+ long n = strtol(p, &end, 10);
+ if (n <= 0 || *end != '\0' || n > INT_MAX)
+ return 0;
+ if (p > s) {
+ if (!gsize)
+ gsize = 10;
+ if (*s == '+') {
+ if (gsize > INT_MAX - n)
+ return 0;
+ gsize += int(n);
+ }
+ else {
+ if (gsize - n <= 0)
+ return 0;
+ gsize -= int(n);
+ }
+ }
+ else
+ gsize = int(n);
+ return 1;
+}
+
+void set_script_reduction(int n)
+{
+ script_size_reduction = n;
+}
+
+const char *get_gfont()
+{
+ return gfont ? gfont : "I";
+}
+
+const char *get_grfont()
+{
+ return grfont ? grfont : "R";
+}
+
+const char *get_gbfont()
+{
+ return gbfont ? gbfont : "B";
+}
+
+void set_gfont(const char *s)
+{
+ a_delete gfont;
+ gfont = strsave(s);
+}
+
+void set_grfont(const char *s)
+{
+ a_delete grfont;
+ grfont = strsave(s);
+}
+
+void set_gbfont(const char *s)
+{
+ a_delete gbfont;
+ gbfont = strsave(s);
+}
+
+// this must be precisely 2 characters in length
+#define COMPATIBLE_REG "0C"
+
+void start_string()
+{
+ printf(".nr " COMPATIBLE_REG " \\n(.C\n");
+ printf(".cp 0\n");
+ printf(".ds " LINE_STRING "\n");
+}
+
+void output_string()
+{
+ printf("\\*[" LINE_STRING "]\n");
+}
+
+void restore_compatibility()
+{
+ printf(".cp \\n(" COMPATIBLE_REG "\n");
+}
+
+void do_text(const char *s)
+{
+ printf(".eo\n");
+ printf(".as " LINE_STRING " \"%s\n", s);
+ printf(".ec\n");
+}
+
+void set_minimum_size(int n)
+{
+ minimum_size = n;
+}
+
+void set_script_size()
+{
+ if (minimum_size < 0)
+ minimum_size = 0;
+ if (script_size_reduction >= 0)
+ printf(".ps \\n[.s]-%d>?%d\n", script_size_reduction, minimum_size);
+ else
+ printf(".ps (u;\\n[.s]*7+5/10>?%d)*1z\n", minimum_size);
+}
+
+int box::next_uid = 0;
+
+box::box() : uid(next_uid++), spacing_type(ORDINARY_TYPE)
+{
+}
+
+box::~box()
+{
+}
+
+void box::top_level()
+{
+ // debug_print();
+ // putc('\n', stderr);
+ box *b = this;
+ printf(".nr " SAVED_FONT_REG " \\n[.f]\n");
+ printf(".ft\n");
+ printf(".nr " SAVED_PREV_FONT_REG " \\n[.f]\n");
+ printf(".ft %s\n", get_gfont());
+ printf(".nr " SAVED_SIZE_REG " \\n[.s]z\n");
+ if (gsize > 0) {
+ char buf[INT_DIGITS + 1];
+ sprintf(buf, "%d", gsize);
+ b = new size_box(strsave(buf), b);
+ }
+ current_roman_font = get_grfont();
+ // This catches tabs used within \Z (which aren't allowed).
+ b->check_tabs(0);
+ int r = b->compute_metrics(DISPLAY_STYLE);
+ printf(".ft \\n[" SAVED_PREV_FONT_REG "]\n");
+ printf(".ft \\n[" SAVED_FONT_REG "]\n");
+ printf(".nr " MARK_OR_LINEUP_FLAG_REG " %d\n", r);
+ if (r == FOUND_MARK) {
+ printf(".nr " SAVED_MARK_REG " \\n[" MARK_REG "]\n");
+ printf(".nr " MARK_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", b->uid);
+ }
+ else if (r == FOUND_LINEUP)
+ printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
+ SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n");
+ else
+ assert(r == FOUND_NOTHING);
+ // The problem here is that the argument to \f is read in copy mode,
+ // so we cannot use \E there; so we hide it in a string instead.
+ // Another problem is that if we use \R directly, then the space will
+ // prevent it working in a macro argument.
+ printf(".ds " SAVE_FONT_STRING " "
+ "\\R'" SAVED_INLINE_FONT_REG " \\\\n[.f]'"
+ "\\fP"
+ "\\R'" SAVED_INLINE_PREV_FONT_REG " \\\\n[.f]'"
+ "\\R'" SAVED_INLINE_SIZE_REG " \\\\n[.s]z'"
+ "\\s0"
+ "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\\\n[.s]z'"
+ "\n"
+ ".ds " RESTORE_FONT_STRING " "
+ "\\f[\\\\n[" SAVED_INLINE_PREV_FONT_REG "]]"
+ "\\f[\\\\n[" SAVED_INLINE_FONT_REG "]]"
+ "\\s'\\\\n[" SAVED_INLINE_PREV_SIZE_REG "]u'"
+ "\\s'\\\\n[" SAVED_INLINE_SIZE_REG "]u'"
+ "\n");
+ printf(".as " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]");
+ printf("\\f[%s]", get_gfont());
+ printf("\\s'\\En[" SAVED_SIZE_REG "]u'");
+ current_roman_font = get_grfont();
+ b->output();
+ printf("\\E*[" RESTORE_FONT_STRING "]\n");
+ if (r == FOUND_LINEUP)
+ printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
+ MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n["
+ WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n",
+ b->uid);
+ b->extra_space();
+ if (!inline_flag)
+ printf(".ne \\n[" HEIGHT_FORMAT "]u-%dM>?0+(\\n["
+ DEPTH_FORMAT "]u-%dM>?0)\n",
+ b->uid, body_height, b->uid, body_depth);
+ delete b;
+ next_uid = 0;
+}
+
+// gpic defines this register so as to make geqn not produce `\x's
+#define EQN_NO_EXTRA_SPACE_REG "0x"
+
+void box::extra_space()
+{
+ printf(".if !r" EQN_NO_EXTRA_SPACE_REG " "
+ ".nr " EQN_NO_EXTRA_SPACE_REG " 0\n");
+ if (positive_space >= 0 || negative_space >= 0) {
+ if (positive_space > 0)
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".as " LINE_STRING " \\x'-%dM'\n", positive_space);
+ if (negative_space > 0)
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".as " LINE_STRING " \\x'%dM'\n", negative_space);
+ positive_space = negative_space = -1;
+ }
+ else {
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".if \\n[" HEIGHT_FORMAT "]>%dM .as " LINE_STRING
+ " \\x'-(\\n[" HEIGHT_FORMAT
+ "]u-%dM)'\n",
+ uid, body_height, uid, body_height);
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".if \\n[" DEPTH_FORMAT "]>%dM .as " LINE_STRING
+ " \\x'\\n[" DEPTH_FORMAT
+ "]u-%dM'\n",
+ uid, body_depth, uid, body_depth);
+ }
+}
+
+int box::compute_metrics(int)
+{
+ printf(".nr " WIDTH_FORMAT " 0\n", uid);
+ printf(".nr " HEIGHT_FORMAT " 0\n", uid);
+ printf(".nr " DEPTH_FORMAT " 0\n", uid);
+ return FOUND_NOTHING;
+}
+
+void box::compute_subscript_kern()
+{
+ printf(".nr " SUB_KERN_FORMAT " 0\n", uid);
+}
+
+void box::compute_skew()
+{
+ printf(".nr " SKEW_FORMAT " 0\n", uid);
+}
+
+void box::output()
+{
+}
+
+void box::check_tabs(int)
+{
+}
+
+int box::is_char()
+{
+ return 0;
+}
+
+int box::left_is_italic()
+{
+ return 0;
+}
+
+int box::right_is_italic()
+{
+ return 0;
+}
+
+void box::hint(unsigned)
+{
+}
+
+void box::handle_char_type(int, int)
+{
+}
+
+
+box_list::box_list(box *pp)
+{
+ p = new box*[10];
+ for (int i = 0; i < 10; i++)
+ p[i] = 0;
+ maxlen = 10;
+ len = 1;
+ p[0] = pp;
+}
+
+void box_list::append(box *pp)
+{
+ if (len + 1 > maxlen) {
+ box **oldp = p;
+ maxlen *= 2;
+ p = new box*[maxlen];
+ memcpy(p, oldp, sizeof(box*)*len);
+ a_delete oldp;
+ }
+ p[len++] = pp;
+}
+
+box_list::~box_list()
+{
+ for (int i = 0; i < len; i++)
+ delete p[i];
+ a_delete p;
+}
+
+void box_list::list_check_tabs(int level)
+{
+ for (int i = 0; i < len; i++)
+ p[i]->check_tabs(level);
+}
+
+
+pointer_box::pointer_box(box *pp) : p(pp)
+{
+ spacing_type = p->spacing_type;
+}
+
+pointer_box::~pointer_box()
+{
+ delete p;
+}
+
+int pointer_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void pointer_box::compute_subscript_kern()
+{
+ p->compute_subscript_kern();
+ printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", uid, p->uid);
+}
+
+void pointer_box::compute_skew()
+{
+ p->compute_skew();
+ printf(".nr " SKEW_FORMAT " 0\\n[" SKEW_FORMAT "]\n",
+ uid, p->uid);
+}
+
+void pointer_box::check_tabs(int level)
+{
+ p->check_tabs(level);
+}
+
+int simple_box::compute_metrics(int)
+{
+ printf(".nr " WIDTH_FORMAT " 0\\w" DELIMITER_CHAR, uid);
+ output();
+ printf(DELIMITER_CHAR "\n");
+ printf(".nr " HEIGHT_FORMAT " 0>?\\n[rst]\n", uid);
+ printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?0\n", uid);
+ printf(".nr " SUB_KERN_FORMAT " 0-\\n[ssc]>?0\n", uid);
+ printf(".nr " SKEW_FORMAT " 0\\n[skw]\n", uid);
+ return FOUND_NOTHING;
+}
+
+void simple_box::compute_subscript_kern()
+{
+ // do nothing, we already computed it in do_metrics
+}
+
+void simple_box::compute_skew()
+{
+ // do nothing, we already computed it in do_metrics
+}
+
+int box::is_simple()
+{
+ return 0;
+}
+
+int simple_box::is_simple()
+{
+ return 1;
+}
+
+quoted_text_box::quoted_text_box(char *s) : text(s)
+{
+}
+
+quoted_text_box::~quoted_text_box()
+{
+ a_delete text;
+}
+
+void quoted_text_box::output()
+{
+ if (text)
+ fputs(text, stdout);
+}
+
+tab_box::tab_box() : disabled(0)
+{
+}
+
+// We treat a tab_box as having width 0 for width computations.
+
+void tab_box::output()
+{
+ if (!disabled)
+ printf("\\t");
+}
+
+void tab_box::check_tabs(int level)
+{
+ if (level > 0) {
+ error("tabs allowed only at outermost level");
+ disabled = 1;
+ }
+}
+
+space_box::space_box()
+{
+ spacing_type = SUPPRESS_TYPE;
+}
+
+void space_box::output()
+{
+ printf("\\h'%dM'", thick_space);
+}
+
+half_space_box::half_space_box()
+{
+ spacing_type = SUPPRESS_TYPE;
+}
+
+void half_space_box::output()
+{
+ printf("\\h'%dM'", thin_space);
+}
+
+void box_list::list_debug_print(const char *sep)
+{
+ p[0]->debug_print();
+ for (int i = 1; i < len; i++) {
+ fprintf(stderr, "%s", sep);
+ p[i]->debug_print();
+ }
+}
+
+void quoted_text_box::debug_print()
+{
+ fprintf(stderr, "\"%s\"", (text ? text : ""));
+}
+
+void half_space_box::debug_print()
+{
+ fprintf(stderr, "^");
+}
+
+void space_box::debug_print()
+{
+ fprintf(stderr, "~");
+}
+
+void tab_box::debug_print()
+{
+ fprintf(stderr, "<tab>");
+}
diff --git a/gnu/usr.bin/groff/eqn/box.h b/gnu/usr.bin/groff/eqn/box.h
new file mode 100644
index 000000000000..a6da83eca9a5
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/box.h
@@ -0,0 +1,277 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct list_box;
+
+class box {
+private:
+ static int next_uid;
+public:
+ int spacing_type;
+ const int uid;
+ box();
+ virtual void debug_print() = 0;
+ virtual ~box();
+ void top_level();
+ virtual int compute_metrics(int);
+ virtual void compute_subscript_kern();
+ virtual void compute_skew();
+ virtual void output();
+ void extra_space();
+ virtual list_box *to_list_box();
+ virtual int is_simple();
+ virtual int is_char();
+ virtual int left_is_italic();
+ virtual int right_is_italic();
+ virtual void handle_char_type(int, int);
+ enum { FOUND_NOTHING = 0, FOUND_MARK = 1, FOUND_LINEUP = 2 };
+ void set_spacing_type(char *type);
+ virtual void hint(unsigned);
+ virtual void check_tabs(int);
+};
+
+class box_list {
+private:
+ int maxlen;
+public:
+ box **p;
+ int len;
+
+ box_list(box *);
+ ~box_list();
+ void append(box *);
+ void list_check_tabs(int);
+ void list_debug_print(const char *sep);
+ friend class list_box;
+};
+
+class list_box : public box {
+ int is_script;
+ box_list list;
+ int sty;
+public:
+ list_box(box *);
+ void debug_print();
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void output();
+ void check_tabs(int);
+ void append(box *);
+ list_box *to_list_box();
+ void handle_char_type(int, int);
+ void compute_sublist_width(int n);
+ friend box *make_script_box(box *, box *, box *);
+ friend box *make_mark_box(box *);
+ friend box *make_lineup_box(box *);
+};
+
+enum alignment { LEFT_ALIGN, RIGHT_ALIGN, CENTER_ALIGN };
+
+class column : public box_list {
+ alignment align;
+ int space;
+public:
+ column(box *);
+ void set_alignment(alignment);
+ void set_space(int);
+ void debug_print(const char *);
+
+ friend class matrix_box;
+ friend class pile_box;
+};
+
+class pile_box : public box {
+ column col;
+public:
+ pile_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+ void set_alignment(alignment a) { col.set_alignment(a); }
+ void set_space(int n) { col.set_space(n); }
+ void append(box *p) { col.append(p); }
+};
+
+class matrix_box : public box {
+private:
+ int len;
+ int maxlen;
+ column **p;
+public:
+ matrix_box(column *);
+ ~matrix_box();
+ void append(column *);
+ int compute_metrics(int);
+ void output();
+ void check_tabs(int);
+ void debug_print();
+};
+
+class pointer_box : public box {
+protected:
+ box *p;
+public:
+ pointer_box(box *);
+ ~pointer_box();
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void compute_skew();
+ void debug_print() = 0;
+ void check_tabs(int);
+};
+
+class vcenter_box : public pointer_box {
+public:
+ vcenter_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class simple_box : public box {
+public:
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void compute_skew();
+ void output() = 0;
+ void debug_print() = 0;
+ int is_simple();
+};
+
+class quoted_text_box : public simple_box {
+ char *text;
+public:
+ quoted_text_box(char *);
+ ~quoted_text_box();
+ void debug_print();
+ void output();
+};
+
+class half_space_box : public simple_box {
+public:
+ half_space_box();
+ void output();
+ void debug_print();
+};
+
+class space_box : public simple_box {
+public:
+ space_box();
+ void output();
+ void debug_print();
+};
+
+class tab_box : public box {
+ int disabled;
+public:
+ tab_box();
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+class size_box : public pointer_box {
+private:
+ char *size;
+public:
+ size_box(char *, box *);
+ ~size_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class font_box : public pointer_box {
+private:
+ char *f;
+public:
+ font_box(char *, box *);
+ ~font_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class fat_box : public pointer_box {
+public:
+ fat_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class vmotion_box : public pointer_box {
+private:
+ int n; // up is >= 0
+public:
+ vmotion_box(int, box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class hmotion_box : public pointer_box {
+ int n;
+public:
+ hmotion_box(int, box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+box *split_text(char *);
+box *make_script_box(box *, box *, box *);
+box *make_mark_box(box *);
+box *make_lineup_box(box *);
+box *make_delim_box(char *, box *, char *);
+box *make_sqrt_box(box *);
+box *make_prime_box(box *);
+box *make_over_box(box *, box *);
+box *make_small_over_box(box *, box *);
+box *make_limit_box(box *, box *, box *);
+box *make_accent_box(box *, box *);
+box *make_uaccent_box(box *, box *);
+box *make_overline_box(box *);
+box *make_underline_box(box *);
+box *make_special_box(char *, box *);
+
+void set_space(int);
+int set_gsize(const char *);
+void set_gfont(const char *);
+void set_grfont(const char *);
+void set_gbfont(const char *);
+const char *get_gfont();
+const char *get_grfont();
+const char *get_gbfont();
+void start_string();
+void output_string();
+void do_text(const char *);
+void restore_compatibility();
+void set_script_reduction(int n);
+void set_minimum_size(int n);
+void set_param(const char *name, int value);
+
+void set_char_type(const char *type, char *ch);
+
+void init_char_table();
+void init_extensible();
+void define_extensible(const char *name, const char *ext, const char *top = 0,
+ const char *mid = 0, const char *bot = 0);
diff --git a/gnu/usr.bin/groff/eqn/delim.cc b/gnu/usr.bin/groff/eqn/delim.cc
new file mode 100644
index 000000000000..ecf9c557e065
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/delim.cc
@@ -0,0 +1,380 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+enum left_or_right_t { LEFT_DELIM = 01, RIGHT_DELIM = 02 };
+
+// Small must be none-zero and must exist in each device.
+// Small will be put in the roman font, others are assumed to be
+// on the special font (so no font change will be necessary.)
+
+struct delimiter {
+ const char *name;
+ int flags;
+ const char *small;
+ const char *chain_format;
+ const char *ext;
+ const char *top;
+ const char *mid;
+ const char *bot;
+} delim_table[] = {
+ {
+ "(", LEFT_DELIM|RIGHT_DELIM, "(", "\\[parenleft%s]",
+ "\\[parenleftex]",
+ "\\[parenlefttp]",
+ 0,
+ "\\[parenleftbt]",
+ },
+ {
+ ")", LEFT_DELIM|RIGHT_DELIM, ")", "\\[parenright%s]",
+ "\\[parenrightex]",
+ "\\[parenrighttp]",
+ 0,
+ "\\[parenrightbt]",
+ },
+ {
+ "[", LEFT_DELIM|RIGHT_DELIM, "[", "\\[bracketleft%s]",
+ "\\[bracketleftex]",
+ "\\[bracketlefttp]",
+ 0,
+ "\\[bracketleftbt]",
+ },
+ {
+ "]", LEFT_DELIM|RIGHT_DELIM, "]", "\\[bracketright%s]",
+ "\\[bracketrightex]",
+ "\\[bracketrighttp]",
+ 0,
+ "\\[bracketrightbt]",
+ },
+ {
+ "{", LEFT_DELIM|RIGHT_DELIM, "{", "\\[braceleft%s]",
+ "\\[braceleftex]",
+ "\\[bracelefttp]",
+ "\\[braceleftmid]",
+ "\\[braceleftbt]",
+ },
+ {
+ "}", LEFT_DELIM|RIGHT_DELIM, "}", "\\[braceright%s]",
+ "\\[bracerightex]",
+ "\\[bracerighttp]",
+ "\\[bracerightmid]",
+ "\\[bracerightbt]",
+ },
+ {
+ "|", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]",
+ "\\[barex]",
+ },
+ {
+ "floor", LEFT_DELIM, "\\(lf", "\\[floorleft%s]",
+ "\\[bracketleftex]",
+ 0,
+ 0,
+ "\\[bracketleftbt]",
+ },
+ {
+ "floor", RIGHT_DELIM, "\\(rf", "\\[floorright%s]",
+ "\\[bracketrightex]",
+ 0,
+ 0,
+ "\\[bracketrightbt]",
+ },
+ {
+ "ceiling", LEFT_DELIM, "\\(lc", "\\[ceilingleft%s]",
+ "\\[bracketleftex]",
+ "\\[bracketlefttp]",
+ },
+ {
+ "ceiling", RIGHT_DELIM, "\\(rc", "\\[ceilingright%s]",
+ "\\[bracketrightex]",
+ "\\[bracketrighttp]",
+ },
+ {
+ "||", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]",
+ "\\[bardblex]",
+ },
+ {
+ "<", LEFT_DELIM|RIGHT_DELIM, "\\(la", "\\[angleleft%s]",
+ },
+ {
+ ">", LEFT_DELIM|RIGHT_DELIM, "\\(ra", "\\[angleright%s]",
+ },
+ {
+ "uparrow", LEFT_DELIM|RIGHT_DELIM, "\\(ua", "\\[arrowup%s]",
+ "\\[arrowvertex]",
+ "\\[arrowverttp]",
+ },
+ {
+ "downarrow", LEFT_DELIM|RIGHT_DELIM, "\\(da", "\\[arrowdown%s]",
+ "\\[arrowvertex]",
+ 0,
+ 0,
+ "\\[arrowvertbt]",
+ },
+ {
+ "updownarrow", LEFT_DELIM|RIGHT_DELIM, "\\(va", "\\[arrowupdown%s]",
+ "\\[arrowvertex]",
+ "\\[arrowverttp]",
+ 0,
+ "\\[arrowvertbt]",
+ },
+};
+
+const int DELIM_TABLE_SIZE = int(sizeof(delim_table)/sizeof(delim_table[0]));
+
+class delim_box : public box {
+private:
+ char *left;
+ char *right;
+ box *p;
+public:
+ delim_box(char *, box *, char *);
+ ~delim_box();
+ int compute_metrics(int);
+ void output();
+ void check_tabs(int);
+ void debug_print();
+};
+
+box *make_delim_box(char *l, box *pp, char *r)
+{
+ if (l != 0 && *l == '\0') {
+ a_delete l;
+ l = 0;
+ }
+ if (r != 0 && *r == '\0') {
+ a_delete r;
+ r = 0;
+ }
+ return new delim_box(l, pp, r);
+}
+
+delim_box::delim_box(char *l, box *pp, char *r)
+: left(l), right(r), p(pp)
+{
+}
+
+delim_box::~delim_box()
+{
+ a_delete left;
+ a_delete right;
+ delete p;
+}
+
+static void build_extensible(const char *ext, const char *top, const char *mid,
+ const char *bot)
+{
+ assert(ext != 0);
+ printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ ext);
+ printf(".nr " EXT_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " EXT_DEPTH_REG " 0-\\n[rsb]\n");
+ if (top) {
+ printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]"
+ ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ top);
+ printf(".nr " TOP_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " TOP_DEPTH_REG " 0-\\n[rsb]\n");
+ }
+ if (mid) {
+ printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]"
+ ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ mid);
+ printf(".nr " MID_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " MID_DEPTH_REG " 0-\\n[rsb]\n");
+ }
+ if (bot) {
+ printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]"
+ ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ bot);
+ printf(".nr " BOT_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " BOT_DEPTH_REG " 0-\\n[rsb]\n");
+ }
+ printf(".nr " TOTAL_HEIGHT_REG " 0");
+ if (top)
+ printf("+\\n[" TOP_HEIGHT_REG "]+\\n[" TOP_DEPTH_REG "]");
+ if (bot)
+ printf("+\\n[" BOT_HEIGHT_REG "]+\\n[" BOT_DEPTH_REG "]");
+ if (mid)
+ printf("+\\n[" MID_HEIGHT_REG "]+\\n[" MID_DEPTH_REG "]");
+ printf("\n");
+ // determine how many extensible characters we need
+ printf(".nr " TEMP_REG " \\n[" DELTA_REG "]-\\n[" TOTAL_HEIGHT_REG "]");
+ if (mid)
+ printf("/2");
+ printf(">?0+\\n[" EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "]-1/(\\n["
+ EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "])\n");
+
+ printf(".nr " TOTAL_HEIGHT_REG " +(\\n[" EXT_HEIGHT_REG "]+\\n["
+ EXT_DEPTH_REG "]*\\n[" TEMP_REG "]");
+ if (mid)
+ printf("*2");
+ printf(")\n");
+ printf(".ds " DELIM_STRING " \\Z" DELIMITER_CHAR
+ "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG "]u/2u)'\n",
+ axis_height);
+ if (top)
+ printf(".as " DELIM_STRING " \\v'\\n[" TOP_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" TOP_DEPTH_REG "]u'\n",
+ top);
+
+ // this macro appends $2 copies of $3 to string $1
+ printf(".de " REPEAT_APPEND_STRING_MACRO "\n"
+ ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n"
+ "." REPEAT_APPEND_STRING_MACRO " \\\\$1 \\\\$2-1 \"\\\\$3\"\n"
+ ".\\}\n"
+ "..\n");
+
+ printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING " \\n[" TEMP_REG "] "
+ "\\v'\\n[" EXT_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" EXT_DEPTH_REG "]u'\n",
+ ext);
+
+ if (mid) {
+ printf(".as " DELIM_STRING " \\v'\\n[" MID_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" MID_DEPTH_REG "]u'\n",
+ mid);
+ printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING
+ " \\n[" TEMP_REG "] "
+ "\\v'\\n[" EXT_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" EXT_DEPTH_REG "]u'\n",
+ ext);
+ }
+ if (bot)
+ printf(".as " DELIM_STRING " \\v'\\n[" BOT_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" BOT_DEPTH_REG "]u'\n",
+ bot);
+ printf(".as " DELIM_STRING " " DELIMITER_CHAR "\n");
+}
+
+static void define_extensible_string(char *delim, int uid,
+ left_or_right_t left_or_right)
+{
+ printf(".ds " DELIM_STRING "\n");
+ delimiter *d = delim_table;
+ int delim_len = strlen(delim);
+ for (int i = 0; i < DELIM_TABLE_SIZE; i++, d++)
+ if (strncmp(delim, d->name, delim_len) == 0
+ && (left_or_right & d->flags) != 0)
+ break;
+ if (i >= DELIM_TABLE_SIZE) {
+ error("there is no `%1' delimiter", delim);
+ printf(".nr " DELIM_WIDTH_REG " 0\n");
+ return;
+ }
+
+ printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "\\f[%s]%s\\fP" DELIMITER_CHAR "\n"
+ ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR
+ "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR "\n"
+ ".nr " TOTAL_HEIGHT_REG " \\n[rst]-\\n[rsb]\n"
+ ".if \\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] "
+ "\\{",
+ current_roman_font, d->small, axis_height,
+ current_roman_font, d->small);
+
+ char buf[256];
+ sprintf(buf, d->chain_format, "\\\\n[" INDEX_REG "]");
+ printf(".nr " INDEX_REG " 0\n"
+ ".de " TEMP_MACRO "\n"
+ ".ie c%s \\{\\\n"
+ ".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n"
+ ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR
+ "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR "\n"
+ ".nr " TOTAL_HEIGHT_REG " \\\\n[rst]-\\\\n[rsb]\n"
+ ".if \\\\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] "
+ "\\{.nr " INDEX_REG " +1\n"
+ "." TEMP_MACRO "\n"
+ ".\\}\\}\n"
+ ".el .nr " INDEX_REG " 0-1\n"
+ "..\n"
+ "." TEMP_MACRO "\n",
+ buf, buf, axis_height, buf);
+ if (d->ext) {
+ printf(".if \\n[" INDEX_REG "]<0 \\{.if c%s \\{\\\n", d->ext);
+ build_extensible(d->ext, d->top, d->mid, d->bot);
+ printf(".\\}\\}\n");
+ }
+ printf(".\\}\n");
+ printf(".as " DELIM_STRING " \\h'\\n[" DELIM_WIDTH_REG "]u'\n");
+ printf(".nr " WIDTH_FORMAT " +\\n[" DELIM_WIDTH_REG "]\n", uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?(\\n[" TOTAL_HEIGHT_REG "]/2+%dM)\n",
+ uid, uid, axis_height);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ ">?(\\n[" TOTAL_HEIGHT_REG "]/2-%dM)\n",
+ uid, uid, axis_height);
+}
+
+int delim_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DELTA_REG " \\n[" HEIGHT_FORMAT "]-%dM"
+ ">?(\\n[" DEPTH_FORMAT "]+%dM)\n",
+ p->uid, axis_height, p->uid, axis_height);
+ printf(".nr " DELTA_REG " 0\\n[" DELTA_REG "]*%d/500"
+ ">?(\\n[" DELTA_REG "]*2-%dM)\n",
+ delimiter_factor, delimiter_shortfall);
+ if (left) {
+ define_extensible_string(left, uid, LEFT_DELIM);
+ printf(".rn " DELIM_STRING " " LEFT_DELIM_STRING_FORMAT "\n",
+ uid);
+ }
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" DELIM_WIDTH_REG "]\n");
+ if (right) {
+ define_extensible_string(right, uid, RIGHT_DELIM);
+ printf(".rn " DELIM_STRING " " RIGHT_DELIM_STRING_FORMAT "\n",
+ uid);
+ }
+ return r;
+}
+
+void delim_box::output()
+{
+ if (left)
+ printf("\\*[" LEFT_DELIM_STRING_FORMAT "]", uid);
+ p->output();
+ if (right)
+ printf("\\*[" RIGHT_DELIM_STRING_FORMAT "]", uid);
+}
+
+void delim_box::check_tabs(int level)
+{
+ p->check_tabs(level);
+}
+
+void delim_box::debug_print()
+{
+ fprintf(stderr, "left \"%s\" { ", left ? left : "");
+ p->debug_print();
+ fprintf(stderr, " }");
+ if (right)
+ fprintf(stderr, " right \"%s\"", right);
+}
+
diff --git a/gnu/usr.bin/groff/eqn/eqn.1 b/gnu/usr.bin/groff/eqn/eqn.1
new file mode 100644
index 000000000000..1b9aa78fb616
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/eqn.1
@@ -0,0 +1,862 @@
+.\" -*- nroff -*-
+.ie \n(.V<\n(.v .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH EQN 1 "6 October 1992" "Groff Version 1.08"
+.SH NAME
+eqn \- format equations for troff
+.SH SYNOPSIS
+.B eqn
+[
+.B \-rvCNR
+]
+[
+.BI \-d cc
+]
+[
+.BI \-T name
+]
+[
+.BI \-M dir
+]
+[
+.BI \-f F
+]
+[
+.BI \-s n
+]
+[
+.BI \-p n
+]
+[
+.BI \-m n
+]
+[
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+This manual page describes the GNU version of
+.BR eqn ,
+which is part of the groff document formatting system.
+.B eqn
+compiles descriptions of equations embedded within
+.B troff
+input files into commands that are understood by
+.BR troff .
+Normally, it should be invoked using the
+.B \-e
+option of
+.BR groff .
+The syntax is quite compatible with Unix eqn.
+The output of GNU eqn cannot be processed with Unix troff;
+it must be processed with GNU troff.
+If no files are given on the command line, the standard input
+will be read.
+A filename of
+.B \-
+will cause the standard input to be read.
+.LP
+.B eqn
+searches for the file
+.B eqnrc
+using the path
+.BR /usr/share/tmac .
+If it exists, eqn will process it before the other input files.
+The
+.B \-R
+option prevents this.
+.LP
+GNU eqn does not provide the functionality of neqn:
+it does not support low-resolution, typewriter-like devices
+(although it may work adequately for very simple input).
+.SH OPTIONS
+.TP
+.B \-C
+Recognize
+.B .EQ
+and
+.B .EN
+even when followed by a character other than space or newline.
+.TP
+.B \-N
+Don't allow newlines within delimiters.
+This option allows
+.B eqn
+to recover better from missing closing delimiters.
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-r
+Only one size reduction.
+.TP
+.BI \-m n
+The minimum point-size is
+.IR n .
+eqn will not reduce the size of subscripts or superscripts to
+a smaller size than
+.IR n .
+.TP
+.BI \-T name
+The output is for device
+.IR name .
+The only effect of this is to define a macro
+.I name
+with a value of
+.BR 1 .
+Typically
+.B eqnrc
+will use this to provide definitions appropriate for the output device.
+The default output device is
+.BR ps .
+.TP
+.BI \-M dir
+Search
+.I dir
+for
+.B eqnrc
+before the default directories.
+.TP
+.B \-R
+Don't load
+.BR eqnrc .
+.TP
+.BI \-f F
+This is equivalent to a
+.BI gfont\ F
+command.
+.TP
+.BI \-s n
+This is equivalent to a
+.BI gsize\ n
+command.
+This option is deprecated.
+eqn will normally set equations at whatever the current point size
+is when the equation is encountered.
+.TP
+.BI \-p n
+This says that subscripts and superscripts should be
+.I n
+points smaller than the surrounding text.
+This option is deprecated.
+Normally eqn makes sets subscripts and superscripts at 70%
+of the size of the surrounding text.
+.SH USAGE
+Only the differences between GNU eqn and Unix eqn are described here.
+.LP
+Most of the new features of GNU eqn
+are based on \*(tx.
+There are some references to the differences between \*(tx and GNU eqn below;
+these may safely be ignored if you do not know \*(tx.
+.SS Automatic spacing
+.LP
+.B eqn
+gives each component of an equation a type, and adjusts the spacing
+between components using that type.
+Possible types are:
+.TP \w'punctuation'u+2n
+ordinary
+an ordinary character such as 1 or
+.IR x ;
+.TP
+operator
+a large operator such as
+.ds Su \s+5\(*S\s0
+.if \n(.g .if !c\(*S .ds Su the summation operator
+\*(Su;
+.TP
+binary
+a binary operator such as +;
+.TP
+relation
+a relation such as =;
+.TP
+opening
+a opening bracket such as (;
+.TP
+closing
+a closing bracket such as );
+.TP
+punctuation
+a punctutation character such as ,;
+.TP
+inner
+a subformula contained within brackets;
+.TP
+suppress
+spacing that suppresses automatic spacing adjustment.
+.LP
+Components of an equation get a type in one of two ways.
+.TP
+.BI type\ t\ e
+This yields an equation component that contains
+.I e
+but that has type
+.IR t ,
+where
+.I t
+is one of the types mentioned above.
+For example,
+.B times
+is defined as
+.RS
+.IP
+.B
+type "binary" \e(mu
+.RE
+.IP
+The name of the type doesn't have to be quoted, but quoting protects
+from macro expansion.
+.TP
+.BI chartype\ t\ text
+Unquoted groups of characters are split up into individual characters,
+and the type of each character is looked up;
+this changes the type that is stored for each character;
+it says that the characters in
+.I text
+from now on have type
+.IR t .
+For example,
+.RS
+.IP
+.B
+chartype "punctuation" .,;:
+.RE
+.IP
+would make the characters
+.B .,;:
+have type punctuation
+whenever they subsequently appeared in an equation.
+The type
+.I t
+can also be
+.B letter
+or
+.BR digit ;
+in these cases
+.B chartype
+changes the font type of the characters.
+See the Fonts subsection.
+.SS New primitives
+.TP
+.IB e1\ smallover\ e2
+This is similar to
+.BR over ;
+.B smallover
+reduces the size of
+.I e1
+and
+.IR e2 ;
+it also puts less vertical space between
+.I e1
+or
+.I e2
+and the fraction bar.
+The
+.B over
+primitive corresponds to the \*(tx
+.B \eover
+primitive in display styles;
+.B smallover
+corresponds to
+.B \eover
+in non-display styles.
+.TP
+.BI vcenter\ e
+This vertically centers
+.I e
+about the math axis.
+The math axis is the vertical position about which characters
+such as + and - are centered; also it is the vertical position
+used for the bar of fractions.
+For example,
+.B sum
+is defined as
+.RS
+.IP
+.B
+{ type "operator" vcenter size +5 \e(*S }
+.RE
+.TP
+.IB e1\ accent\ e2
+This sets
+.I e2
+as an accent over
+.IR e1 .
+.I e2
+is assumed to be at the correct height for a lowercase letter;
+.I e2
+will be moved down according if
+.I e1
+is taller or shorter than a lowercase letter.
+For example,
+.B hat
+is defined as
+.RS
+.IP
+.B
+accent { "^" }
+.RE
+.IP
+.BR dotdot ,
+.BR dot ,
+.BR tilde ,
+.B vec
+and
+.B dyad
+are also defined using the
+.B accent
+primitive.
+.TP
+.IB e1\ uaccent\ e2
+This sets
+.I e2
+as an accent under
+.IR e1 .
+.I e2
+is assumed to be at the correct height for a character without a descender;
+.I e2
+will be moved down if
+.I e1
+has a descender.
+.B utilde
+is pre-defined using
+.B uaccent
+as a tilde accent below the baseline.
+.TP
+.BI split\ \(ts text \(ts
+This has the same effect as simply
+.RS
+.IP
+.I text
+.RE
+.IP
+but
+.I text
+is not subject to macro expansion because it is quoted;
+.I text
+will be split up and the spacing between individual characters
+will be adjusted.
+.TP
+.BI nosplit\ text
+This has the same effect as
+.RS
+.IP
+.BI \(ts text \(ts
+.RE
+.IP
+but because
+.I text
+is not quoted it will be subject to macro expansion;
+.I text
+will not be split up
+and the spacing between individual characters will not be adjusted.
+.TP
+.IB e\ opprime
+This is a variant of
+.B prime
+that acts as an operator on
+.IR e .
+It produces a different result from
+.B prime
+in a case such as
+.BR A\ opprime\ sub\ 1 :
+with
+.B opprime
+the
+.B 1
+will be tucked under the prime as a subscript to the
+.B A
+(as is conventional in mathematical typesetting),
+whereas with
+.B prime
+the
+.B 1
+will be a subscript to the prime character.
+The precedence of
+.B opprime
+is the same as that of
+.B bar
+and
+.BR under ,
+which is higher than that of everything except
+.B accent
+and
+.BR uaccent .
+In unquoted text a
+.B '
+that is not the first character will be treated like
+.BR opprime .
+.TP
+.BI special\ text\ e
+This constructs a new object from
+.I e
+using a
+.BR troff (1)
+macro named
+.IR text .
+When the macro is called,
+the string
+.B 0s
+will contain the output for
+.IR e ,
+and the number registers
+.BR 0w ,
+.BR 0h ,
+.BR 0d ,
+.BR 0skern
+and
+.BR 0skew
+will contain the width, height, depth, subscript kern, and skew of
+.IR e .
+(The
+.I "subscript kern"
+of an object says how much a subscript on that object should be tucked in;
+the
+.I skew
+of an object says how far to the right of the center of the object an
+accent over the object should be placed.)
+The macro must modify
+.B 0s
+so that it will output the desired result with its origin at the current
+point, and increase the current horizontal position by the width
+of the object.
+The number registers must also be modified so that they correspond to the
+result.
+.RS
+.LP
+For example, suppose you wanted a construct that `cancels' an expression
+by drawing a diagonal line through it.
+.IP
+.nf
+.ft B
+.ne 6+\n(.Vu
+\&.EQ
+define cancel 'special Ca'
+\&.EN
+\&.de Ca
+\&.ds 0s \eZ'\e\e*(0s'\ev'\e\en(0du'\eD'l \e\en(0wu -\e\en(0hu-\e\en(0du'\ev'\e\en(0hu'
+\&..
+.ft
+.fi
+.LP
+Then you could cancel an expression
+.I e
+with
+.BI cancel\ {\ e\ }
+.LP
+Here's a more complicated construct that draws a box round an expression:
+.IP
+.nf
+.ft B
+.ne 11+\n(.Vu
+\&.EQ
+define box 'special Bx'
+\&.EN
+\&.de Bx
+\&.ds 0s \eZ'\eh'1n'\e\e*(0s'\e
+\eZ'\ev'\e\en(0du+1n'\eD'l \e\en(0wu+2n 0'\eD'l 0 -\e\en(0hu-\e\en(0du-2n'\e
+\eD'l -\e\en(0wu-2n 0'\eD'l 0 \e\en(0hu+\e\en(0du+2n''\eh'\e\en(0wu+2n'
+\&.nr 0w +2n
+\&.nr 0d +1n
+\&.nr 0h +1n
+\&..
+.ft
+.fi
+.RE
+.SS Customization
+The appearance of equations is controlled by
+a large number of parameters. These can be set using
+the
+.B set
+command.
+.TP
+.BI set\ p\ n
+This sets parameter
+.I p
+to value
+.I n ;
+.I n
+is an integer.
+For example,
+.RS
+.IP
+.B
+set x_height 45
+.RE
+.IP
+says that
+.B eqn
+should assume an x height of 0.45 ems.
+.RS
+.LP
+Possible parameters are as follows.
+Values are in units of hundredths of an em unless otherwise stated.
+These descriptions are intended to be expository rather than
+definitive.
+.TP \w'\fBdefault_rule_thickness'u+2n
+.B minimum_size
+.B eqn
+will not set anything at a smaller point-size than this.
+The value is in points.
+.TP
+.B fat_offset
+The
+.B fat
+primitive emboldens an equation
+by overprinting two copies of the equation
+horizontally offset by this amount.
+.TP
+.B over_hang
+A fraction bar will be longer by twice this amount than
+the maximum of the widths of the numerator and denominator;
+in other words, it will overhang the numerator and
+denominator by at least this amount.
+.TP
+.B accent_width
+When
+.B bar
+or
+.B under
+is applied to a single character,
+the line will be this long.
+Normally,
+.B bar
+or
+.B under
+produces a line whose length is the width of the object to which it applies;
+in the case of a single character,
+this tends to produce a line that looks too long.
+.TP
+.B delimiter_factor
+Extensible delimiters produced with the
+.B left
+and
+.B right
+primitives will have a combined height and depth of at least this many
+thousandths of twice the maximum amount by which the sub-equation that
+the delimiters enclose extends away from the axis.
+.TP
+.B delimiter_shortfall
+Extensible delimiters produced with the
+.B left
+and
+.B right
+primitives will have a combined height and depth
+not less than the difference of
+twice the maximum amount by which the sub-equation that
+the delimiters enclose extends away from the axis
+and this amount.
+.TP
+.B null_delimiter_space
+This much horizontal space is inserted
+on each side of a fraction.
+.TP
+.B script_space
+The width of subscripts and superscripts is increased by this amount.
+.TP
+.B thin_space
+This amount of space is automatically inserted after punctuation
+characters.
+.TP
+.B medium_space
+This amount of space is automatically inserted on either side
+of binary operators.
+.TP
+.B thick_space
+This amount of space is automatically inserted on either side of
+relations.
+.TP
+.B x_height
+The height of lowercase letters without ascenders such as x.
+.TP
+.B axis_height
+The height above the baseline of the center of characters
+such as \(pl and \(mi.
+It is important that this value is correct for the font
+you are using.
+.TP
+.B default_rule_thickness
+This should set to the thickness of the
+.B \e(ru
+character, or the thickness of horizontal lines produced with the
+.B \eD
+escape sequence.
+.TP
+.B num1
+The
+.B over
+command will shift up the numerator by at least this amount.
+.TP
+.B num2
+The
+.B smallover
+command will shift up the numerator by at least this amount.
+.TP
+.B denom1
+The
+.B over
+command will shift down the denominator by at least this amount.
+.TP
+.B denom2
+The
+.B smallover
+command will shift down the denominator by at least this amount.
+.TP
+.B sup1
+Normally superscripts will be shifted up by at least this amount.
+.TP
+.B sup2
+Superscripts within superscripts or upper limits
+or numerators of
+.B smallover
+fractions
+will be shifted up by at least this amount.
+This is usually less than sup1.
+.TP
+.B sup3
+Superscripts within denominators or square roots
+or subscripts or lower limits will be shifted up by at least
+this amount.
+This is usually less than sup2.
+.TP
+.B sub1
+Subscripts will normally be shifted down by at least this amount.
+.TP
+.B sub2
+When there is both a subscript and a superscript, the subscript
+will be shifted down by at least this amount.
+.TP
+.B sup_drop
+The baseline of a superscript will be no more
+than this much amount below the top of the object on
+which the superscript is set.
+.TP
+.B sub_drop
+The baseline of a subscript will be at least this much below
+the bottom of the object on which the subscript is set.
+.TP
+.B big_op_spacing1
+The baseline of an upper limit will be at least this
+much above the top of the object on which the limit is set.
+.TP
+.B big_op_spacing2
+The baseline of a lower limit will be at least this
+much below the bottom of the object on which the limit is set.
+.TP
+.B big_op_spacing3
+The bottom of an upper limit will be at least this much above the
+top of the object on which the limit is set.
+.TP
+.B big_op_spacing4
+The top of a lower limit will be at least this much below
+the bottom of the object on which the limit is set.
+.TP
+.B big_op_spacing5
+This much vertical space will be added above and below limits.
+.TP
+.B baseline_sep
+The baselines of the rows in a pile or matrix will normally be
+this far apart.
+In most cases this should be equal to the sum of
+.B num1
+and
+.BR denom1 .
+.TP
+.B shift_down
+The midpoint between the top baseline and the bottom baseline
+in a matrix or pile will be shifted down by this much from the axis.
+In most cases this should be equal to
+.BR axis_height .
+.TP
+.B column_sep
+This much space will be added between columns in a matrix.
+.TP
+.B matrix_side_sep
+This much space will be added at each side of a matrix.
+.TP
+.B draw_lines
+If this is non-zero, lines will be drawn using the
+.B \eD
+escape sequence, rather than with the
+.B \el
+escape sequence and the
+.B \e(ru
+character.
+.TP
+.B body_height
+The amount by which the height of the equation exceeds this
+will be added as extra space before the line containing the equation
+(using
+.BR \ex .)
+The default value is 85.
+.TP
+.B body_depth
+The amount by which the depth of the equation exceeds this
+will be added as extra space after the line containing the equation
+(using
+.BR \ex .)
+The default value is 35.
+.TP
+.B nroff
+If this is non-zero,
+then
+.B ndefine
+will behave like
+.B define
+and
+.B tdefine
+will be ignored,
+otherwise
+.B tdefine
+will behave like
+.B define
+and
+.B ndefine
+will be ignored.
+The default value is 0
+(This is typically changed to 1 by the
+.B eqnrc
+file for the
+.B ascii
+and
+.B latin1
+devices.)
+.LP
+A more precise description of the role of many of these
+parameters can be found in Appendix H of
+.IR The\ \*(txbook .
+.RE
+.SS Macros
+Macros can take arguments.
+In a macro body,
+.BI $ n
+where
+.I n
+is between 1 and 9,
+will be replaced by the
+.IR n-th
+argument if the macro is called with arguments;
+if there are fewer than
+.I n
+arguments, it will be replaced by nothing.
+A word containing a left parenthesis where the part of the word
+before the left parenthesis has been defined using the
+.B define
+command
+will be recognized as a macro call with arguments;
+characters following the left parenthesis
+up to a matching right parenthesis will be treated as comma-separated
+arguments;
+commas inside nested parentheses do not terminate an argument.
+.TP
+.BI sdefine\ name\ X\ anything\ X
+This is like the
+.B define
+command, but
+.I name
+will not be recognized if called with arguments.
+.TP
+.BI include\ \(ts file \(ts
+Include the contents of
+.IR file .
+Lines of
+.I file
+beginning with
+.B .EQ
+or
+.B .EN
+will be ignored.
+.TP
+.BI ifdef\ name\ X\ anything\ X
+If
+.I name
+has been defined by
+.B define
+(or has been automatically defined because
+.I name
+is the output device)
+process
+.IR anything ;
+otherwise ignore
+.IR anything .
+.I X
+can be any character not appearing in
+.IR anything .
+.SS Fonts
+.B eqn
+normally uses at least two fonts to set an equation:
+an italic font for letters,
+and a roman font for everything else.
+The existing
+.B gfont
+command
+changes the font that is used as the italic font.
+By default this is
+.BR I .
+The font that is used as the roman font can be changed
+using the new
+.B grfont
+command.
+.TP
+.BI grfont\ f
+Set the roman font to
+.IR f .
+.LP
+The
+.B italic
+primitive uses the current italic font set by
+.BR gfont ;
+the
+.B roman
+primitive uses the current roman font set by
+.BR grfont .
+There is also a new
+.B gbfont
+command, which changes the font used by the
+.B bold
+primitive.
+If you only use the
+.BR roman ,
+.B italic
+and
+.B bold
+primitives to changes fonts within an equation,
+you can change all the fonts used by your equations
+just by using
+.BR gfont ,
+.B grfont
+and
+.B gbfont
+commands.
+.LP
+You can control which characters are treated as letters
+(and therefore set in italics) by using the
+.B chartype
+command described above.
+A type of
+.B letter
+will cause a character to be set in italic type.
+A type of
+.B digit
+will cause a character to be set in roman type.
+.SH FILES
+.Tp \w'\fB/usr/share/tmac/eqnrc'u+2n
+.B /usr/share/tmac/eqnrc
+Initialization file.
+.SH BUGS
+Inline equations will be set at the point size that is current at the
+beginning of the input line.
+.SH "SEE ALSO"
+.BR groff (1),
+.BR troff (1),
+.BR groff_font (5),
+.I The\ \*(txbook
diff --git a/gnu/usr.bin/groff/eqn/eqn.h b/gnu/usr.bin/groff/eqn/eqn.h
new file mode 100644
index 000000000000..e854a6be2eb5
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/eqn.h
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "cset.h"
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+
+#include "box.h"
+
+extern char start_delim;
+extern char end_delim;
+extern int non_empty_flag;
+extern int inline_flag;
+extern int draw_flag;
+extern int one_size_reduction_flag;
+extern int compatible_flag;
+extern int nroff;
+
+void init_lex(const char *str, const char *filename, int lineno);
+void lex_error(const char *message,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+void init_table(const char *device);
+
+// prefix for all registers, strings, macros
+#define PREFIX "0"
diff --git a/gnu/usr.bin/groff/eqn/eqn.y b/gnu/usr.bin/groff/eqn/eqn.y
new file mode 100644
index 000000000000..28011fbd9f84
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/eqn.y
@@ -0,0 +1,331 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+%{
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "lib.h"
+#include "box.h"
+extern int non_empty_flag;
+char *strsave(const char *);
+int yylex();
+void yyerror(const char *);
+%}
+
+%union {
+ char *str;
+ box *b;
+ pile_box *pb;
+ matrix_box *mb;
+ int n;
+ column *col;
+}
+
+%token OVER
+%token SMALLOVER
+%token SQRT
+%token SUB
+%token SUP
+%token LPILE
+%token RPILE
+%token CPILE
+%token PILE
+%token LEFT
+%token RIGHT
+%token TO
+%token FROM
+%token SIZE
+%token FONT
+%token ROMAN
+%token BOLD
+%token ITALIC
+%token FAT
+%token ACCENT
+%token BAR
+%token UNDER
+%token ABOVE
+%token <str> TEXT
+%token <str> QUOTED_TEXT
+%token FWD
+%token BACK
+%token DOWN
+%token UP
+%token MATRIX
+%token COL
+%token LCOL
+%token RCOL
+%token CCOL
+%token MARK
+%token LINEUP
+%token TYPE
+%token VCENTER
+%token PRIME
+%token SPLIT
+%token NOSPLIT
+%token UACCENT
+%token SPECIAL
+
+/* these are handled in the lexer */
+%token SPACE
+%token GFONT
+%token GSIZE
+%token DEFINE
+%token NDEFINE
+%token TDEFINE
+%token SDEFINE
+%token UNDEF
+%token IFDEF
+%token INCLUDE
+%token DELIM
+%token CHARTYPE
+%token SET
+%token GRFONT
+%token GBFONT
+
+/* The original eqn manual says that `left' is right associative. It's lying.
+Consider `left ( ~ left ( ~ right ) right )'. */
+
+%right LEFT
+%left RIGHT
+%right LPILE RPILE CPILE PILE TEXT QUOTED_TEXT MATRIX MARK LINEUP '^' '~' '\t' '{' SPLIT NOSPLIT
+%right FROM TO
+%left SQRT OVER SMALLOVER
+%right SUB SUP
+%right ROMAN BOLD ITALIC FAT FONT SIZE FWD BACK DOWN UP TYPE VCENTER SPECIAL
+%right BAR UNDER PRIME
+%left ACCENT UACCENT
+
+%type <b> mark from_to sqrt_over script simple equation nonsup
+%type <n> number
+%type <str> text delim
+%type <pb> pile_element_list pile_arg
+%type <mb> column_list
+%type <col> column column_arg column_element_list
+
+%%
+top:
+ /* empty */
+ | equation
+ { $1->top_level(); non_empty_flag = 1; }
+ ;
+
+equation:
+ mark
+ { $$ = $1; }
+ | equation mark
+ {
+ list_box *lb = $1->to_list_box();
+ if (!lb)
+ lb = new list_box($1);
+ lb->append($2);
+ $$ = lb;
+ }
+ ;
+
+mark:
+ from_to
+ { $$ = $1; }
+ | MARK mark
+ { $$ = make_mark_box($2); }
+ | LINEUP mark
+ { $$ = make_lineup_box($2); }
+ ;
+
+from_to:
+ sqrt_over %prec FROM
+ { $$ = $1; }
+ | sqrt_over TO from_to
+ { $$ = make_limit_box($1, 0, $3); }
+ | sqrt_over FROM sqrt_over
+ { $$ = make_limit_box($1, $3, 0); }
+ | sqrt_over FROM sqrt_over TO from_to
+ { $$ = make_limit_box($1, $3, $5); }
+ | sqrt_over FROM sqrt_over FROM from_to
+ { $$ = make_limit_box($1, make_limit_box($3, $5, 0), 0); }
+ ;
+
+sqrt_over:
+ script
+ { $$ = $1; }
+ | SQRT sqrt_over
+ { $$ = make_sqrt_box($2); }
+ | sqrt_over OVER sqrt_over
+ { $$ = make_over_box($1, $3); }
+ | sqrt_over SMALLOVER sqrt_over
+ { $$ = make_small_over_box($1, $3); }
+ ;
+
+script:
+ nonsup
+ { $$ = $1; }
+ | simple SUP script
+ { $$ = make_script_box($1, 0, $3); }
+ ;
+
+nonsup:
+ simple %prec SUP
+ { $$ = $1; }
+ | simple SUB nonsup
+ { $$ = make_script_box($1, $3, 0); }
+ | simple SUB simple SUP script
+ { $$ = make_script_box($1, $3, $5); }
+ ;
+
+simple:
+ TEXT
+ { $$ = split_text($1); }
+ | QUOTED_TEXT
+ { $$ = new quoted_text_box($1); }
+ | SPLIT QUOTED_TEXT
+ { $$ = split_text($2); }
+ | NOSPLIT TEXT
+ { $$ = new quoted_text_box($2); }
+ | '^'
+ { $$ = new half_space_box; }
+ | '~'
+ { $$ = new space_box; }
+ | '\t'
+ { $$ = new tab_box; }
+ | '{' equation '}'
+ { $$ = $2; }
+ | PILE pile_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ | LPILE pile_arg
+ { $2->set_alignment(LEFT_ALIGN); $$ = $2; }
+ | RPILE pile_arg
+ { $2->set_alignment(RIGHT_ALIGN); $$ = $2; }
+ | CPILE pile_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ | MATRIX '{' column_list '}'
+ { $$ = $3; }
+ | LEFT delim equation RIGHT delim
+ { $$ = make_delim_box($2, $3, $5); }
+ | LEFT delim equation
+ { $$ = make_delim_box($2, $3, 0); }
+ | simple BAR
+ { $$ = make_overline_box($1); }
+ | simple UNDER
+ { $$ = make_underline_box($1); }
+ | simple PRIME
+ { $$ = make_prime_box($1); }
+ | simple ACCENT simple
+ { $$ = make_accent_box($1, $3); }
+ | simple UACCENT simple
+ { $$ = make_uaccent_box($1, $3); }
+ | ROMAN simple
+ { $$ = new font_box(strsave(get_grfont()), $2); }
+ | BOLD simple
+ { $$ = new font_box(strsave(get_gbfont()), $2); }
+ | ITALIC simple
+ { $$ = new font_box(strsave(get_gfont()), $2); }
+ | FAT simple
+ { $$ = new fat_box($2); }
+ | FONT text simple
+ { $$ = new font_box($2, $3); }
+ | SIZE text simple
+ { $$ = new size_box($2, $3); }
+ | FWD number simple
+ { $$ = new hmotion_box($2, $3); }
+ | BACK number simple
+ { $$ = new hmotion_box(-$2, $3); }
+ | UP number simple
+ { $$ = new vmotion_box($2, $3); }
+ | DOWN number simple
+ { $$ = new vmotion_box(-$2, $3); }
+ | TYPE text simple
+ { $3->set_spacing_type($2); $$ = $3; }
+ | VCENTER simple
+ { $$ = new vcenter_box($2); }
+ | SPECIAL text simple
+ { $$ = make_special_box($2, $3); }
+ ;
+
+number:
+ text
+ {
+ int n;
+ if (sscanf($1, "%d", &n) == 1)
+ $$ = n;
+ a_delete $1;
+ }
+ ;
+
+pile_element_list:
+ equation
+ { $$ = new pile_box($1); }
+ | pile_element_list ABOVE equation
+ { $1->append($3); $$ = $1; }
+ ;
+
+pile_arg:
+ '{' pile_element_list '}'
+ { $$ = $2; }
+ | number '{' pile_element_list '}'
+ { $3->set_space($1); $$ = $3; }
+ ;
+
+column_list:
+ column
+ { $$ = new matrix_box($1); }
+ | column_list column
+ { $1->append($2); $$ = $1; }
+ ;
+
+column_element_list:
+ equation
+ { $$ = new column($1); }
+ | column_element_list ABOVE equation
+ { $1->append($3); $$ = $1; }
+ ;
+
+column_arg:
+ '{' column_element_list '}'
+ { $$ = $2; }
+ | number '{' column_element_list '}'
+ { $3->set_space($1); $$ = $3; }
+ ;
+
+column:
+ COL column_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ | LCOL column_arg
+ { $2->set_alignment(LEFT_ALIGN); $$ = $2; }
+ | RCOL column_arg
+ { $2->set_alignment(RIGHT_ALIGN); $$ = $2; }
+ | CCOL column_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ ;
+
+text: TEXT
+ { $$ = $1; }
+ | QUOTED_TEXT
+ { $$ = $1; }
+ ;
+
+delim:
+ text
+ { $$ = $1; }
+ | '{'
+ { $$ = strsave("{"); }
+ | '}'
+ { $$ = strsave("}"); }
+ ;
+
+%%
diff --git a/gnu/usr.bin/groff/eqn/lex.cc b/gnu/usr.bin/groff/eqn/lex.cc
new file mode 100644
index 000000000000..910db77f56c7
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/lex.cc
@@ -0,0 +1,1160 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "eqn.tab.h"
+#include "stringclass.h"
+#include "ptable.h"
+
+struct definition {
+ char is_macro;
+ char is_simple;
+ union {
+ int tok;
+ char *contents;
+ };
+ definition();
+ ~definition();
+};
+
+definition::definition() : is_macro(1), is_simple(0)
+{
+ contents = 0;
+}
+
+definition::~definition()
+{
+ if (is_macro)
+ a_delete contents;
+}
+
+declare_ptable(definition)
+implement_ptable(definition)
+
+PTABLE(definition) macro_table;
+
+static struct {
+ const char *name;
+ int token;
+} token_table[] = {
+ "over", OVER,
+ "smallover", SMALLOVER,
+ "sqrt", SQRT,
+ "sub", SUB,
+ "sup", SUP,
+ "lpile", LPILE,
+ "rpile", RPILE,
+ "cpile", CPILE,
+ "pile", PILE,
+ "left", LEFT,
+ "right", RIGHT,
+ "to", TO,
+ "from", FROM,
+ "size", SIZE,
+ "font", FONT,
+ "roman", ROMAN,
+ "bold", BOLD,
+ "italic", ITALIC,
+ "fat", FAT,
+ "bar", BAR,
+ "under", UNDER,
+ "accent", ACCENT,
+ "uaccent", UACCENT,
+ "above", ABOVE,
+ "fwd", FWD,
+ "back", BACK,
+ "down", DOWN,
+ "up", UP,
+ "matrix", MATRIX,
+ "col", COL,
+ "lcol", LCOL,
+ "rcol", RCOL,
+ "ccol", CCOL,
+ "mark", MARK,
+ "lineup", LINEUP,
+ "space", SPACE,
+ "gfont", GFONT,
+ "gsize", GSIZE,
+ "define", DEFINE,
+ "sdefine", SDEFINE,
+ "ndefine", NDEFINE,
+ "tdefine", TDEFINE,
+ "undef", UNDEF,
+ "ifdef", IFDEF,
+ "include", INCLUDE,
+ "copy", INCLUDE,
+ "delim", DELIM,
+ "chartype", CHARTYPE,
+ "type", TYPE,
+ "vcenter", VCENTER,
+ "set", SET,
+ "opprime", PRIME,
+ "grfont", GRFONT,
+ "gbfont", GBFONT,
+ "split", SPLIT,
+ "nosplit", NOSPLIT,
+ "special", SPECIAL,
+};
+
+static struct {
+ const char *name;
+ const char *def;
+} def_table[] = {
+ "ALPHA", "\\(*A",
+ "BETA", "\\(*B",
+ "CHI", "\\(*X",
+ "DELTA", "\\(*D",
+ "EPSILON", "\\(*E",
+ "ETA", "\\(*Y",
+ "GAMMA", "\\(*G",
+ "IOTA", "\\(*I",
+ "KAPPA", "\\(*K",
+ "LAMBDA", "\\(*L",
+ "MU", "\\(*M",
+ "NU", "\\(*N",
+ "OMEGA", "\\(*W",
+ "OMICRON", "\\(*O",
+ "PHI", "\\(*F",
+ "PI", "\\(*P",
+ "PSI", "\\(*Q",
+ "RHO", "\\(*R",
+ "SIGMA", "\\(*S",
+ "TAU", "\\(*T",
+ "THETA", "\\(*H",
+ "UPSILON", "\\(*U",
+ "XI", "\\(*C",
+ "ZETA", "\\(*Z",
+ "Alpha", "\\(*A",
+ "Beta", "\\(*B",
+ "Chi", "\\(*X",
+ "Delta", "\\(*D",
+ "Epsilon", "\\(*E",
+ "Eta", "\\(*Y",
+ "Gamma", "\\(*G",
+ "Iota", "\\(*I",
+ "Kappa", "\\(*K",
+ "Lambda", "\\(*L",
+ "Mu", "\\(*M",
+ "Nu", "\\(*N",
+ "Omega", "\\(*W",
+ "Omicron", "\\(*O",
+ "Phi", "\\(*F",
+ "Pi", "\\(*P",
+ "Psi", "\\(*Q",
+ "Rho", "\\(*R",
+ "Sigma", "\\(*S",
+ "Tau", "\\(*T",
+ "Theta", "\\(*H",
+ "Upsilon", "\\(*U",
+ "Xi", "\\(*C",
+ "Zeta", "\\(*Z",
+ "alpha", "\\(*a",
+ "beta", "\\(*b",
+ "chi", "\\(*x",
+ "delta", "\\(*d",
+ "epsilon", "\\(*e",
+ "eta", "\\(*y",
+ "gamma", "\\(*g",
+ "iota", "\\(*i",
+ "kappa", "\\(*k",
+ "lambda", "\\(*l",
+ "mu", "\\(*m",
+ "nu", "\\(*n",
+ "omega", "\\(*w",
+ "omicron", "\\(*o",
+ "phi", "\\(*f",
+ "pi", "\\(*p",
+ "psi", "\\(*q",
+ "rho", "\\(*r",
+ "sigma", "\\(*s",
+ "tau", "\\(*t",
+ "theta", "\\(*h",
+ "upsilon", "\\(*u",
+ "xi", "\\(*c",
+ "zeta", "\\(*z",
+ "max", "{type \"operator\" roman \"max\"}",
+ "min", "{type \"operator\" roman \"min\"}",
+ "lim", "{type \"operator\" roman \"lim\"}",
+ "sin", "{type \"operator\" roman \"sin\"}",
+ "cos", "{type \"operator\" roman \"cos\"}",
+ "tan", "{type \"operator\" roman \"tan\"}",
+ "sinh", "{type \"operator\" roman \"sinh\"}",
+ "cosh", "{type \"operator\" roman \"cosh\"}",
+ "tanh", "{type \"operator\" roman \"tanh\"}",
+ "arc", "{type \"operator\" roman \"arc\"}",
+ "log", "{type \"operator\" roman \"log\"}",
+ "ln", "{type \"operator\" roman \"ln\"}",
+ "exp", "{type \"operator\" roman \"exp\"}",
+ "Re", "{type \"operator\" roman \"Re\"}",
+ "Im", "{type \"operator\" roman \"Im\"}",
+ "det", "{type \"operator\" roman \"det\"}",
+ "and", "{roman \"and\"}",
+ "if", "{roman \"if\"}",
+ "for", "{roman \"for\"}",
+ "sum", "{type \"operator\" vcenter size +5 \\(*S}",
+ "prod", "{type \"operator\" vcenter size +5 \\(*P}",
+ "int", "{type \"operator\" vcenter size +8 \\(is}",
+ "union", "{type \"operator\" vcenter size +5 \\(cu}",
+ "inter", "{type \"operator\" vcenter size +5 \\(ca}",
+ "times", "type \"binary\" \\(mu",
+ "ldots", "type \"inner\" { . . . }",
+ "inf", "\\(if",
+ "partial", "\\(pd",
+ "nothing", "\"\"",
+ "half", "{1 smallover 2}",
+ "hat_def", "roman \"^\"",
+ "hat", "accent { hat_def }",
+ "dot_def", "back 15 \"\\v'-52M'.\\v'52M'\"",
+ "dot", "accent { dot_def }",
+ "dotdot_def", "back 25 \"\\v'-52M'..\\v'52M'\"",
+ "dotdot", "accent { dotdot_def }",
+ "tilde_def", "\"~\"",
+ "tilde", "accent { tilde_def }",
+ "utilde_def", "\"\\v'75M'~\\v'-75M'\"",
+ "utilde", "uaccent { utilde_def }",
+ "vec_def", "up 52 size -5 \\(->",
+ "vec", "accent { vec_def }",
+ "dyad_def", "up 52 size -5 {\\(<- back 60 \\(->}",
+ "dyad", "accent { dyad_def }",
+ "==", "type \"relation\" \\(==",
+ "!=", "type \"relation\" \\(!=",
+ "+-", "type \"binary\" \\(+-",
+ "->", "type \"relation\" \\(->",
+ "<-", "type \"relation\" \\(<-",
+ "<<", "{ < back 20 < }",
+ ">>", "{ > back 20 > }",
+ "...", "type \"inner\" vcenter { . . . }",
+ "prime", "'",
+ "approx", "type \"relation\" \"\\(~=\"",
+ "grad", "\\(gr",
+ "del", "\\(gr",
+ "cdot", "type \"binary\" vcenter .",
+ "dollar", "$",
+};
+
+void init_table(const char *device)
+{
+ for (int i = 0; i < sizeof(token_table)/sizeof(token_table[0]); i++) {
+ definition *def = new definition;
+ def->is_macro = 0;
+ def->tok = token_table[i].token;
+ macro_table.define(token_table[i].name, def);
+ }
+ for (i = 0; i < sizeof(def_table)/sizeof(def_table[0]); i++) {
+ definition *def = new definition;
+ def->is_macro = 1;
+ def->contents = strsave(def_table[i].def);
+ def->is_simple = 1;
+ macro_table.define(def_table[i].name, def);
+ }
+ definition *def = new definition;
+ def->is_macro = 1;
+ def->contents = strsave("1");
+ macro_table.define(device, def);
+}
+
+class input {
+ input *next;
+public:
+ input(input *p);
+ virtual ~input();
+ virtual int get() = 0;
+ virtual int peek() = 0;
+ virtual int get_location(char **, int *);
+
+ friend int get_char();
+ friend int peek_char();
+ friend int get_location(char **, int *);
+ friend void init_lex(const char *str, const char *filename, int lineno);
+};
+
+class file_input : public input {
+ FILE *fp;
+ char *filename;
+ int lineno;
+ string line;
+ const char *ptr;
+ int read_line();
+public:
+ file_input(FILE *, const char *, input *);
+ ~file_input();
+ int get();
+ int peek();
+ int get_location(char **, int *);
+};
+
+
+class macro_input : public input {
+ char *s;
+ char *p;
+public:
+ macro_input(const char *, input *);
+ ~macro_input();
+ int get();
+ int peek();
+};
+
+class top_input : public macro_input {
+ char *filename;
+ int lineno;
+ public:
+ top_input(const char *, const char *, int, input *);
+ ~top_input();
+ int get();
+ int get_location(char **, int *);
+};
+
+class argument_macro_input: public input {
+ char *s;
+ char *p;
+ char *ap;
+ int argc;
+ char *argv[9];
+public:
+ argument_macro_input(const char *, int, char **, input *);
+ ~argument_macro_input();
+ int get();
+ int peek();
+};
+
+input::input(input *x) : next(x)
+{
+}
+
+input::~input()
+{
+}
+
+int input::get_location(char **, int *)
+{
+ return 0;
+}
+
+file_input::file_input(FILE *f, const char *fn, input *p)
+: input(p), lineno(0), ptr("")
+{
+ fp = f;
+ filename = strsave(fn);
+}
+
+file_input::~file_input()
+{
+ a_delete filename;
+ fclose(fp);
+}
+
+int file_input::read_line()
+{
+ for (;;) {
+ line.clear();
+ lineno++;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ else if (illegal_input_char(c))
+ lex_error("illegal input character code %1", c);
+ else {
+ line += char(c);
+ if (c == '\n')
+ break;
+ }
+ }
+ if (line.length() == 0)
+ return 0;
+ if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'E'
+ && (line[2] == 'Q' || line[2] == 'N')
+ && (line.length() == 3 || line[3] == ' ' || line[3] == '\n'
+ || compatible_flag))) {
+ line += '\0';
+ ptr = line.contents();
+ return 1;
+ }
+ }
+}
+
+int file_input::get()
+{
+ if (*ptr != '\0' || read_line())
+ return *ptr++ & 0377;
+ else
+ return EOF;
+}
+
+int file_input::peek()
+{
+ if (*ptr != '\0' || read_line())
+ return *ptr;
+ else
+ return EOF;
+}
+
+int file_input::get_location(char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+macro_input::macro_input(const char *str, input *x) : input(x)
+{
+ p = s = strsave(str);
+}
+
+macro_input::~macro_input()
+{
+ a_delete s;
+}
+
+int macro_input::get()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return *p++ & 0377;
+}
+
+int macro_input::peek()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return *p & 0377;
+}
+
+top_input::top_input(const char *str, const char *fn, int ln, input *x)
+: macro_input(str, x), lineno(ln)
+{
+ filename = strsave(fn);
+}
+
+top_input::~top_input()
+{
+ a_delete filename;
+}
+
+int top_input::get()
+{
+ int c = macro_input::get();
+ if (c == '\n')
+ lineno++;
+ return c;
+}
+
+int top_input::get_location(char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+// Character respresenting $1. Must be illegal input character.
+#define ARG1 14
+
+argument_macro_input::argument_macro_input(const char *body, int ac,
+ char **av, input *x)
+: input(x), argc(ac), ap(0)
+{
+ for (int i = 0; i < argc; i++)
+ argv[i] = av[i];
+ p = s = strsave(body);
+ int j = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') {
+ if (s[i+1] != '0')
+ s[j++] = ARG1 + s[++i] - '1';
+ }
+ else
+ s[j++] = s[i];
+ s[j] = '\0';
+}
+
+
+argument_macro_input::~argument_macro_input()
+{
+ for (int i = 0; i < argc; i++)
+ a_delete argv[i];
+ a_delete s;
+}
+
+int argument_macro_input::get()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return *ap++ & 0377;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return *ap++ & 0377;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return *p++ & 0377;
+}
+
+int argument_macro_input::peek()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return *ap & 0377;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return *ap & 0377;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return *p & 0377;
+}
+
+static input *current_input = 0;
+
+/* we insert a newline between input from different levels */
+
+int get_char()
+{
+ if (current_input == 0)
+ return EOF;
+ else {
+ int c = current_input->get();
+ if (c != EOF)
+ return c;
+ else {
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ return '\n';
+ }
+ }
+}
+
+int peek_char()
+{
+ if (current_input == 0)
+ return EOF;
+ else {
+ int c = current_input->peek();
+ if (c != EOF)
+ return c;
+ else
+ return '\n';
+ }
+}
+
+int get_location(char **fnp, int *lnp)
+{
+ for (input *p = current_input; p; p = p->next)
+ if (p->get_location(fnp, lnp))
+ return 1;
+ return 0;
+}
+
+string token_buffer;
+const int NCONTEXT = 4;
+string context_ring[NCONTEXT];
+int context_index = 0;
+
+void flush_context()
+{
+ for (int i = 0; i < NCONTEXT; i++)
+ context_ring[i] = "";
+ context_index = 0;
+}
+
+void show_context()
+{
+ int i = context_index;
+ fputs(" context is\n\t", stderr);
+ for (;;) {
+ int j = (i + 1) % NCONTEXT;
+ if (j == context_index) {
+ fputs(">>> ", stderr);
+ put_string(context_ring[i], stderr);
+ fputs(" <<<", stderr);
+ break;
+ }
+ else if (context_ring[i].length() > 0) {
+ put_string(context_ring[i], stderr);
+ putc(' ', stderr);
+ }
+ i = j;
+ }
+ putc('\n', stderr);
+}
+
+void add_context(const string &s)
+{
+ context_ring[context_index] = s;
+ context_index = (context_index + 1) % NCONTEXT;
+}
+
+void add_context(char c)
+{
+ context_ring[context_index] = c;
+ context_index = (context_index + 1) % NCONTEXT;
+}
+
+void add_quoted_context(const string &s)
+{
+ string &r = context_ring[context_index];
+ r = '"';
+ for (int i = 0; i < s.length(); i++)
+ if (s[i] == '"')
+ r += "\\\"";
+ else
+ r += s[i];
+ r += '"';
+ context_index = (context_index + 1) % NCONTEXT;
+}
+
+void init_lex(const char *str, const char *filename, int lineno)
+{
+ while (current_input != 0) {
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ current_input = new top_input(str, filename, lineno, 0);
+ flush_context();
+}
+
+
+void get_delimited_text()
+{
+ char *filename;
+ int lineno;
+ int got_location = get_location(&filename, &lineno);
+ int start = get_char();
+ while (start == ' ' || start == '\t' || start == '\n')
+ start = get_char();
+ token_buffer.clear();
+ if (start == EOF) {
+ if (got_location)
+ error_with_file_and_line(filename, lineno,
+ "end of input while defining macro");
+ else
+ error("end of input while defining macro");
+ return;
+ }
+ for (;;) {
+ int c = get_char();
+ if (c == EOF) {
+ if (got_location)
+ error_with_file_and_line(filename, lineno,
+ "end of input while defining macro");
+ else
+ error("end of input while defining macro");
+ add_context(start + token_buffer);
+ return;
+ }
+ if (c == start)
+ break;
+ token_buffer += char(c);
+ }
+ add_context(start + token_buffer + start);
+}
+
+void interpolate_macro_with_args(const char *body)
+{
+ char *argv[9];
+ int argc = 0;
+ for (int i = 0; i < 9; i++)
+ argv[i] = 0;
+ int level = 0;
+ int c;
+ do {
+ token_buffer.clear();
+ for (;;) {
+ c = get_char();
+ if (c == EOF) {
+ lex_error("end of input while scanning macro arguments");
+ break;
+ }
+ if (level == 0 && (c == ',' || c == ')')) {
+ if (token_buffer.length() > 0) {
+ token_buffer += '\0';
+ argv[argc] = strsave(token_buffer.contents());
+ }
+ // for `foo()', argc = 0
+ if (argc > 0 || c != ')' || i > 0)
+ argc++;
+ break;
+ }
+ token_buffer += char(c);
+ if (c == '(')
+ level++;
+ else if (c == ')')
+ level--;
+ }
+ } while (c != ')' && c != EOF);
+ current_input = new argument_macro_input(body, argc, argv, current_input);
+}
+
+/* If lookup flag is non-zero the token will be looked up to see
+if it is macro. If it's 1, it will looked up to see if it's a token.
+*/
+
+int get_token(int lookup_flag = 0)
+{
+ for (;;) {
+ int c = get_char();
+ while (c == ' ' || c == '\n')
+ c = get_char();
+ switch (c) {
+ case EOF:
+ add_context("end of input");
+ return 0;
+ case '"':
+ {
+ int quoted = 0;
+ token_buffer.clear();
+ for (;;) {
+ c = get_char();
+ if (c == EOF) {
+ lex_error("missing \"");
+ break;
+ }
+ else if (c == '\n') {
+ lex_error("newline before end of quoted text");
+ break;
+ }
+ else if (c == '"') {
+ if (!quoted)
+ break;
+ token_buffer[token_buffer.length() - 1] = '"';
+ quoted = 0;
+ }
+ else {
+ token_buffer += c;
+ quoted = quoted ? 0 : c == '\\';
+ }
+ }
+ }
+ add_quoted_context(token_buffer);
+ return QUOTED_TEXT;
+ case '{':
+ case '}':
+ case '^':
+ case '~':
+ case '\t':
+ add_context(c);
+ return c;
+ default:
+ {
+ int break_flag = 0;
+ int quoted = 0;
+ token_buffer.clear();
+ if (c == '\\')
+ quoted = 1;
+ else
+ token_buffer += c;
+ int done = 0;
+ while (!done) {
+ c = peek_char();
+ if (!quoted && lookup_flag != 0 && c == '(') {
+ token_buffer += '\0';
+ definition *def = macro_table.lookup(token_buffer.contents());
+ if (def && def->is_macro && !def->is_simple) {
+ (void)get_char(); // skip initial '('
+ interpolate_macro_with_args(def->contents);
+ break_flag = 1;
+ break;
+ }
+ token_buffer.set_length(token_buffer.length() - 1);
+ }
+ if (quoted) {
+ quoted = 0;
+ switch (c) {
+ case EOF:
+ lex_error("`\\' ignored at end of equation");
+ done = 1;
+ break;
+ case '\n':
+ lex_error("`\\' ignored because followed by newline");
+ done = 1;
+ break;
+ case '\t':
+ lex_error("`\\' ignored because followed by tab");
+ done = 1;
+ break;
+ case '"':
+ (void)get_char();
+ token_buffer += '"';
+ break;
+ default:
+ (void)get_char();
+ token_buffer += '\\';
+ token_buffer += c;
+ break;
+ }
+ }
+ else {
+ switch (c) {
+ case EOF:
+ case '{':
+ case '}':
+ case '^':
+ case '~':
+ case '"':
+ case ' ':
+ case '\t':
+ case '\n':
+ done = 1;
+ break;
+ case '\\':
+ (void)get_char();
+ quoted = 1;
+ break;
+ default:
+ (void)get_char();
+ token_buffer += char(c);
+ break;
+ }
+ }
+ }
+ if (break_flag || token_buffer.length() == 0)
+ break;
+ if (lookup_flag != 0) {
+ token_buffer += '\0';
+ definition *def = macro_table.lookup(token_buffer.contents());
+ token_buffer.set_length(token_buffer.length() - 1);
+ if (def) {
+ if (def->is_macro) {
+ current_input = new macro_input(def->contents, current_input);
+ break;
+ }
+ else if (lookup_flag == 1) {
+ add_context(token_buffer);
+ return def->tok;
+ }
+ }
+ }
+ add_context(token_buffer);
+ return TEXT;
+ }
+ }
+ }
+}
+
+void do_include()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad filename for include");
+ return;
+ }
+ token_buffer += '\0';
+ const char *filename = token_buffer.contents();
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ lex_error("can't open included file `%1'", filename);
+ return;
+ }
+ current_input = new file_input(fp, filename, current_input);
+}
+
+void ignore_definition()
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad definition");
+ return;
+ }
+ get_delimited_text();
+}
+
+void do_definition(int is_simple)
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad definition");
+ return;
+ }
+ token_buffer += '\0';
+ const char *name = token_buffer.contents();
+ definition *def = macro_table.lookup(name);
+ if (def == 0) {
+ def = new definition;
+ macro_table.define(name, def);
+ }
+ else if (def->is_macro) {
+ a_delete def->contents;
+ }
+ get_delimited_text();
+ token_buffer += '\0';
+ def->is_macro = 1;
+ def->contents = strsave(token_buffer.contents());
+ def->is_simple = is_simple;
+}
+
+void do_undef()
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad undef command");
+ return;
+ }
+ token_buffer += '\0';
+ macro_table.define(token_buffer.contents(), 0);
+}
+
+void do_gsize()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to gsize command");
+ return;
+ }
+ token_buffer += '\0';
+ if (!set_gsize(token_buffer.contents()))
+ lex_error("invalid size `%1'", token_buffer.contents());
+}
+
+void do_gfont()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to gfont command");
+ return;
+ }
+ token_buffer += '\0';
+ set_gfont(token_buffer.contents());
+}
+
+void do_grfont()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to grfont command");
+ return;
+ }
+ token_buffer += '\0';
+ set_grfont(token_buffer.contents());
+}
+
+void do_gbfont()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to gbfont command");
+ return;
+ }
+ token_buffer += '\0';
+ set_gbfont(token_buffer.contents());
+}
+
+void do_space()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to space command");
+ return;
+ }
+ token_buffer += '\0';
+ char *ptr;
+ long n = strtol(token_buffer.contents(), &ptr, 10);
+ if (n == 0 && ptr == token_buffer.contents())
+ lex_error("bad argument `%1' to space command");
+ else
+ set_space(int(n));
+}
+
+void do_ifdef()
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad ifdef");
+ return;
+ }
+ token_buffer += '\0';
+ definition *def = macro_table.lookup(token_buffer.contents());
+ int result = def && def->is_macro && !def->is_simple;
+ get_delimited_text();
+ if (result) {
+ token_buffer += '\0';
+ current_input = new macro_input(token_buffer.contents(), current_input);
+ }
+}
+
+void do_delim()
+{
+ int c = get_char();
+ while (c == ' ' || c == '\n')
+ c = get_char();
+ int d;
+ if (c == EOF || (d = get_char()) == EOF)
+ lex_error("end of file while reading argument to `delim'");
+ else {
+ if (c == 'o' && d == 'f' && peek_char() == 'f') {
+ (void)get_char();
+ start_delim = end_delim = '\0';
+ }
+ else {
+ start_delim = c;
+ end_delim = d;
+ }
+ }
+}
+
+void do_chartype()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad chartype");
+ return;
+ }
+ token_buffer += '\0';
+ string type = token_buffer;
+ t = get_token();
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad chartype");
+ return;
+ }
+ token_buffer += '\0';
+ set_char_type(type.contents(), strsave(token_buffer.contents()));
+}
+
+void do_set()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad set");
+ return;
+ }
+ token_buffer += '\0';
+ string param = token_buffer;
+ t = get_token();
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad set");
+ return;
+ }
+ token_buffer += '\0';
+ int n;
+ if (sscanf(&token_buffer[0], "%d", &n) != 1) {
+ lex_error("bad number `%1'", token_buffer.contents());
+ return;
+ }
+ set_param(param.contents(), n);
+}
+
+int yylex()
+{
+ for (;;) {
+ int tk = get_token(1);
+ switch(tk) {
+ case UNDEF:
+ do_undef();
+ break;
+ case SDEFINE:
+ do_definition(1);
+ break;
+ case DEFINE:
+ do_definition(0);
+ break;
+ case TDEFINE:
+ if (!nroff)
+ do_definition(0);
+ else
+ ignore_definition();
+ break;
+ case NDEFINE:
+ if (nroff)
+ do_definition(0);
+ else
+ ignore_definition();
+ break;
+ case GSIZE:
+ do_gsize();
+ break;
+ case GFONT:
+ do_gfont();
+ break;
+ case GRFONT:
+ do_grfont();
+ break;
+ case GBFONT:
+ do_gbfont();
+ break;
+ case SPACE:
+ do_space();
+ break;
+ case INCLUDE:
+ do_include();
+ break;
+ case IFDEF:
+ do_ifdef();
+ break;
+ case DELIM:
+ do_delim();
+ break;
+ case CHARTYPE:
+ do_chartype();
+ break;
+ case SET:
+ do_set();
+ break;
+ case QUOTED_TEXT:
+ case TEXT:
+ token_buffer += '\0';
+ yylval.str = strsave(token_buffer.contents());
+ // fall through
+ default:
+ return tk;
+ }
+ }
+}
+
+void lex_error(const char *message,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ char *filename;
+ int lineno;
+ if (!get_location(&filename, &lineno))
+ error(message, arg1, arg2, arg3);
+ else
+ error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
+}
+
+void yyerror(const char *s)
+{
+ char *filename;
+ int lineno;
+ if (!get_location(&filename, &lineno))
+ error(s);
+ else
+ error_with_file_and_line(filename, lineno, s);
+ show_context();
+}
+
diff --git a/gnu/usr.bin/groff/eqn/limit.cc b/gnu/usr.bin/groff/eqn/limit.cc
new file mode 100644
index 000000000000..04abced8920b
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/limit.cc
@@ -0,0 +1,195 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class limit_box : public box {
+private:
+ box *p;
+ box *from;
+ box *to;
+public:
+ limit_box(box *, box *, box *);
+ ~limit_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+box *make_limit_box(box *pp, box *qq, box *rr)
+{
+ return new limit_box(pp, qq, rr);
+}
+
+limit_box::limit_box(box *pp, box *qq, box *rr)
+: p(pp), from(qq), to(rr)
+{
+ spacing_type = p->spacing_type;
+}
+
+limit_box::~limit_box()
+{
+ delete p;
+ delete from;
+ delete to;
+}
+
+int limit_box::compute_metrics(int style)
+{
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
+ set_script_size();
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ int res = 0;
+ int mark_uid = -1;
+ if (from != 0) {
+ res = from->compute_metrics(cramped_style(script_style(style)));
+ if (res)
+ mark_uid = from->uid;
+ }
+ if (to != 0) {
+ int r = to->compute_metrics(script_style(style));
+ if (res && r)
+ error("multiple marks and lineups");
+ else {
+ mark_uid = to->uid;
+ res = r;
+ }
+ }
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ int r = p->compute_metrics(style);
+ p->compute_subscript_kern();
+ if (res && r)
+ error("multiple marks and lineups");
+ else {
+ mark_uid = p->uid;
+ res = r;
+ }
+ printf(".nr " LEFT_WIDTH_FORMAT " "
+ "0\\n[" WIDTH_FORMAT "]",
+ uid, p->uid);
+ if (from != 0)
+ printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, from->uid);
+ if (to != 0)
+ printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, to->uid);
+ printf("/2\n");
+ printf(".nr " WIDTH_FORMAT " "
+ "0\\n[" WIDTH_FORMAT "]",
+ uid, p->uid);
+ if (from != 0)
+ printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, from->uid);
+ if (to != 0)
+ printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, to->uid);
+ printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
+ if (to != 0)
+ printf(">?\\n[" WIDTH_FORMAT "]", to->uid);
+ if (from != 0)
+ printf(">?\\n[" WIDTH_FORMAT "]", from->uid);
+ printf("\n");
+ if (res)
+ printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]"
+ "-(\\n[" WIDTH_FORMAT "]/2))\n",
+ uid, mark_uid);
+ if (to != 0) {
+ printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT
+ "]>?%dM+\\n[" HEIGHT_FORMAT "]\n",
+ uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
+ HEIGHT_FORMAT "]+%dM\n",
+ uid, uid, to->uid, big_op_spacing5);
+ }
+ else
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ if (from != 0) {
+ printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT
+ "]>?%dM+\\n[" DEPTH_FORMAT "]\n",
+ uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
+ DEPTH_FORMAT "]+%dM\n",
+ uid, uid, from->uid, big_op_spacing5);
+ }
+ else
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return res;
+}
+
+void limit_box::output()
+{
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ if (to != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
+ "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'",
+ uid, to->uid, p->uid);
+ to->output();
+ printf(DELIMITER_CHAR);
+ }
+ if (from != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
+ "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid, from->uid);
+ from->output();
+ printf(DELIMITER_CHAR);
+ }
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
+ "-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void limit_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " }");
+ if (from) {
+ fprintf(stderr, " from { ");
+ from->debug_print();
+ fprintf(stderr, " }");
+ }
+ if (to) {
+ fprintf(stderr, " to { ");
+ to->debug_print();
+ fprintf(stderr, " }");
+ }
+}
+
+void limit_box::check_tabs(int level)
+{
+ if (to)
+ to->check_tabs(level + 1);
+ if (from)
+ from->check_tabs(level + 1);
+ p->check_tabs(level + 1);
+}
diff --git a/gnu/usr.bin/groff/eqn/list.cc b/gnu/usr.bin/groff/eqn/list.cc
new file mode 100644
index 000000000000..7c8d1d617d17
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/list.cc
@@ -0,0 +1,236 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+list_box *box::to_list_box()
+{
+ return 0;
+}
+
+list_box *list_box::to_list_box()
+{
+ return this;
+}
+
+void list_box::append(box *pp)
+{
+ list_box *q = pp->to_list_box();
+ if (q == 0)
+ list.append(pp);
+ else {
+ for (int i = 0; i < q->list.len; i++) {
+ list.append(q->list.p[i]);
+ q->list.p[i] = 0;
+ }
+ q->list.len = 0;
+ delete q;
+ }
+}
+
+list_box::list_box(box *pp) : list(pp), sty(-1)
+{
+ list_box *q = pp->to_list_box();
+ if (q != 0) {
+ // flatten it
+ list.p[0] = q->list.p[0];
+ for (int i = 1; i < q->list.len; i++) {
+ list.append(q->list.p[i]);
+ q->list.p[i] = 0;
+ }
+ q->list.len = 0;
+ delete q;
+ }
+}
+
+static int compute_spacing(int is_script, int left, int right)
+{
+ if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE)
+ return 0;
+ if (left == PUNCTUATION_TYPE)
+ return is_script ? 0 : thin_space;
+ if (left == OPENING_TYPE || right == CLOSING_TYPE)
+ return 0;
+ if (right == BINARY_TYPE || left == BINARY_TYPE)
+ return is_script ? 0 : medium_space;
+ if (right == RELATION_TYPE) {
+ if (left == RELATION_TYPE)
+ return 0;
+ else
+ return is_script ? 0 : thick_space;
+ }
+ if (left == RELATION_TYPE)
+ return is_script ? 0 : thick_space;
+ if (right == OPERATOR_TYPE)
+ return thin_space;
+ if (left == INNER_TYPE || right == INNER_TYPE)
+ return is_script ? 0 : thin_space;
+ if (left == OPERATOR_TYPE && right == ORDINARY_TYPE)
+ return thin_space;
+ return 0;
+}
+
+int list_box::compute_metrics(int style)
+{
+ sty = style;
+ int i;
+ for (i = 0; i < list.len; i++) {
+ int t = list.p[i]->spacing_type;
+ // 5
+ if (t == BINARY_TYPE) {
+ int prevt;
+ if (i == 0
+ || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE
+ || prevt == OPERATOR_TYPE
+ || prevt == RELATION_TYPE
+ || prevt == OPENING_TYPE
+ || prevt == PUNCTUATION_TYPE)
+ list.p[i]->spacing_type = ORDINARY_TYPE;
+ }
+ // 7
+ else if ((t == RELATION_TYPE || t == CLOSING_TYPE
+ || t == PUNCTUATION_TYPE)
+ && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE)
+ list.p[i-1]->spacing_type = ORDINARY_TYPE;
+ }
+ for (i = 0; i < list.len; i++) {
+ unsigned flags = 0;
+ if (i - 1 >= 0 && list.p[i - 1]->right_is_italic())
+ flags |= HINT_PREV_IS_ITALIC;
+ if (i + 1 < list.len && list.p[i + 1]->left_is_italic())
+ flags |= HINT_NEXT_IS_ITALIC;
+ if (flags)
+ list.p[i]->hint(flags);
+ }
+ is_script = (style <= SCRIPT_STYLE);
+ int total_spacing = 0;
+ for (i = 1; i < list.len; i++)
+ total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
+ list.p[i]->spacing_type);
+ int res = 0;
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple()) {
+ int r = list.p[i]->compute_metrics(style);
+ if (r) {
+ if (res)
+ error("multiple marks and lineups");
+ else {
+ compute_sublist_width(i);
+ printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n");
+ res = r;
+ }
+ }
+ }
+ printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing);
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple())
+ printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
+ printf("\n");
+ printf(".nr " HEIGHT_FORMAT " 0", uid);
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple())
+ printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid);
+ printf("\n");
+ printf(".nr " DEPTH_FORMAT " 0", uid);
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple())
+ printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid);
+ printf("\n");
+ int have_simple = 0;
+ for (i = 0; i < list.len && !have_simple; i++)
+ have_simple = list.p[i]->is_simple();
+ if (have_simple) {
+ printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid);
+ for (int i = 0; i < list.len; i++)
+ if (list.p[i]->is_simple())
+ list.p[i]->output();
+ printf(DELIMITER_CHAR "\n");
+ printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n",
+ uid, uid);
+ printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n",
+ uid, uid);
+ }
+ return res;
+}
+
+void list_box::compute_sublist_width(int n)
+{
+ int total_spacing = 0;
+ for (int i = 1; i < n + 1 && i < list.len; i++)
+ total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
+ list.p[i]->spacing_type);
+ printf(".nr " TEMP_REG " %dM", total_spacing);
+ for (i = 0; i < n; i++)
+ if (!list.p[i]->is_simple())
+ printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
+ int have_simple = 0;
+ for (i = 0; i < n && !have_simple; i++)
+ have_simple = list.p[i]->is_simple();
+ if (have_simple) {
+ printf("+\\w" DELIMITER_CHAR);
+ for (int i = 0; i < n; i++)
+ if (list.p[i]->is_simple())
+ list.p[i]->output();
+ printf(DELIMITER_CHAR);
+ }
+ printf("\n");
+}
+
+void list_box::compute_subscript_kern()
+{
+ // We can only call compute_subscript_kern if we have called
+ // compute_metrics first.
+ if (list.p[list.len-1]->is_simple())
+ list.p[list.len-1]->compute_metrics(sty);
+ list.p[list.len-1]->compute_subscript_kern();
+ printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n",
+ uid, list.p[list.len-1]->uid);
+}
+
+void list_box::output()
+{
+ for (int i = 0; i < list.len; i++) {
+ if (i > 0) {
+ int n = compute_spacing(is_script,
+ list.p[i-1]->spacing_type,
+ list.p[i]->spacing_type);
+ if (n > 0)
+ printf("\\h'%dM'", n);
+ }
+ list.p[i]->output();
+ }
+}
+
+void list_box::handle_char_type(int st, int ft)
+{
+ for (int i = 0; i < list.len; i++)
+ list.p[i]->handle_char_type(st, ft);
+}
+
+void list_box::debug_print()
+{
+ list.list_debug_print(" ");
+}
+
+void list_box::check_tabs(int level)
+{
+ list.list_check_tabs(level);
+}
diff --git a/gnu/usr.bin/groff/eqn/main.cc b/gnu/usr.bin/groff/eqn/main.cc
new file mode 100644
index 000000000000..cfc25f2368df
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/main.cc
@@ -0,0 +1,352 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "stringclass.h"
+#include "device.h"
+#include "searchpath.h"
+#include "macropath.h"
+
+#define STARTUP_FILE "eqnrc"
+
+extern int yyparse();
+
+static char *delim_search(char *, int);
+static int inline_equation(FILE *, string &, string &);
+
+char start_delim = '\0';
+char end_delim = '\0';
+int non_empty_flag;
+int inline_flag;
+int draw_flag = 0;
+int one_size_reduction_flag = 0;
+int compatible_flag = 0;
+int no_newline_in_delim_flag = 0;
+
+int read_line(FILE *fp, string *p)
+{
+ p->clear();
+ int c = -1;
+ while ((c = getc(fp)) != EOF) {
+ if (!illegal_input_char(c))
+ *p += char(c);
+ else
+ error("illegal input character code `%1'", c);
+ if (c == '\n')
+ break;
+ }
+ current_lineno++;
+ return p->length() > 0;
+}
+
+void do_file(FILE *fp, const char *filename)
+{
+ string linebuf;
+ string str;
+ printf(".lf 1 %s\n", filename);
+ current_filename = filename;
+ current_lineno = 0;
+ while (read_line(fp, &linebuf)) {
+ if (linebuf.length() >= 4
+ && linebuf[0] == '.' && linebuf[1] == 'l' && linebuf[2] == 'f'
+ && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) {
+ put_string(linebuf, stdout);
+ linebuf += '\0';
+ if (interpret_lf_args(linebuf.contents() + 3))
+ current_lineno--;
+ }
+ else if (linebuf.length() >= 4
+ && linebuf[0] == '.'
+ && linebuf[1] == 'E'
+ && linebuf[2] == 'Q'
+ && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) {
+ put_string(linebuf, stdout);
+ int start_lineno = current_lineno + 1;
+ str.clear();
+ for (;;) {
+ if (!read_line(fp, &linebuf))
+ fatal("end of file before .EN");
+ if (linebuf.length() >= 3 && linebuf[0] == '.' && linebuf[1] == 'E') {
+ if (linebuf[2] == 'N'
+ && (linebuf.length() == 3 || linebuf[3] == ' '
+ || linebuf[3] == '\n' || compatible_flag))
+ break;
+ else if (linebuf[2] == 'Q' && linebuf.length() > 3
+ && (linebuf[3] == ' ' || linebuf[3] == '\n'
+ || compatible_flag))
+ fatal("nested .EQ");
+ }
+ str += linebuf;
+ }
+ str += '\0';
+ start_string();
+ init_lex(str.contents(), current_filename, start_lineno);
+ non_empty_flag = 0;
+ inline_flag = 0;
+ yyparse();
+ if (non_empty_flag) {
+ printf(".lf %d\n", current_lineno - 1);
+ output_string();
+ }
+ restore_compatibility();
+ printf(".lf %d\n", current_lineno);
+ put_string(linebuf, stdout);
+ }
+ else if (start_delim != '\0' && linebuf.search(start_delim) >= 0
+ && inline_equation(fp, linebuf, str))
+ ;
+ else
+ put_string(linebuf, stdout);
+ }
+ current_filename = 0;
+ current_lineno = 0;
+}
+
+/* Handle an inline equation. Return 1 if it was an inline equation,
+0 otherwise. */
+
+static int inline_equation(FILE *fp, string &linebuf, string &str)
+{
+ linebuf += '\0';
+ char *ptr = &linebuf[0];
+ char *start = delim_search(ptr, start_delim);
+ if (!start) {
+ // It wasn't a delimiter after all.
+ linebuf.set_length(linebuf.length() - 1); // strip the '\0'
+ return 0;
+ }
+ start_string();
+ inline_flag = 1;
+ for (;;) {
+ if (no_newline_in_delim_flag && strchr(start + 1, end_delim) == 0) {
+ error("missing `%1'", end_delim);
+ char *nl = strchr(start + 1, '\n');
+ if (nl != 0)
+ *nl = '\0';
+ do_text(ptr);
+ break;
+ }
+ int start_lineno = current_lineno;
+ *start = '\0';
+ do_text(ptr);
+ ptr = start + 1;
+ str.clear();
+ for (;;) {
+ char *end = strchr(ptr, end_delim);
+ if (end != 0) {
+ *end = '\0';
+ str += ptr;
+ ptr = end + 1;
+ break;
+ }
+ str += ptr;
+ if (!read_line(fp, &linebuf))
+ fatal("end of file before `%1'", end_delim);
+ linebuf += '\0';
+ ptr = &linebuf[0];
+ }
+ str += '\0';
+ init_lex(str.contents(), current_filename, start_lineno);
+ yyparse();
+ start = delim_search(ptr, start_delim);
+ if (start == 0) {
+ char *nl = strchr(ptr, '\n');
+ if (nl != 0)
+ *nl = '\0';
+ do_text(ptr);
+ break;
+ }
+ }
+ printf(".lf %d\n", current_lineno);
+ output_string();
+ restore_compatibility();
+ printf(".lf %d\n", current_lineno + 1);
+ return 1;
+}
+
+/* Search for delim. Skip over number register and string names etc. */
+
+static char *delim_search(char *ptr, int delim)
+{
+ while (*ptr) {
+ if (*ptr == delim)
+ return ptr;
+ if (*ptr++ == '\\') {
+ switch (*ptr) {
+ case 'n':
+ case '*':
+ case 'f':
+ case 'g':
+ case 'k':
+ switch (*++ptr) {
+ case '\0':
+ case '\\':
+ break;
+ case '(':
+ if (*++ptr != '\\' && *ptr != '\0' && *++ptr != '\\' && *ptr != '\0')
+ ptr++;
+ break;
+ case '[':
+ while (*++ptr != '\0')
+ if (*ptr == ']') {
+ ptr++;
+ break;
+ }
+ break;
+ default:
+ ptr++;
+ break;
+ }
+ break;
+ case '\\':
+ case '\0':
+ break;
+ default:
+ ptr++;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+void usage()
+{
+ fprintf(stderr,
+ "usage: %s [ -rvDCNR ] -dxx -fn -sn -pn -mn -Mdir -Ts [ files ... ]\n",
+ program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ int load_startup_file = 1;
+ while ((opt = getopt(argc, argv, "DCRvd:f:p:s:m:T:M:rN")) != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'R': // don't load eqnchar
+ load_startup_file = 0;
+ break;
+ case 'M':
+ macro_path.command_line_dir(optarg);
+ break;
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU eqn version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'd':
+ if (optarg[0] == '\0' || optarg[1] == '\0')
+ error("-d requires two character argument");
+ else if (illegal_input_char(optarg[0]))
+ error("bad delimiter `%1'", optarg[0]);
+ else if (illegal_input_char(optarg[1]))
+ error("bad delimiter `%1'", optarg[1]);
+ else {
+ start_delim = optarg[0];
+ end_delim = optarg[1];
+ }
+ break;
+ case 'f':
+ set_gfont(optarg);
+ break;
+ case 'T':
+ device = optarg;
+ break;
+ case 's':
+ if (!set_gsize(optarg))
+ error("invalid size `%1'", optarg);
+ break;
+ case 'p':
+ {
+ int n;
+ if (sscanf(optarg, "%d", &n) == 1)
+ set_script_reduction(n);
+ else
+ error("bad size `%1'", optarg);
+ }
+ break;
+ case 'm':
+ {
+ int n;
+ if (sscanf(optarg, "%d", &n) == 1)
+ set_minimum_size(n);
+ else
+ error("bad size `%1'", optarg);
+ }
+ break;
+ case 'r':
+ one_size_reduction_flag = 1;
+ break;
+ case 'D':
+ warning("-D option is obsolete: use `set draw_lines 1' instead");
+ draw_flag = 1;
+ break;
+ case 'N':
+ no_newline_in_delim_flag = 1;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ init_table(device);
+ init_char_table();
+ printf(".if !'\\*(.T'%s' "
+ ".tm warning: %s should have been given a `-T\\*(.T' option\n",
+ device, program_name);
+ if (load_startup_file) {
+ char *path;
+ FILE *fp = macro_path.open_file(STARTUP_FILE, &path);
+ if (fp) {
+ do_file(fp, path);
+ fclose(fp);
+ a_delete path;
+ }
+ }
+ if (optind >= argc)
+ do_file(stdin, "-");
+ else
+ for (int i = optind; i < argc; i++)
+ if (strcmp(argv[i], "-") == 0)
+ do_file(stdin, "-");
+ else {
+ errno = 0;
+ FILE *fp = fopen(argv[i], "r");
+ if (!fp)
+ fatal("can't open `%1': %2", argv[i], strerror(errno));
+ else {
+ do_file(fp, argv[i]);
+ fclose(fp);
+ }
+ }
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ exit(0);
+}
diff --git a/gnu/usr.bin/groff/eqn/mark.cc b/gnu/usr.bin/groff/eqn/mark.cc
new file mode 100644
index 000000000000..fa5916d3d1e2
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/mark.cc
@@ -0,0 +1,121 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class mark_box : public pointer_box {
+public:
+ mark_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+// we push down marks so that they don't interfere with spacing
+
+box *make_mark_box(box *p)
+{
+ list_box *b = p->to_list_box();
+ if (b != 0) {
+ b->list.p[0] = make_mark_box(b->list.p[0]);
+ return b;
+ }
+ else
+ return new mark_box(p);
+}
+
+mark_box::mark_box(box *pp) : pointer_box(pp)
+{
+}
+
+void mark_box::output()
+{
+ p->output();
+}
+
+int mark_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ if (res)
+ error("multiple marks and lineups");
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " MARK_REG " 0\n");
+ return FOUND_MARK;
+}
+
+void mark_box::debug_print()
+{
+ fprintf(stderr, "mark { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+
+class lineup_box : public pointer_box {
+public:
+ lineup_box(box *);
+ void output();
+ int compute_metrics(int style);
+ void debug_print();
+};
+
+// we push down lineups so that they don't interfere with spacing
+
+box *make_lineup_box(box *p)
+{
+ list_box *b = p->to_list_box();
+ if (b != 0) {
+ b->list.p[0] = make_lineup_box(b->list.p[0]);
+ return b;
+ }
+ else
+ return new lineup_box(p);
+}
+
+lineup_box::lineup_box(box *pp) : pointer_box(pp)
+{
+}
+
+void lineup_box::output()
+{
+ p->output();
+}
+
+int lineup_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ if (res)
+ error("multiple marks and lineups");
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " MARK_REG " 0\n");
+ return FOUND_LINEUP;
+}
+
+void lineup_box::debug_print()
+{
+ fprintf(stderr, "lineup { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
diff --git a/gnu/usr.bin/groff/eqn/neqn.sh b/gnu/usr.bin/groff/eqn/neqn.sh
new file mode 100644
index 000000000000..770376732b29
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/neqn.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Provision of this shell script should not be taken to imply that use of
+# GNU eqn with groff -Tascii|-Tlatin1 is supported.
+
+exec @g@eqn -Tascii ${1+"$@"}
diff --git a/gnu/usr.bin/groff/eqn/other.cc b/gnu/usr.bin/groff/eqn/other.cc
new file mode 100644
index 000000000000..5b8b9c269964
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/other.cc
@@ -0,0 +1,601 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class accent_box : public pointer_box {
+private:
+ box *ab;
+public:
+ accent_box(box *, box *);
+ ~accent_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+box *make_accent_box(box *p, box *q)
+{
+ return new accent_box(p, q);
+}
+
+accent_box::accent_box(box *pp, box *qq) : ab(qq), pointer_box(pp)
+{
+}
+
+accent_box::~accent_box()
+{
+ delete ab;
+}
+
+#if 0
+int accent_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ p->compute_skew();
+ ab->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
+ uid, p->uid, x_height);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
+ SUP_RAISE_FORMAT "]\n",
+ uid, ab->uid, uid);
+ return r;
+}
+
+void accent_box::output()
+{
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
+ SKEW_FORMAT "]u'",
+ p->uid, ab->uid, p->uid);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ ab->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid);
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
+ SKEW_FORMAT "]u)'",
+ p->uid, ab->uid, p->uid);
+ p->output();
+}
+#endif
+
+/* This version copes with the possibility of an accent's being wider
+than its accentee. LEFT_WIDTH_FORMAT gives the distance from the
+left edge of the resulting box to the middle of the accentee's box.*/
+
+int accent_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ p->compute_skew();
+ ab->compute_metrics(style);
+ printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2-\\n[" SKEW_FORMAT "])\n",
+ uid, p->uid, ab->uid, p->uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2+\\n[" SKEW_FORMAT "])"
+ "+\\n[" LEFT_WIDTH_FORMAT "]\n",
+ uid, p->uid, ab->uid, p->uid, uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
+ uid, p->uid, x_height);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
+ SUP_RAISE_FORMAT "]\n",
+ uid, ab->uid, uid);
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
+ "-(\\n[" WIDTH_FORMAT "]/2)'\n",
+ uid, p->uid);
+ return r;
+}
+
+void accent_box::output()
+{
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u"
+ "-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid, ab->uid);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ ab->output();
+ printf(DELIMITER_CHAR);
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void accent_box::check_tabs(int level)
+{
+ ab->check_tabs(level + 1);
+ p->check_tabs(level + 1);
+}
+
+void accent_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } accent { ");
+ ab->debug_print();
+ fprintf(stderr, " }");
+}
+
+class overline_char_box : public simple_box {
+public:
+ overline_char_box();
+ void output();
+ void debug_print();
+};
+
+overline_char_box::overline_char_box()
+{
+}
+
+void overline_char_box::output()
+{
+ printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height);
+ printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
+ accent_width);
+ printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height);
+}
+
+void overline_char_box::debug_print()
+{
+ fprintf(stderr, "<overline char>");
+}
+
+class overline_box : public pointer_box {
+public:
+ overline_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+box *make_overline_box(box *p)
+{
+ if (p->is_char())
+ return new accent_box(p, new overline_char_box);
+ else
+ return new overline_box(p);
+}
+
+overline_box::overline_box(box *pp) : pointer_box(pp)
+{
+}
+
+int overline_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(cramped_style(style));
+ // 9
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n",
+ uid, p->uid, default_rule_thickness*5);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void overline_box::output()
+{
+ // 9
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'",
+ p->uid, 7*default_rule_thickness);
+ if (draw_flag)
+ printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
+ else
+ printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
+ printf(DELIMITER_CHAR);
+ p->output();
+}
+
+void overline_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } bar");
+}
+
+class uaccent_box : public pointer_box {
+ box *ab;
+public:
+ uaccent_box(box *, box *);
+ ~uaccent_box();
+ int compute_metrics(int);
+ void output();
+ void compute_subscript_kern();
+ void check_tabs(int);
+ void debug_print();
+};
+
+box *make_uaccent_box(box *p, box *q)
+{
+ return new uaccent_box(p, q);
+}
+
+uaccent_box::uaccent_box(box *pp, box *qq)
+: pointer_box(pp), ab(qq)
+{
+}
+
+uaccent_box::~uaccent_box()
+{
+ delete ab;
+}
+
+int uaccent_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ ab->compute_metrics(style);
+ printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2)\n",
+ uid, p->uid, ab->uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2)"
+ "+\\n[" LEFT_WIDTH_FORMAT "]\n",
+ uid, p->uid, ab->uid, uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ "+\\n[" DEPTH_FORMAT "]\n",
+ uid, p->uid, ab->uid);
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
+ "-(\\n[" WIDTH_FORMAT "]/2)'\n",
+ uid, p->uid);
+ return r;
+}
+
+void uaccent_box::output()
+{
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, ab->uid);
+ printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid);
+ ab->output();
+ printf(DELIMITER_CHAR);
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void uaccent_box::check_tabs(int level)
+{
+ ab->check_tabs(level + 1);
+ p->check_tabs(level + 1);
+}
+
+void uaccent_box::compute_subscript_kern()
+{
+ box::compute_subscript_kern(); // want 0 subscript kern
+}
+
+void uaccent_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } uaccent { ");
+ ab->debug_print();
+ fprintf(stderr, " }");
+}
+
+class underline_char_box : public simple_box {
+public:
+ underline_char_box();
+ void output();
+ void debug_print();
+};
+
+underline_char_box::underline_char_box()
+{
+}
+
+void underline_char_box::output()
+{
+ printf("\\v'%dM/2u'", 7*default_rule_thickness);
+ printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
+ accent_width);
+ printf("\\v'-%dM/2u'", 7*default_rule_thickness);
+}
+
+void underline_char_box::debug_print()
+{
+ fprintf(stderr, "<underline char>");
+}
+
+
+class underline_box : public pointer_box {
+public:
+ underline_box(box *);
+ int compute_metrics(int);
+ void output();
+ void compute_subscript_kern();
+ void debug_print();
+};
+
+box *make_underline_box(box *p)
+{
+ if (p->is_char())
+ return new uaccent_box(p, new underline_char_box);
+ else
+ return new underline_box(p);
+}
+
+underline_box::underline_box(box *pp) : pointer_box(pp)
+{
+}
+
+int underline_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ // 10
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
+ uid, p->uid, default_rule_thickness*5);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void underline_box::output()
+{
+ // 10
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'",
+ p->uid, 7*default_rule_thickness);
+ if (draw_flag)
+ printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
+ else
+ printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
+ printf(DELIMITER_CHAR);
+ p->output();
+}
+
+// we want an underline box to have 0 subscript kern
+
+void underline_box::compute_subscript_kern()
+{
+ box::compute_subscript_kern();
+}
+
+void underline_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } under");
+}
+
+size_box::size_box(char *s, box *pp) : size(s), pointer_box(pp)
+{
+}
+
+int size_box::compute_metrics(int style)
+{
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".ps %s\n", size);
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ int r = p->compute_metrics(style);
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void size_box::output()
+{
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ p->output();
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+}
+
+size_box::~size_box()
+{
+ a_delete size;
+}
+
+void size_box::debug_print()
+{
+ fprintf(stderr, "size %s { ", size);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+
+font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s)
+{
+}
+
+font_box::~font_box()
+{
+ a_delete f;
+}
+
+int font_box::compute_metrics(int style)
+{
+ const char *old_roman_font = current_roman_font;
+ current_roman_font = f;
+ printf(".nr " FONT_FORMAT " \\n[.f]\n", uid);
+ printf(".ft %s\n", f);
+ int r = p->compute_metrics(style);
+ current_roman_font = old_roman_font;
+ printf(".ft \\n[" FONT_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void font_box::output()
+{
+ printf("\\f[%s]", f);
+ const char *old_roman_font = current_roman_font;
+ current_roman_font = f;
+ p->output();
+ current_roman_font = old_roman_font;
+ printf("\\f[\\n[" FONT_FORMAT "]]", uid);
+}
+
+void font_box::debug_print()
+{
+ fprintf(stderr, "font %s { ", f);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+fat_box::fat_box(box *pp) : pointer_box(pp)
+{
+}
+
+int fat_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
+ uid, p->uid, fat_offset);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void fat_box::output()
+{
+ p->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid);
+ printf("\\h'%dM'", fat_offset);
+ p->output();
+}
+
+
+void fat_box::debug_print()
+{
+ fprintf(stderr, "fat { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+
+vmotion_box::vmotion_box(int i, box *pp) : n(i), pointer_box(pp)
+{
+}
+
+int vmotion_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ if (n > 0) {
+ printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n",
+ uid, n, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ }
+ else {
+ printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n",
+ uid, -n, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n",
+ uid, p->uid);
+ }
+ return r;
+}
+
+void vmotion_box::output()
+{
+ printf("\\v'%dM'", -n);
+ p->output();
+ printf("\\v'%dM'", n);
+}
+
+void vmotion_box::debug_print()
+{
+ if (n >= 0)
+ fprintf(stderr, "up %d { ", n);
+ else
+ fprintf(stderr, "down %d { ", -n);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+hmotion_box::hmotion_box(int i, box *pp) : n(i), pointer_box(pp)
+{
+}
+
+int hmotion_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
+ uid, p->uid, n);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ if (r)
+ printf(".nr " MARK_REG " +%dM\n", n);
+ return r;
+}
+
+void hmotion_box::output()
+{
+ printf("\\h'%dM'", n);
+ p->output();
+}
+
+void hmotion_box::debug_print()
+{
+ if (n >= 0)
+ fprintf(stderr, "fwd %d { ", n);
+ else
+ fprintf(stderr, "back %d { ", -n);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+vcenter_box::vcenter_box(box *pp) : pointer_box(pp)
+{
+}
+
+int vcenter_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
+ HEIGHT_FORMAT "]/2+%dM\n",
+ uid, p->uid, p->uid, axis_height);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
+ SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
+ SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
+
+ return r;
+}
+
+void vcenter_box::output()
+{
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ p->output();
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+}
+
+void vcenter_box::debug_print()
+{
+ fprintf(stderr, "vcenter { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
diff --git a/gnu/usr.bin/groff/eqn/over.cc b/gnu/usr.bin/groff/eqn/over.cc
new file mode 100644
index 000000000000..5ea0121eb04f
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/over.cc
@@ -0,0 +1,196 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class over_box : public box {
+private:
+ int reduce_size;
+ box *num;
+ box *den;
+public:
+ over_box(int small, box *, box *);
+ ~over_box();
+ void debug_print();
+ int compute_metrics(int);
+ void output();
+ void check_tabs(int);
+};
+
+box *make_over_box(box *pp, box *qq)
+{
+ return new over_box(0, pp, qq);
+}
+
+box *make_small_over_box(box *pp, box *qq)
+{
+ return new over_box(1, pp, qq);
+}
+
+over_box::over_box(int is_small, box *pp, box *qq)
+: num(pp), den(qq), reduce_size(is_small)
+{
+ spacing_type = INNER_TYPE;
+}
+
+over_box::~over_box()
+{
+ delete num;
+ delete den;
+}
+
+int over_box::compute_metrics(int style)
+{
+ if (reduce_size) {
+ style = script_style(style);
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ set_script_size();
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ }
+ int mark_uid;
+ int res = num->compute_metrics(style);
+ if (res)
+ mark_uid = num->uid;
+ int r = den->compute_metrics(cramped_style(style));
+ if (r && res)
+ error("multiple marks and lineups");
+ else {
+ mark_uid = den->uid;
+ res = r;
+ }
+ if (reduce_size)
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
+ uid, num->uid, den->uid);
+ // allow for \(ru being wider than both the numerator and denominator
+ if (!draw_flag)
+ fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
+ printf(")+%dM\n", null_delimiter_space*2 + over_hang*2);
+ // 15b
+ printf(".nr " SUP_RAISE_FORMAT " %dM\n",
+ uid, (reduce_size ? num2 : num1));
+ printf(".nr " SUB_LOWER_FORMAT " %dM\n",
+ uid, (reduce_size ? denom2 : denom1));
+
+ // 15d
+ printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
+ "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
+ uid, num->uid, uid, axis_height, default_rule_thickness,
+ default_rule_thickness*(reduce_size ? 1 : 3));
+ printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
+ "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
+ uid, den->uid, uid, axis_height, default_rule_thickness,
+ default_rule_thickness*(reduce_size ? 1 : 3));
+
+
+ printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
+ HEIGHT_FORMAT "]\n",
+ uid, uid, num->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
+ DEPTH_FORMAT "]\n",
+ uid, uid, den->uid);
+ if (res)
+ printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n["
+ WIDTH_FORMAT "]/2)\n", uid, mark_uid);
+ return res;
+}
+
+#define USE_Z
+
+void over_box::output()
+{
+ if (reduce_size)
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+#ifdef USE_Z
+ printf("\\Z" DELIMITER_CHAR);
+#endif
+ // move up to the numerator baseline
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ // move across so that it's centered
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, num->uid);
+
+ // print the numerator
+ num->output();
+
+#ifdef USE_Z
+ printf(DELIMITER_CHAR);
+#else
+ // back again
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid);
+ printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, num->uid);
+ // down again
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+#endif
+#ifdef USE_Z
+ printf("\\Z" DELIMITER_CHAR);
+#endif
+ // move down to the denominator baseline
+ printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
+
+ // move across so that it's centered
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, den->uid);
+
+ // print the the denominator
+ den->output();
+
+#ifdef USE_Z
+ printf(DELIMITER_CHAR);
+#else
+ // back again
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid);
+ printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, den->uid);
+ // up again
+ printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
+#endif
+ if (reduce_size)
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ // draw the line
+ printf("\\h'%dM'", null_delimiter_space);
+ printf("\\v'-%dM'", axis_height);
+ fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
+ printf("\\n[" WIDTH_FORMAT "]u-%dM",
+ uid, 2*null_delimiter_space);
+ fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
+ printf("\\v'%dM'", axis_height);
+ printf("\\h'%dM'", null_delimiter_space);
+}
+
+void over_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ num->debug_print();
+ if (reduce_size)
+ fprintf(stderr, " } smallover { ");
+ else
+ fprintf(stderr, " } over { ");
+ den->debug_print();
+ fprintf(stderr, " }");
+}
+
+void over_box::check_tabs(int level)
+{
+ num->check_tabs(level + 1);
+ den->check_tabs(level + 1);
+}
diff --git a/gnu/usr.bin/groff/eqn/pbox.h b/gnu/usr.bin/groff/eqn/pbox.h
new file mode 100644
index 000000000000..adee780cf978
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/pbox.h
@@ -0,0 +1,141 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern int fat_offset;
+
+extern int over_hang;
+extern int accent_width;
+
+extern int delimiter_factor;
+extern int delimiter_shortfall;
+
+extern int null_delimiter_space;
+extern int script_space;
+extern int thin_space;
+extern int medium_space;
+extern int thick_space;
+
+extern int num1;
+extern int num2;
+// we don't use num3, because we don't have \atop
+extern int denom1;
+extern int denom2;
+extern int axis_height;
+extern int sup1;
+extern int sup2;
+extern int sup3;
+extern int default_rule_thickness;
+extern int sub1;
+extern int sub2;
+extern int sup_drop;
+extern int sub_drop;
+extern int x_height;
+extern int big_op_spacing1;
+extern int big_op_spacing2;
+extern int big_op_spacing3;
+extern int big_op_spacing4;
+extern int big_op_spacing5;
+
+extern int baseline_sep;
+extern int shift_down;
+extern int column_sep;
+extern int matrix_side_sep;
+
+// ms.eqn relies on this!
+
+#define LINE_STRING "10"
+#define MARK_OR_LINEUP_FLAG_REG "MK"
+
+#define WIDTH_FORMAT PREFIX "w%d"
+#define HEIGHT_FORMAT PREFIX "h%d"
+#define DEPTH_FORMAT PREFIX "d%d"
+#define TOTAL_FORMAT PREFIX "t%d"
+#define SIZE_FORMAT PREFIX "z%d"
+#define SMALL_SIZE_FORMAT PREFIX "Z%d"
+#define SUP_RAISE_FORMAT PREFIX "p%d"
+#define SUB_LOWER_FORMAT PREFIX "b%d"
+#define SUB_KERN_FORMAT PREFIX "k%d"
+#define FONT_FORMAT PREFIX "f%d"
+#define SKEW_FORMAT PREFIX "s%d"
+#define LEFT_WIDTH_FORMAT PREFIX "lw%d"
+#define LEFT_DELIM_STRING_FORMAT PREFIX "l%d"
+#define RIGHT_DELIM_STRING_FORMAT PREFIX "r%d"
+#define SQRT_STRING_FORMAT PREFIX "sqr%d"
+#define SQRT_WIDTH_FORMAT PREFIX "sq%d"
+#define BASELINE_SEP_FORMAT PREFIX "bs%d"
+// this needs two parameters, the uid and the column index
+#define COLUMN_WIDTH_FORMAT PREFIX "cw%d,%d"
+
+#define BAR_STRING PREFIX "sqb"
+#define TEMP_REG PREFIX "temp"
+#define MARK_REG PREFIX "mark"
+#define MARK_WIDTH_REG PREFIX "mwidth"
+#define SAVED_MARK_REG PREFIX "smark"
+#define MAX_SIZE_REG PREFIX "mxsz"
+#define REPEAT_APPEND_STRING_MACRO PREFIX "ras"
+#define TOP_HEIGHT_REG PREFIX "th"
+#define TOP_DEPTH_REG PREFIX "td"
+#define MID_HEIGHT_REG PREFIX "mh"
+#define MID_DEPTH_REG PREFIX "md"
+#define BOT_HEIGHT_REG PREFIX "bh"
+#define BOT_DEPTH_REG PREFIX "bd"
+#define EXT_HEIGHT_REG PREFIX "eh"
+#define EXT_DEPTH_REG PREFIX "ed"
+#define TOTAL_HEIGHT_REG PREFIX "tot"
+#define DELTA_REG PREFIX "delta"
+#define DELIM_STRING PREFIX "delim"
+#define DELIM_WIDTH_REG PREFIX "dwidth"
+#define SAVED_FONT_REG PREFIX "sfont"
+#define SAVED_PREV_FONT_REG PREFIX "spfont"
+#define SAVED_INLINE_FONT_REG PREFIX "sifont"
+#define SAVED_INLINE_PREV_FONT_REG PREFIX "sipfont"
+#define SAVED_SIZE_REG PREFIX "ssize"
+#define SAVED_INLINE_SIZE_REG PREFIX "sisize"
+#define SAVED_INLINE_PREV_SIZE_REG PREFIX "sipsize"
+#define SAVE_FONT_STRING PREFIX "sfont"
+#define RESTORE_FONT_STRING PREFIX "rfont"
+#define INDEX_REG PREFIX "i"
+#define TEMP_MACRO PREFIX "tempmac"
+
+#define DELIMITER_CHAR "\\(EQ"
+
+const int CRAMPED_SCRIPT_STYLE = 0;
+const int SCRIPT_STYLE = 1;
+const int CRAMPED_DISPLAY_STYLE = 2;
+const int DISPLAY_STYLE = 3;
+
+extern int script_style(int);
+extern int cramped_style(int);
+
+const int ORDINARY_TYPE = 0;
+const int OPERATOR_TYPE = 1;
+const int BINARY_TYPE = 2;
+const int RELATION_TYPE = 3;
+const int OPENING_TYPE = 4;
+const int CLOSING_TYPE = 5;
+const int PUNCTUATION_TYPE = 6;
+const int INNER_TYPE = 7;
+const int SUPPRESS_TYPE = 8;
+
+void set_script_size();
+
+enum { HINT_PREV_IS_ITALIC = 01, HINT_NEXT_IS_ITALIC = 02 };
+
+extern const char *current_roman_font;
diff --git a/gnu/usr.bin/groff/eqn/pile.cc b/gnu/usr.bin/groff/eqn/pile.cc
new file mode 100644
index 000000000000..9aa43068ce25
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/pile.cc
@@ -0,0 +1,293 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+// piles and matrices
+
+#include "eqn.h"
+#include "pbox.h"
+
+// SUP_RAISE_FORMAT gives the first baseline
+// BASELINE_SEP_FORMAT gives the separation between baselines
+
+int pile_box::compute_metrics(int style)
+{
+ int i;
+ for (i = 0; i < col.len; i++)
+ col.p[i]->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0", uid);
+ for (i = 0; i < col.len; i++)
+ printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
+ printf("\n");
+ printf(".nr " BASELINE_SEP_FORMAT " %dM",
+ uid, baseline_sep+col.space);
+ for (i = 1; i < col.len; i++)
+ printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
+ col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
+ // round it so that it's a multiple of the vertical resolution
+ printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
+
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
+ "+%dM\n",
+ uid, uid, col.len-1, axis_height - shift_down);
+ printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
+ HEIGHT_FORMAT "]\n",
+ uid, uid, col.p[0]->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
+ DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
+ uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
+ return FOUND_NOTHING;
+}
+
+void pile_box::output()
+{
+ int i;
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ for (i = 0; i < col.len; i++) {
+ switch (col.align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, col.p[i]->uid);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ uid, col.p[i]->uid);
+ break;
+ default:
+ assert(0);
+ }
+ col.p[i]->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
+ switch (col.align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ col.p[i]->uid, uid);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ col.p[i]->uid, uid);
+ break;
+ default:
+ assert(0);
+ }
+ if (i != col.len - 1)
+ printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
+ }
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+pile_box::pile_box(box *pp) : col(pp)
+{
+}
+
+void pile_box::check_tabs(int level)
+{
+ col.list_check_tabs(level);
+}
+
+void pile_box::debug_print()
+{
+ col.debug_print("pile");
+}
+
+int matrix_box::compute_metrics(int style)
+{
+ int i, j;
+ int maxlen = 0;
+ int space = 0;
+ for (i = 0; i < len; i++) {
+ for (j = 0; j < p[i]->len; j++)
+ p[i]->p[j]->compute_metrics(style);
+ if (p[i]->len > maxlen)
+ maxlen = p[i]->len;
+ if (p[i]->space > space)
+ space = p[i]->space;
+ }
+ for (i = 0; i < len; i++) {
+ printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
+ for (j = 0; j < p[i]->len; j++)
+ printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
+ printf("\n");
+ }
+ printf(".nr " WIDTH_FORMAT " %dM",
+ uid, column_sep*(len-1)+2*matrix_side_sep);
+ for (i = 0; i < len; i++)
+ printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
+ printf("\n");
+ printf(".nr " BASELINE_SEP_FORMAT " %dM",
+ uid, baseline_sep+space);
+ for (i = 0; i < len; i++)
+ for (j = 1; j < p[i]->len; j++)
+ printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
+ p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
+ // round it so that it's a multiple of the vertical resolution
+ printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
+ "+%dM\n",
+ uid, uid, maxlen-1, axis_height - shift_down);
+ printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
+ uid, uid);
+ for (i = 0; i < len; i++)
+ printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
+ printf(")>?0\n");
+ printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
+ SUP_RAISE_FORMAT "]+(0",
+ uid, uid, maxlen-1, uid);
+ for (i = 0; i < len; i++)
+ if (p[i]->len == maxlen)
+ printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[maxlen-1]->uid);
+ printf(")>?0\n");
+ return FOUND_NOTHING;
+}
+
+void matrix_box::output()
+{
+ printf("\\h'%dM'", matrix_side_sep);
+ for (int i = 0; i < len; i++) {
+ int j;
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ for (j = 0; j < p[i]->len; j++) {
+ switch (p[i]->align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, i, p[i]->p[j]->uid);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ uid, i, p[i]->p[j]->uid);
+ break;
+ default:
+ assert(0);
+ }
+ p[i]->p[j]->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
+ switch (p[i]->align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
+ p[i]->p[j]->uid, uid, i);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
+ p[i]->p[j]->uid, uid, i);
+ break;
+ default:
+ assert(0);
+ }
+ if (j != p[i]->len - 1)
+ printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
+ }
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
+ printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
+ if (i != len - 1)
+ printf("\\h'%dM'", column_sep);
+ }
+ printf("\\h'%dM'", matrix_side_sep);
+}
+
+matrix_box::matrix_box(column *pp)
+{
+ p = new column*[10];
+ for (int i = 0; i < 10; i++)
+ p[i] = 0;
+ maxlen = 10;
+ len = 1;
+ p[0] = pp;
+}
+
+matrix_box::~matrix_box()
+{
+ for (int i = 0; i < len; i++)
+ delete p[i];
+ a_delete p;
+}
+
+void matrix_box::append(column *pp)
+{
+ if (len + 1 > maxlen) {
+ column **oldp = p;
+ maxlen *= 2;
+ p = new column*[maxlen];
+ memcpy(p, oldp, sizeof(column*)*len);
+ a_delete oldp;
+ }
+ p[len++] = pp;
+}
+
+void matrix_box::check_tabs(int level)
+{
+ for (int i = 0; i < len; i++)
+ p[i]->list_check_tabs(level);
+}
+
+void matrix_box::debug_print()
+{
+ fprintf(stderr, "matrix { ");
+ p[0]->debug_print("col");
+ for (int i = 1; i < len; i++) {
+ fprintf(stderr, " ");
+ p[i]->debug_print("col");
+ }
+ fprintf(stderr, " }");
+}
+
+column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
+{
+}
+
+void column::set_alignment(alignment a)
+{
+ align = a;
+}
+
+void column::set_space(int n)
+{
+ space = n;
+}
+
+void column::debug_print(const char *s)
+{
+ char c = '\0'; // shut up -Wall
+ switch (align) {
+ case LEFT_ALIGN:
+ c = 'l';
+ break;
+ case RIGHT_ALIGN:
+ c = 'r';
+ break;
+ case CENTER_ALIGN:
+ c = 'c';
+ break;
+ default:
+ assert(0);
+ }
+ fprintf(stderr, "%c%s %d { ", c, s, space);
+ list_debug_print(" above ");
+ fprintf(stderr, " }");
+}
+
diff --git a/gnu/usr.bin/groff/eqn/script.cc b/gnu/usr.bin/groff/eqn/script.cc
new file mode 100644
index 000000000000..3ee83ba52f51
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/script.cc
@@ -0,0 +1,221 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class script_box : public pointer_box {
+private:
+ box *sub;
+ box *sup;
+public:
+ script_box(box *, box *, box *);
+ ~script_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ int left_is_italic();
+ void hint(unsigned);
+ void check_tabs(int);
+};
+
+/* The idea is that the script should attach to the rightmost box
+of a list. For example, given `2x sup 3', the superscript should
+attach to `x' rather than `2x'. */
+
+box *make_script_box(box *nuc, box *sub, box *sup)
+{
+ list_box *b = nuc->to_list_box();
+ if (b != 0) {
+ b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
+ sub,
+ sup);
+ return b;
+ }
+ else
+ return new script_box(nuc, sub, sup);
+}
+
+script_box::script_box(box *pp, box *qq, box *rr)
+: pointer_box(pp), sub(qq), sup(rr)
+{
+}
+
+script_box::~script_box()
+{
+ delete sub;
+ delete sup;
+}
+
+int script_box::left_is_italic()
+{
+ return p->left_is_italic();
+}
+
+int script_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ p->compute_subscript_kern();
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
+ set_script_size();
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ if (sub != 0)
+ sub->compute_metrics(cramped_style(script_style(style)));
+ if (sup != 0)
+ sup->compute_metrics(script_style(style));
+ // 18a
+ if (p->is_char()) {
+ printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
+ printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
+ }
+ else {
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
+ uid, p->uid, sup_drop);
+ printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
+ uid, p->uid, sub_drop);
+ }
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ if (sup == 0) {
+ assert(sub != 0);
+ // 18b
+ printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
+ HEIGHT_FORMAT "]-(%dM*4/5))\n",
+ uid, uid, sub1, sub->uid, x_height);
+ }
+ else {
+ // sup != 0
+ // 18c
+ int p;
+ if (style == DISPLAY_STYLE)
+ p = sup1;
+ else if (style & 1) // not cramped
+ p = sup2;
+ else
+ p = sup3;
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
+ "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
+ uid, uid, p, sup->uid, x_height);
+ // 18d
+ if (sub != 0) {
+ printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
+ uid, uid, sub2);
+ // 18e
+ printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
+ SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
+ SUB_LOWER_FORMAT "]+(4*%dM)\n",
+ sup->uid, uid, sub->uid, uid, default_rule_thickness);
+ printf(".if \\n[" TEMP_REG "] \\{");
+ printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
+ printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
+ "]+\\n[" DEPTH_FORMAT "]>?0\n",
+ x_height, uid, sup->uid);
+ printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
+ printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
+ printf(".\\}\n");
+ }
+ }
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
+ if (sub != 0 && sup != 0)
+ printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
+ WIDTH_FORMAT "])+%dM)>?0\n",
+ sub->uid, p->uid, sup->uid, script_space);
+ else if (sub != 0)
+ printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
+ sub->uid, p->uid, script_space);
+ else if (sup != 0)
+ printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
+ else
+ printf("\n");
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
+ uid, p->uid);
+ if (sup != 0)
+ printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
+ uid, sup->uid);
+ if (sub != 0)
+ printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
+ uid, sub->uid);
+ printf("\n");
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
+ uid, p->uid);
+ if (sub != 0)
+ printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
+ uid, sub->uid);
+ if (sup != 0)
+ printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
+ uid, sup->uid);
+ printf("\n");
+ return res;
+}
+
+void script_box::output()
+{
+ p->output();
+ if (sup != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ sup->output();
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf(DELIMITER_CHAR);
+ }
+ if (sub != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
+ sub->output();
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf(DELIMITER_CHAR);
+ }
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ uid, p->uid);
+}
+
+void script_box::hint(unsigned flags)
+{
+ p->hint(flags & ~HINT_NEXT_IS_ITALIC);
+}
+
+void script_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " }");
+ if (sub) {
+ fprintf(stderr, " sub { ");
+ sub->debug_print();
+ fprintf(stderr, " }");
+ }
+ if (sup) {
+ fprintf(stderr, " sup { ");
+ sup->debug_print();
+ fprintf(stderr, " }");
+ }
+}
+
+void script_box::check_tabs(int level)
+{
+ if (sup)
+ sup->check_tabs(level + 1);
+ if (sub)
+ sub->check_tabs(level + 1);
+ p->check_tabs(level);
+}
diff --git a/gnu/usr.bin/groff/eqn/special.cc b/gnu/usr.bin/groff/eqn/special.cc
new file mode 100644
index 000000000000..be7354365542
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/special.cc
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+#define STRING_FORMAT PREFIX "str%d"
+
+#define SPECIAL_STRING "0s"
+#define SPECIAL_WIDTH_REG "0w"
+#define SPECIAL_HEIGHT_REG "0h"
+#define SPECIAL_DEPTH_REG "0d"
+#define SPECIAL_SUB_KERN_REG "0skern"
+#define SPECIAL_SKEW_REG "0skew"
+
+/*
+For example:
+
+.de Cl
+.ds 0s \Z'\\*[0s]'\v'\\n(0du'\D'l \\n(0wu -\\n(0hu-\\n(0du'\v'\\n(0hu'
+..
+.EQ
+define cancel 'special Cl'
+.EN
+*/
+
+
+class special_box : public pointer_box {
+ char *macro_name;
+public:
+ special_box(char *, box *);
+ ~special_box();
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void compute_skew();
+ void output();
+ void debug_print();
+};
+
+box *make_special_box(char *s, box *p)
+{
+ return new special_box(s, p);
+}
+
+special_box::special_box(char *s, box *pp) :macro_name(s), pointer_box(pp)
+{
+}
+
+special_box::~special_box()
+{
+ a_delete macro_name;
+}
+
+int special_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ p->compute_subscript_kern();
+ p->compute_skew();
+ printf(".ds " SPECIAL_STRING " \"");
+ p->output();
+ printf("\n");
+ printf(".nr " SPECIAL_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_HEIGHT_REG " \\n[" HEIGHT_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_DEPTH_REG " \\n[" DEPTH_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_SUB_KERN_REG " \\n[" SUB_KERN_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_SKEW_REG " 0\\n[" SKEW_FORMAT "]\n", p->uid);
+ printf(".%s\n", macro_name);
+ printf(".rn " SPECIAL_STRING " " STRING_FORMAT "\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" SPECIAL_WIDTH_REG "]\n", uid);
+ printf(".nr " HEIGHT_FORMAT " 0>?\\n[" SPECIAL_HEIGHT_REG "]\n", uid);
+ printf(".nr " DEPTH_FORMAT " 0>?\\n[" SPECIAL_DEPTH_REG "]\n", uid);
+ printf(".nr " SUB_KERN_FORMAT " 0>?\\n[" SPECIAL_SUB_KERN_REG "]\n", uid);
+ printf(".nr " SKEW_FORMAT " 0\\n[" SPECIAL_SKEW_REG "]\n", uid);
+ // User will have to change MARK_REG if appropriate.
+ return r;
+}
+
+void special_box::compute_subscript_kern()
+{
+ // Already computed in compute_metrics(), so do nothing.
+}
+
+void special_box::compute_skew()
+{
+ // Already computed in compute_metrics(), so do nothing.
+}
+
+void special_box::output()
+{
+ printf("\\*[" STRING_FORMAT "]", uid);
+}
+
+void special_box::debug_print()
+{
+ fprintf(stderr, "special %s { ", macro_name);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
diff --git a/gnu/usr.bin/groff/eqn/sqrt.cc b/gnu/usr.bin/groff/eqn/sqrt.cc
new file mode 100644
index 000000000000..5ec05a098621
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/sqrt.cc
@@ -0,0 +1,179 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+
+class sqrt_box : public pointer_box {
+public:
+ sqrt_box(box *);
+ int compute_metrics(int style);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+box *make_sqrt_box(box *pp)
+{
+ return new sqrt_box(pp);
+}
+
+sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
+{
+}
+
+#define SQRT_CHAR "\\(sr"
+#define RADICAL_EXTENSION_CHAR "\\(rn"
+
+#define SQRT_CHAIN "\\[sr\\\\n[" INDEX_REG "]]"
+#define BAR_CHAIN "\\[rn\\\\n[" INDEX_REG "]]"
+
+int sqrt_box::compute_metrics(int style)
+{
+ // 11
+ int r = p->compute_metrics(cramped_style(style));
+ printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
+ "]+%dM+(%dM/4)\n",
+ p->uid, p->uid, default_rule_thickness,
+ (style > SCRIPT_STYLE ? x_height : default_rule_thickness));
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
+ printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
+ printf(".nr " SQRT_WIDTH_FORMAT
+ " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
+ uid);
+ printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
+ default_rule_thickness);
+
+ printf(".nr " INDEX_REG " 0\n"
+ ".de " TEMP_MACRO "\n"
+ ".ie c" SQRT_CHAIN " \\{"
+ ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
+ ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
+ ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
+ ".nr " SQRT_WIDTH_FORMAT
+ " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
+ ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
+ ".nr " INDEX_REG " +1\n"
+ "." TEMP_MACRO "\n"
+ ".\\}\\}\n"
+ ".el .nr " INDEX_REG " 0-1\n"
+ "..\n"
+ "." TEMP_MACRO "\n",
+ uid, uid, default_rule_thickness);
+
+ printf(".if \\n[" INDEX_REG "]<0 \\{");
+
+ // Determine the maximum point size
+ printf(".ps 1000\n");
+ printf(".nr " MAX_SIZE_REG " \\n[.s]\n");
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ // We define a macro that will increase the current point size
+ // until we get a radical sign that's tall enough or we reach
+ // the maximum point size.
+ printf(".de " TEMP_MACRO "\n"
+ ".nr " SQRT_WIDTH_FORMAT
+ " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
+ ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "]"
+ "&(\\\\n[.s]<\\n[" MAX_SIZE_REG "]) \\{"
+ ".ps +1\n"
+ "." TEMP_MACRO "\n"
+ ".\\}\n"
+ "..\n"
+ "." TEMP_MACRO "\n",
+ uid, uid, default_rule_thickness);
+
+ printf(".\\}\\}\n");
+
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ // set TEMP_REG to the amount by which the radical sign is too big
+ printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
+ default_rule_thickness);
+ // If TEMP_REG is negative, the bottom of the radical sign should
+ // be -TEMP_REG above the bottom of p. If it's positive, the bottom
+ // of the radical sign should be TEMP_REG/2 below the bottom of p.
+ // This calculates the amount by which the baseline of the radical
+ // should be raised.
+ printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
+ "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
+ uid, p->uid, uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
+ uid, p->uid, uid);
+ // Do this last, so we don't lose height and depth information on
+ // the radical sign.
+ // Remember that the width of the bar might be greater than the width of p.
+
+ printf(".nr " TEMP_REG " "
+ "\\n[" WIDTH_FORMAT "]"
+ ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
+ p->uid);
+ printf(".as " SQRT_STRING_FORMAT " "
+ "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
+ uid);
+ printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
+ "+\\n[" SQRT_WIDTH_FORMAT "]\n",
+ uid, uid);
+
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
+ // the top of the bar might be higher than the top of the radical sign
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
+ uid, p->uid, uid);
+ // put a bit of extra space above the bar
+ printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ return r;
+}
+
+void sqrt_box::output()
+{
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\*[" SQRT_STRING_FORMAT "]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf(DELIMITER_CHAR);
+
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
+ "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
+ uid, p->uid, uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void sqrt_box::debug_print()
+{
+ fprintf(stderr, "sqrt { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+void sqrt_box::check_tabs(int level)
+{
+ p->check_tabs(level + 1);
+}
diff --git a/gnu/usr.bin/groff/eqn/text.cc b/gnu/usr.bin/groff/eqn/text.cc
new file mode 100644
index 000000000000..ee6618f8c273
--- /dev/null
+++ b/gnu/usr.bin/groff/eqn/text.cc
@@ -0,0 +1,528 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+#include "ptable.h"
+
+class char_box : public simple_box {
+ unsigned char c;
+ char next_is_italic;
+ char prev_is_italic;
+public:
+ char_box(unsigned char);
+ void debug_print();
+ void output();
+ int is_char();
+ int left_is_italic();
+ int right_is_italic();
+ void hint(unsigned);
+ void handle_char_type(int, int);
+};
+
+class special_char_box : public simple_box {
+ char *s;
+public:
+ special_char_box(const char *);
+ ~special_char_box();
+ void output();
+ void debug_print();
+ int is_char();
+ void handle_char_type(int, int);
+};
+
+const char *spacing_type_table[] = {
+ "ordinary",
+ "operator",
+ "binary",
+ "relation",
+ "opening",
+ "closing",
+ "punctuation",
+ "inner",
+ "suppress",
+ 0,
+};
+
+const int DIGIT_TYPE = 0;
+const int LETTER_TYPE = 1;
+
+const char *font_type_table[] = {
+ "digit",
+ "letter",
+ 0,
+};
+
+struct char_info {
+ int spacing_type;
+ int font_type;
+ char_info();
+};
+
+char_info::char_info()
+: spacing_type(ORDINARY_TYPE), font_type(DIGIT_TYPE)
+{
+}
+
+static char_info char_table[256];
+
+declare_ptable(char_info)
+implement_ptable(char_info)
+
+PTABLE(char_info) special_char_table;
+
+static int get_special_char_spacing_type(const char *ch)
+{
+ char_info *p = special_char_table.lookup(ch);
+ return p ? p->spacing_type : ORDINARY_TYPE;
+}
+
+static int get_special_char_font_type(const char *ch)
+{
+ char_info *p = special_char_table.lookup(ch);
+ return p ? p->font_type : DIGIT_TYPE;
+}
+
+static void set_special_char_type(const char *ch, int st, int ft)
+{
+ char_info *p = special_char_table.lookup(ch);
+ if (!p) {
+ p = new char_info;
+ special_char_table.define(ch, p);
+ }
+ if (st >= 0)
+ p->spacing_type = st;
+ if (ft >= 0)
+ p->font_type = ft;
+}
+
+void init_char_table()
+{
+ set_special_char_type("pl", 2, -1); // binary
+ set_special_char_type("mi", 2, -1);
+ set_special_char_type("eq", 3, -1); // relation
+ set_special_char_type("<=", 3, -1);
+ set_special_char_type(">=", 3, -1);
+ char_table['}'].spacing_type = 5; // closing
+ char_table[')'].spacing_type = 5;
+ char_table[']'].spacing_type = 5;
+ char_table['{'].spacing_type = 4; // opening
+ char_table['('].spacing_type = 4;
+ char_table['['].spacing_type = 4;
+ char_table[','].spacing_type = 6; // punctuation
+ char_table[';'].spacing_type = 6;
+ char_table[':'].spacing_type = 6;
+ char_table['.'].spacing_type = 6;
+ char_table['>'].spacing_type = 3;
+ char_table['<'].spacing_type = 3;
+ char_table['*'].spacing_type = 2; // binary
+ for (int i = 0; i < 256; i++)
+ if (csalpha(i))
+ char_table[i].font_type = LETTER_TYPE;
+}
+
+static int lookup_spacing_type(const char *type)
+{
+ for (int i = 0; spacing_type_table[i] != 0; i++)
+ if (strcmp(spacing_type_table[i], type) == 0)
+ return i;
+ return -1;
+}
+
+static int lookup_font_type(const char *type)
+{
+ for (int i = 0; font_type_table[i] != 0; i++)
+ if (strcmp(font_type_table[i], type) == 0)
+ return i;
+ return -1;
+}
+
+void box::set_spacing_type(char *type)
+{
+ int t = lookup_spacing_type(type);
+ if (t < 0)
+ error("unrecognised type `%1'", type);
+ else
+ spacing_type = t;
+ a_delete type;
+}
+
+char_box::char_box(unsigned char cc)
+: c(cc), prev_is_italic(0), next_is_italic(0)
+{
+ spacing_type = char_table[c].spacing_type;
+}
+
+void char_box::hint(unsigned flags)
+{
+ if (flags & HINT_PREV_IS_ITALIC)
+ prev_is_italic = 1;
+ if (flags & HINT_NEXT_IS_ITALIC)
+ next_is_italic = 1;
+}
+
+void char_box::output()
+{
+ int font_type = char_table[c].font_type;
+ if (font_type != LETTER_TYPE)
+ printf("\\f[%s]", current_roman_font);
+ if (!prev_is_italic)
+ fputs("\\,", stdout);
+ if (c == '\\')
+ fputs("\\e", stdout);
+ else
+ putchar(c);
+ if (!next_is_italic)
+ fputs("\\/", stdout);
+ else
+ fputs("\\&", stdout); // suppress ligaturing and kerning
+ if (font_type != LETTER_TYPE)
+ fputs("\\fP", stdout);
+}
+
+int char_box::left_is_italic()
+{
+ int font_type = char_table[c].font_type;
+ return font_type == LETTER_TYPE;
+}
+
+int char_box::right_is_italic()
+{
+ int font_type = char_table[c].font_type;
+ return font_type == LETTER_TYPE;
+}
+
+int char_box::is_char()
+{
+ return 1;
+}
+
+void char_box::debug_print()
+{
+ if (c == '\\') {
+ putc('\\', stderr);
+ putc('\\', stderr);
+ }
+ else
+ putc(c, stderr);
+}
+
+special_char_box::special_char_box(const char *t)
+{
+ s = strsave(t);
+ spacing_type = get_special_char_spacing_type(s);
+}
+
+special_char_box::~special_char_box()
+{
+ a_delete s;
+}
+
+void special_char_box::output()
+{
+ int font_type = get_special_char_font_type(s);
+ if (font_type != LETTER_TYPE)
+ printf("\\f[%s]", current_roman_font);
+ printf("\\,\\[%s]\\/", s);
+ if (font_type != LETTER_TYPE)
+ printf("\\fP");
+}
+
+int special_char_box::is_char()
+{
+ return 1;
+}
+
+void special_char_box::debug_print()
+{
+ fprintf(stderr, "\\[%s]", s);
+}
+
+
+void char_box::handle_char_type(int st, int ft)
+{
+ if (st >= 0)
+ char_table[c].spacing_type = st;
+ if (ft >= 0)
+ char_table[c].font_type = ft;
+}
+
+void special_char_box::handle_char_type(int st, int ft)
+{
+ set_special_char_type(s, st, ft);
+}
+
+void set_char_type(const char *type, char *ch)
+{
+ assert(ch != 0);
+ int st = lookup_spacing_type(type);
+ int ft = lookup_font_type(type);
+ if (st < 0 && ft < 0) {
+ error("bad character type `%1'", type);
+ a_delete ch;
+ return;
+ }
+ box *b = split_text(ch);
+ b->handle_char_type(st, ft);
+ delete b;
+}
+
+/* We give primes special treatment so that in ``x' sub 2'', the ``2''
+will be tucked under the prime */
+
+class prime_box : public pointer_box {
+ box *pb;
+public:
+ prime_box(box *);
+ ~prime_box();
+ int compute_metrics(int style);
+ void output();
+ void compute_subscript_kern();
+ void debug_print();
+ void handle_char_type(int, int);
+};
+
+box *make_prime_box(box *pp)
+{
+ return new prime_box(pp);
+}
+
+prime_box::prime_box(box *pp) : pointer_box(pp)
+{
+ pb = new special_char_box("fm");
+}
+
+prime_box::~prime_box()
+{
+ delete pb;
+}
+
+int prime_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ pb->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]"
+ "+\\n[" WIDTH_FORMAT "]\n",
+ uid, p->uid, pb->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?\\n[" HEIGHT_FORMAT "]\n",
+ uid, p->uid, pb->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ ">?\\n[" DEPTH_FORMAT "]\n",
+ uid, p->uid, pb->uid);
+ return res;
+}
+
+void prime_box::compute_subscript_kern()
+{
+ p->compute_subscript_kern();
+ printf(".nr " SUB_KERN_FORMAT " 0\\n[" WIDTH_FORMAT "]"
+ "+\\n[" SUB_KERN_FORMAT "]>?0\n",
+ uid, pb->uid, p->uid);
+}
+
+void prime_box::output()
+{
+ p->output();
+ pb->output();
+}
+
+void prime_box::handle_char_type(int st, int ft)
+{
+ p->handle_char_type(st, ft);
+ pb->handle_char_type(st, ft);
+}
+
+void prime_box::debug_print()
+{
+ p->debug_print();
+ putc('\'', stderr);
+}
+
+box *split_text(char *text)
+{
+ list_box *lb = 0;
+ box *fb = 0;
+ char *s = text;
+ while (*s != '\0') {
+ char c = *s++;
+ box *b = 0;
+ switch (c) {
+ case '+':
+ b = new special_char_box("pl");
+ break;
+ case '-':
+ b = new special_char_box("mi");
+ break;
+ case '=':
+ b = new special_char_box("eq");
+ break;
+ case '\'':
+ b = new special_char_box("fm");
+ break;
+ case '<':
+ if (*s == '=') {
+ b = new special_char_box("<=");
+ s++;
+ break;
+ }
+ goto normal_char;
+ case '>':
+ if (*s == '=') {
+ b = new special_char_box(">=");
+ s++;
+ break;
+ }
+ goto normal_char;
+ case '\\':
+ if (*s == '\0') {
+ lex_error("bad escape");
+ break;
+ }
+ c = *s++;
+ switch (c) {
+ case '(':
+ {
+ char buf[3];
+ if (*s != '\0') {
+ buf[0] = *s++;
+ if (*s != '\0') {
+ buf[1] = *s++;
+ buf[2] = '\0';
+ b = new special_char_box(buf);
+ }
+ else {
+ lex_error("bad escape");
+ }
+ }
+ else {
+ lex_error("bad escape");
+ }
+ }
+ break;
+ case '[':
+ {
+ char *ch = s;
+ while (*s != ']' && *s != '\0')
+ s++;
+ if (*s == '\0')
+ lex_error("bad escape");
+ else {
+ *s++ = '\0';
+ b = new special_char_box(ch);
+ }
+ }
+ break;
+ case 'f':
+ case 'g':
+ case 'k':
+ case 'n':
+ case '*':
+ {
+ char *escape_start = s - 2;
+ switch (*s) {
+ case '(':
+ if (*++s != '\0')
+ ++s;
+ break;
+ case '[':
+ for (++s; *s != '\0' && *s != ']'; s++)
+ ;
+ break;
+ }
+ if (*s == '\0')
+ lex_error("bad escape");
+ else {
+ ++s;
+ char *buf = new char[s - escape_start + 1];
+ memcpy(buf, escape_start, s - escape_start);
+ buf[s - escape_start] = '\0';
+ b = new quoted_text_box(buf);
+ }
+ }
+ break;
+ case '-':
+ case '_':
+ {
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ b = new special_char_box(buf);
+ }
+ break;
+ case '`':
+ b = new special_char_box("ga");
+ break;
+ case '\'':
+ b = new special_char_box("aa");
+ break;
+ case 'e':
+ case '\\':
+ b = new char_box('\\');
+ break;
+ case '^':
+ case '|':
+ case '0':
+ {
+ char buf[3];
+ buf[0] = '\\';
+ buf[1] = c;
+ buf[2] = '\0';
+ b = new quoted_text_box(strsave(buf));
+ break;
+ }
+ default:
+ lex_error("unquoted escape");
+ b = new quoted_text_box(strsave(s - 2));
+ s = strchr(s, '\0');
+ break;
+ }
+ break;
+ default:
+ normal_char:
+ b = new char_box(c);
+ break;
+ }
+ while (*s == '\'') {
+ if (b == 0)
+ b = new quoted_text_box(0);
+ b = new prime_box(b);
+ s++;
+ }
+ if (b != 0) {
+ if (lb != 0)
+ lb->append(b);
+ else if (fb != 0) {
+ lb = new list_box(fb);
+ lb->append(b);
+ }
+ else
+ fb = b;
+ }
+ }
+ delete text;
+ if (lb != 0)
+ return lb;
+ else if (fb != 0)
+ return fb;
+ else
+ return new quoted_text_box(0);
+}
+
diff --git a/gnu/usr.bin/groff/grodvi/Makefile b/gnu/usr.bin/groff/grodvi/Makefile
new file mode 100644
index 000000000000..c9bd46971000
--- /dev/null
+++ b/gnu/usr.bin/groff/grodvi/Makefile
@@ -0,0 +1,12 @@
+# Makefile for grodvi
+
+PROG= grodvi
+SRCS= dvi.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBDRIVER) $(LIBGROFF) -lm
+DPADD+= $(LIBDRIVER) $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/grodvi/dvi.cc b/gnu/usr.bin/groff/grodvi/dvi.cc
new file mode 100644
index 000000000000..c3ae76ee6ca0
--- /dev/null
+++ b/gnu/usr.bin/groff/grodvi/dvi.cc
@@ -0,0 +1,895 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "driver.h"
+
+#define DEFAULT_LINEWIDTH 40
+static int linewidth = DEFAULT_LINEWIDTH;
+
+static int draw_flag = 1;
+
+/* These values were chosen because:
+
+(MULTIPLIER*SIZESCALE)/(RES*UNITWIDTH) == 1/(2^20 * 72.27)
+
+and 57816 is an exact multiple of both 72.27*SIZESCALE and 72.
+
+The width in the groff font file is the product of MULTIPLIER and the
+width in the tfm file. */
+
+#define RES 57816
+#define RES_7227 (RES/7227)
+#define UNITWIDTH 131072
+#define SIZESCALE 100
+#define MULTIPLIER 1
+
+#define FILL_MAX 1000
+
+class dvi_font : public font {
+ dvi_font(const char *);
+public:
+ int checksum;
+ int design_size;
+ ~dvi_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static dvi_font *load_dvi_font(const char *);
+};
+
+dvi_font *dvi_font::load_dvi_font(const char *s)
+{
+ dvi_font *f = new dvi_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+dvi_font::dvi_font(const char *nm)
+: font(nm), checksum(0), design_size(0)
+{
+}
+
+dvi_font::~dvi_font()
+{
+}
+
+void dvi_font::handle_unknown_font_command(const char *command,
+ const char *arg,
+ const char *filename, int lineno)
+{
+ char *ptr;
+ if (strcmp(command, "checksum") == 0) {
+ if (arg == 0)
+ fatal_with_file_and_line(filename, lineno,
+ "`checksum' command requires an argument");
+ checksum = int(strtol(arg, &ptr, 10));
+ if (checksum == 0 && ptr == arg) {
+ fatal_with_file_and_line(filename, lineno, "bad checksum");
+ }
+ }
+ else if (strcmp(command, "designsize") == 0) {
+ if (arg == 0)
+ fatal_with_file_and_line(filename, lineno,
+ "`designsize' command requires an argument");
+ design_size = int(strtol(arg, &ptr, 10));
+ if (design_size == 0 && ptr == arg) {
+ fatal_with_file_and_line(filename, lineno, "bad design size");
+ }
+ }
+}
+
+#define FONTS_MAX 256
+
+struct output_font {
+ dvi_font *f;
+ int point_size;
+ output_font() : f(0) { }
+};
+
+class dvi_printer : public printer {
+ FILE *fp;
+ int max_drift;
+ int byte_count;
+ int last_bop;
+ int page_count;
+ int cur_h;
+ int cur_v;
+ int end_h;
+ int max_h;
+ int max_v;
+ output_font output_font_table[FONTS_MAX];
+ font *cur_font;
+ int cur_point_size;
+ int pushed;
+ int pushed_h;
+ int pushed_v;
+ int have_pushed;
+ void preamble();
+ void postamble();
+ void define_font(int);
+ void set_font(int);
+ void possibly_begin_line();
+protected:
+ enum {
+ id_byte = 2,
+ set1 = 128,
+ put1 = 133,
+ put_rule = 137,
+ bop = 139,
+ eop = 140,
+ push = 141,
+ pop = 142,
+ right1 = 143,
+ down1 = 157,
+ fnt_num_0 = 171,
+ fnt1 = 235,
+ xxx1 = 239,
+ fnt_def1 = 243,
+ pre = 247,
+ post = 248,
+ post_post = 249,
+ filler = 223
+ };
+ int line_thickness;
+
+ void out1(int);
+ void out2(int);
+ void out3(int);
+ void out4(int);
+ void moveto(int, int);
+ void out_string(const char *);
+ void out_signed(unsigned char, int);
+ void out_unsigned(unsigned char, int);
+ void do_special(const char *);
+public:
+ dvi_printer();
+ ~dvi_printer();
+ font *make_font(const char *);
+ void begin_page(int);
+ void end_page(int);
+ void set_char(int, font *, const environment *, int w);
+ void special(char *arg, const environment *env);
+ void end_of_line();
+ void draw(int code, int *p, int np, const environment *env);
+};
+
+
+class draw_dvi_printer : public dvi_printer {
+ int output_pen_size;
+ int fill;
+ void set_line_thickness(const environment *);
+ void fill_next();
+public:
+ draw_dvi_printer();
+ ~draw_dvi_printer();
+ void draw(int code, int *p, int np, const environment *env);
+ void end_page(int);
+};
+
+dvi_printer::dvi_printer()
+: byte_count(0), last_bop(-1), page_count(0), cur_font(0), fp(stdout),
+ max_h(0), max_v(0), pushed(0), line_thickness(-1), cur_point_size(-1)
+{
+ if (font::res != RES)
+ fatal("resolution must be %1", RES);
+ if (font::unitwidth != UNITWIDTH)
+ fatal("unitwidth must be %1", UNITWIDTH);
+ if (font::hor != 1)
+ fatal("hor must be equal to 1");
+ if (font::vert != 1)
+ fatal("vert must be equal to 1");
+ if (font::sizescale != SIZESCALE)
+ fatal("sizescale must be equal to %1", SIZESCALE);
+ max_drift = font::res/1000; // this is fairly arbitrary
+ preamble();
+}
+
+dvi_printer::~dvi_printer()
+{
+ postamble();
+}
+
+
+draw_dvi_printer::draw_dvi_printer()
+: output_pen_size(-1), fill(FILL_MAX)
+{
+}
+
+draw_dvi_printer::~draw_dvi_printer()
+{
+}
+
+
+void dvi_printer::out1(int n)
+{
+ byte_count += 1;
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out2(int n)
+{
+ byte_count += 2;
+ putc((n >> 8) & 0xff, fp);
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out3(int n)
+{
+ byte_count += 3;
+ putc((n >> 16) & 0xff, fp);
+ putc((n >> 8) & 0xff, fp);
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out4(int n)
+{
+ byte_count += 4;
+ putc((n >> 24) & 0xff, fp);
+ putc((n >> 16) & 0xff, fp);
+ putc((n >> 8) & 0xff, fp);
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out_string(const char *s)
+{
+ out1(strlen(s));
+ while (*s != 0)
+ out1(*s++);
+}
+
+
+void dvi_printer::end_of_line()
+{
+ if (pushed) {
+ out1(pop);
+ pushed = 0;
+ cur_h = pushed_h;
+ cur_v = pushed_v;
+ }
+}
+
+void dvi_printer::possibly_begin_line()
+{
+ if (!pushed) {
+ have_pushed = pushed = 1;
+ pushed_h = cur_h;
+ pushed_v = cur_v;
+ out1(push);
+ }
+}
+
+int scale(int x, int z)
+{
+ int sw;
+ int a, b, c, d;
+ int alpha, beta;
+ alpha = 16*z; beta = 16;
+ while (z >= 040000000L) {
+ z /= 2; beta /= 2;
+ }
+ d = x & 255;
+ c = (x >> 8) & 255;
+ b = (x >> 16) & 255;
+ a = (x >> 24) & 255;
+ sw = (((((d * z) / 0400) + (c * z)) / 0400) + (b * z)) / beta;
+ if (a == 255)
+ sw -= alpha;
+ else
+ assert(a == 0);
+ return sw;
+}
+
+
+void dvi_printer::set_char(int index, font *f, const environment *env, int w)
+{
+ int code = f->get_code(index);
+ if (env->size != cur_point_size || f != cur_font) {
+ cur_font = f;
+ cur_point_size = env->size;
+ for (int i = 0;; i++) {
+ if (i >= FONTS_MAX) {
+ fatal("too many output fonts required");
+ }
+ if (output_font_table[i].f == 0) {
+ output_font_table[i].f = (dvi_font *)cur_font;
+ output_font_table[i].point_size = cur_point_size;
+ define_font(i);
+ }
+ if (output_font_table[i].f == cur_font
+ && output_font_table[i].point_size == cur_point_size)
+ break;
+ }
+ set_font(i);
+ }
+ int distance = env->hpos - cur_h;
+ if (env->hpos != end_h && distance != 0) {
+ out_signed(right1, distance);
+ cur_h = env->hpos;
+ }
+ else if (distance > max_drift) {
+ out_signed(right1, distance - max_drift);
+ cur_h = env->hpos - max_drift;
+ }
+ else if (distance < -max_drift) {
+ out_signed(right1, distance + max_drift);
+ cur_h = env->hpos + max_drift;
+ }
+ if (env->vpos != cur_v) {
+ out_signed(down1, env->vpos - cur_v);
+ cur_v = env->vpos;
+ }
+ possibly_begin_line();
+ end_h = env->hpos + w;
+ cur_h += scale(f->get_width(index, UNITWIDTH)/MULTIPLIER,
+ cur_point_size*RES_7227);
+ if (cur_h > max_h)
+ max_h = cur_h;
+ if (cur_v > max_v)
+ max_v = cur_v;
+ if (code >= 0 && code <= 127)
+ out1(code);
+ else
+ out_unsigned(set1, code);
+}
+
+void dvi_printer::define_font(int i)
+{
+ out_unsigned(fnt_def1, i);
+ dvi_font *f = output_font_table[i].f;
+ out4(f->checksum);
+ out4(output_font_table[i].point_size*RES_7227);
+ out4(int((double(f->design_size)/(1<<20))*RES_7227*100 + .5));
+ const char *nm = f->get_internal_name();
+ out1(0);
+ out_string(nm);
+}
+
+void dvi_printer::set_font(int i)
+{
+ if (i >= 0 && i <= 63)
+ out1(fnt_num_0 + i);
+ else
+ out_unsigned(fnt1, i);
+}
+
+void dvi_printer::out_signed(unsigned char base, int param)
+{
+ if (-128 <= param && param < 128) {
+ out1(base);
+ out1(param);
+ }
+ else if (-32768 <= param && param < 32768) {
+ out1(base+1);
+ out2(param);
+ }
+ else if (-(1 << 23) <= param && param < (1 << 23)) {
+ out1(base+2);
+ out3(param);
+ }
+ else {
+ out1(base+3);
+ out4(param);
+ }
+}
+
+void dvi_printer::out_unsigned(unsigned char base, int param)
+{
+ if (param >= 0) {
+ if (param < 256) {
+ out1(base);
+ out1(param);
+ }
+ else if (param < 65536) {
+ out1(base+1);
+ out2(param);
+ }
+ else if (param < (1 << 24)) {
+ out1(base+2);
+ out3(param);
+ }
+ else {
+ out1(base+3);
+ out4(param);
+ }
+ }
+ else {
+ out1(base+3);
+ out4(param);
+ }
+}
+
+void dvi_printer::preamble()
+{
+ out1(pre);
+ out1(id_byte);
+ out4(254000);
+ out4(font::res);
+ out4(1000);
+ out1(0);
+}
+
+void dvi_printer::postamble()
+{
+ int tem = byte_count;
+ out1(post);
+ out4(last_bop);
+ out4(254000);
+ out4(font::res);
+ out4(1000);
+ out4(max_v);
+ out4(max_h);
+ out2(have_pushed); // stack depth
+ out2(page_count);
+ int i;
+ for (i = 0; i < FONTS_MAX && output_font_table[i].f != 0; i++)
+ define_font(i);
+ out1(post_post);
+ out4(tem);
+ out1(id_byte);
+ for (i = 0; i < 4 || byte_count % 4 != 0; i++)
+ out1(filler);
+}
+
+void dvi_printer::begin_page(int i)
+{
+ page_count++;
+ int tem = byte_count;
+ out1(bop);
+ out4(i);
+ for (int j = 1; j < 10; j++)
+ out4(0);
+ out4(last_bop);
+ last_bop = tem;
+ // By convention position (0,0) in a dvi file is placed at (1in, 1in).
+ cur_h = font::res;
+ cur_v = font::res;
+ end_h = 0;
+}
+
+void dvi_printer::end_page(int)
+{
+ if (pushed)
+ end_of_line();
+ out1(eop);
+ cur_font = 0;
+}
+
+void draw_dvi_printer::end_page(int len)
+{
+ dvi_printer::end_page(len);
+ output_pen_size = -1;
+}
+
+void dvi_printer::do_special(const char *s)
+{
+ int len = strlen(s);
+ if (len == 0)
+ return;
+ possibly_begin_line();
+ out_unsigned(xxx1, len);
+ while (*s)
+ out1(*s++);
+}
+
+void dvi_printer::special(char *arg, const environment *env)
+{
+ moveto(env->hpos, env->vpos);
+ do_special(arg);
+}
+
+void dvi_printer::moveto(int h, int v)
+{
+ if (h != cur_h) {
+ out_signed(right1, h - cur_h);
+ cur_h = h;
+ if (cur_h > max_h)
+ max_h = cur_h;
+ }
+ if (v != cur_v) {
+ out_signed(down1, v - cur_v);
+ cur_v = v;
+ if (cur_v > max_v)
+ max_v = cur_v;
+ }
+ end_h = 0;
+}
+
+void dvi_printer::draw(int code, int *p, int np, const environment *env)
+{
+ if (code == 'l') {
+ int x, y;
+ int height = 0, width;
+ int thickness;
+ if (line_thickness < 0)
+ thickness = env->size*RES_7227*linewidth/1000;
+ else if (line_thickness > 0)
+ thickness = line_thickness;
+ else
+ thickness = 1;
+ if (np != 2) {
+ error("2 arguments required for line");
+ }
+ else if (p[0] == 0) {
+ // vertical rule
+ if (p[1] > 0) {
+ x = env->hpos - thickness/2;
+ y = env->vpos + p[1] + thickness/2;
+ height = p[1] + thickness;
+ width = thickness;
+ }
+ else if (p[1] < 0) {
+ x = env->hpos - thickness/2;
+ y = env->vpos + thickness/2;
+ height = thickness - p[1];
+ width = thickness;
+ }
+ }
+ else if (p[1] == 0) {
+ if (p[0] > 0) {
+ x = env->hpos - thickness/2;
+ y = env->vpos + thickness/2;
+ height = thickness;
+ width = p[0] + thickness;
+ }
+ else if (p[0] < 0) {
+ x = env->hpos - p[0] - thickness/2;
+ y = env->vpos + thickness/2;
+ height = thickness;
+ width = thickness - p[0];
+ }
+ }
+ if (height != 0) {
+ moveto(x, y);
+ out1(put_rule);
+ out4(height);
+ out4(width);
+ }
+ }
+ else if (code == 't') {
+ if (np == 0) {
+ line_thickness = -1;
+ }
+ else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2)
+ error("0 or 1 argument required for thickness");
+ else
+ line_thickness = p[0];
+ }
+ }
+ else if (code == 'R') {
+ if (np != 2)
+ error("2 arguments required for rule");
+ else if (p[0] != 0 || p[1] != 0) {
+ int dh = p[0];
+ int dv = p[1];
+ int oh = env->hpos;
+ int ov = env->vpos;
+ if (dv > 0) {
+ ov += dv;
+ dv = -dv;
+ }
+ if (dh < 0) {
+ oh += dh;
+ dh = -dh;
+ }
+ moveto(oh, ov);
+ out1(put_rule);
+ out4(-dv);
+ out4(dh);
+ }
+ }
+}
+
+// XXX Will this overflow?
+
+inline int milliinches(int n)
+{
+ return (n*1000 + font::res/2)/font::res;
+}
+
+void draw_dvi_printer::set_line_thickness(const environment *env)
+{
+ int desired_pen_size
+ = milliinches(line_thickness < 0
+ // Will this overflow?
+ ? env->size*RES_7227*linewidth/1000
+ : line_thickness);
+ if (desired_pen_size != output_pen_size) {
+ char buf[256];
+ sprintf(buf, "pn %d", desired_pen_size);
+ do_special(buf);
+ output_pen_size = desired_pen_size;
+ }
+}
+
+void draw_dvi_printer::fill_next()
+{
+ char buf[256];
+ sprintf(buf, "sh %.3f", double(fill)/FILL_MAX);
+ do_special(buf);
+}
+
+void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
+{
+ char buf[1024];
+ int fill_flag = 0;
+ switch (code) {
+ case 'C':
+ fill_flag = 1;
+ // fall through
+ case 'c':
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ moveto(env->hpos+p[0]/2, env->vpos);
+ if (fill_flag)
+ fill_next();
+ else
+ set_line_thickness(env);
+ int rad;
+ rad = milliinches(p[0]/2);
+ sprintf(buf, "%s 0 0 %d %d 0 6.28319",
+ (fill_flag ? "ia" : "ar"),
+ rad,
+ rad);
+ do_special(buf);
+ break;
+ case 'l':
+ if (np != 2) {
+ error("2 arguments required for line");
+ break;
+ }
+ moveto(env->hpos, env->vpos);
+ set_line_thickness(env);
+ do_special("pa 0 0");
+ sprintf(buf, "pa %d %d", milliinches(p[0]), milliinches(p[1]));
+ do_special(buf);
+ do_special("fp");
+ break;
+ case 'E':
+ fill_flag = 1;
+ // fall through
+ case 'e':
+ if (np != 2) {
+ error("2 arguments required for ellipse");
+ break;
+ }
+ moveto(env->hpos+p[0]/2, env->vpos);
+ if (fill_flag)
+ fill_next();
+ sprintf(buf, "%s 0 0 %d %d 0 6.28319",
+ (fill_flag ? "ia" : "ar"),
+ milliinches(p[0]/2),
+ milliinches(p[1]/2));
+ do_special(buf);
+ break;
+ case 'P':
+ fill_flag = 1;
+ // fall through
+ case 'p':
+ {
+ if (np & 1) {
+ error("even number of arguments required for polygon");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for polygon");
+ break;
+ }
+ moveto(env->hpos, env->vpos);
+ if (fill_flag)
+ fill_next();
+ else
+ set_line_thickness(env);
+ do_special("pa 0 0");
+ int h = 0, v = 0;
+ for (int i = 0; i < np; i += 2) {
+ h += p[i];
+ v += p[i+1];
+ sprintf(buf, "pa %d %d", milliinches(h), milliinches(v));
+ do_special(buf);
+ }
+ do_special("pa 0 0");
+ do_special(fill_flag ? "ip" : "fp");
+ break;
+ }
+ case '~':
+ {
+ if (np & 1) {
+ error("even number of arguments required for spline");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for spline");
+ break;
+ }
+ moveto(env->hpos, env->vpos);
+ set_line_thickness(env);
+ do_special("pa 0 0");
+ int h = 0, v = 0;
+ for (int i = 0; i < np; i += 2) {
+ h += p[i];
+ v += p[i+1];
+ sprintf(buf, "pa %d %d", milliinches(h), milliinches(v));
+ do_special(buf);
+ }
+ do_special("sp");
+ break;
+ }
+ case 'a':
+ {
+ if (np != 4) {
+ error("4 arguments required for arc");
+ break;
+ }
+ set_line_thickness(env);
+ double c[2];
+ if (adjust_arc_center(p, c)) {
+ int rad = milliinches(int(sqrt(c[0]*c[0] + c[1]*c[1]) + .5));
+ moveto(env->hpos + int(c[0]), env->vpos + int(c[1]));
+ sprintf(buf, "ar 0 0 %d %d %f %f",
+ rad,
+ rad,
+ atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]),
+ atan2(-c[1], -c[0]));
+ do_special(buf);
+ }
+ else {
+ moveto(env->hpos, env->vpos);
+ do_special("pa 0 0");
+ sprintf(buf,
+ "pa %d %d",
+ milliinches(p[0] + p[2]),
+ milliinches(p[1] + p[3]));
+ do_special(buf);
+ do_special("fp");
+ }
+ break;
+ }
+ case 't':
+ {
+ if (np == 0) {
+ line_thickness = -1;
+ }
+ else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2) {
+ error("0 or 1 argument required for thickness");
+ break;
+ }
+ line_thickness = p[0];
+ }
+ break;
+ }
+ case 'f':
+ {
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ }
+ fill = p[0];
+ if (fill < 0 || fill > FILL_MAX)
+ fill = FILL_MAX;
+ break;
+ }
+ case 'R':
+ {
+ if (np != 2) {
+ error("2 arguments required for rule");
+ break;
+ }
+ int dh = p[0];
+ if (dh == 0)
+ break;
+ int dv = p[1];
+ if (dv == 0)
+ break;
+ int oh = env->hpos;
+ int ov = env->vpos;
+ if (dv > 0) {
+ ov += dv;
+ dv = -dv;
+ }
+ if (dh < 0) {
+ oh += dh;
+ dh = -dh;
+ }
+ moveto(oh, ov);
+ out1(put_rule);
+ out4(-dv);
+ out4(dh);
+ break;
+ }
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+}
+
+font *dvi_printer::make_font(const char *nm)
+{
+ return dvi_font::load_dvi_font(nm);
+}
+
+printer *make_printer()
+{
+ if (draw_flag)
+ return new draw_dvi_printer;
+ else
+ return new dvi_printer;
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:vw:d")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "grodvi version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'w':
+ if (sscanf(optarg, "%d", &linewidth) != 1
+ || linewidth < 0 || linewidth > 1000) {
+ error("bad line width");
+ linewidth = DEFAULT_LINEWIDTH;
+ }
+ break;
+ case 'd':
+ draw_flag = 0;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ exit(0);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-dv] [-F dir] [-w n] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/gnu/usr.bin/groff/grodvi/grodvi.1 b/gnu/usr.bin/groff/grodvi/grodvi.1
new file mode 100644
index 000000000000..e2fbd2d423de
--- /dev/null
+++ b/gnu/usr.bin/groff/grodvi/grodvi.1
@@ -0,0 +1,154 @@
+.\" -*- nroff -*-
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GRODVI 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+grodvi \- convert groff output to TeX dvi format
+.SH SYNOPSIS
+.B grodvi
+[
+.B \-dv
+] [
+.BI \-w n
+] [
+.BI \-F dir
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grodvi
+is a driver for
+.B groff
+that produces \*(tx dvi format.
+Normally it should be run by
+.BR groff\ \-Tdvi .
+This will run
+.BR troff\ \-Tdvi ;
+it will also input the macros
+.BR /usr/share/tmac/tmac.dvi ;
+if the input is being preprocessed with
+.B eqn
+it will also input
+.BR /usr/share/groff_font/devdvi/eqnchar .
+.LP
+The dvi file generated by
+.B grodvi
+can be printed by any correctly-written dvi driver.
+The troff drawing primitives are implemented
+using the tpic version 2 specials.
+If the driver does not support these, the
+.B \eD
+commands will not produce any output.
+.LP
+There is an additional drawing command available:
+.TP
+.BI \eD'R\ dh\ dv '
+Draw a rule (solid black rectangle), with one corner
+at the current position, and the diagonally opposite corner
+at the current position
+.RI +( dh , dv ).
+Afterwards the current position will be at the opposite corner. This
+produces a rule in the dvi file and so can be printed even with a
+driver that does not support the tpic specials unlike the other
+.B \eD
+commands.
+.LP
+The groff command
+.BI \eX' anything '
+is translated into the same command in the dvi file as would be
+produced by
+.BI \especial{ anything }
+in \*(tx;
+.I anything may not contain a newline.
+.LP
+Font files for
+.B grodvi
+can be created from tfm files using
+.BR tfmtodit (1).
+The font description file should contain the following
+additional commands:
+.Tp \w'\fBinternalname'u+2n
+.BI internalname\ name
+The name of the tfm file (without the
+.B .tfm
+extension) is
+.IR name .
+.TP
+.BI checksum\ n
+The checksum in the tfm file is
+.IR n .
+.TP
+.BI designsize\ n
+The designsize in the tfm file is
+.IR n .
+.LP
+These are automatically generated by
+.B tfmtodit.
+.LP
+In
+.B troff
+the
+.B \eN
+escape sequence can be used to access characters by their position
+in the corresponding tfm file;
+all characters in the tfm file can be accessed this way.
+.SH OPTIONS
+.TP
+.B \-d
+Do not use tpic specials to implement drawing commands.
+Horizontal and vertical lines will be implemented by rules.
+Other drawing commands will be ignored.
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-w n
+Set the default line thickness to
+.I n
+thousandths of an em.
+.TP
+.BI \-F dir
+Search directory
+.IB dir /devdvi
+for font and device description files.
+.SH FILES
+.TP
+.B /usr/share/groff_font/devdvi/DESC
+Device desciption file.
+.TP
+.B /usr/share/groff_font/devdvi/ F
+Font description file for font
+.IR F .
+.TP
+.B /usr/share/tmac/tmac.dvi
+Macros for use with
+.BR grodvi .
+.SH BUGS
+Dvi files produced by
+.B grodvi
+use a different resolution (57816 units per inch) to those produced by
+\*(tx.
+Incorrectly written drivers which assume the resolution used by \*(tx,
+rather than using the resolution specified in the dvi file will not
+work with grodvi.
+.LP
+When using the
+.B \-d
+option with boxed tables,
+vertical and horizontal lines can sometimes protrude by one pixel.
+This is a consequence of the way \*(tx requires that the heights
+and widths of rules be rounded.
+.SH "SEE ALSO"
+.BR tfmtodit (1),
+.BR groff (1),
+.BR troff (1),
+.BR eqn (1),
+.BR groff_out (5),
+.BR groff_font (5),
+.BR groff_char (7)
diff --git a/gnu/usr.bin/groff/groff/Makefile b/gnu/usr.bin/groff/groff/Makefile
new file mode 100644
index 000000000000..0dd3aa8d670d
--- /dev/null
+++ b/gnu/usr.bin/groff/groff/Makefile
@@ -0,0 +1,12 @@
+# Makefile for groff
+
+PROG= groff
+SRCS= groff.cc pipeline.c
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF) -lm
+DPADD+= $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/groff/groff.1 b/gnu/usr.bin/groff/groff/groff.1
new file mode 100644
index 000000000000..8a63a9669a06
--- /dev/null
+++ b/gnu/usr.bin/groff/groff/groff.1
@@ -0,0 +1,362 @@
+.\" -*- nroff -*-
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROFF 1 "29 October 1992" "Groff Version 1.08"
+.SH NAME
+groff \- front end for the groff document formatting system
+.SH SYNOPSIS
+.B groff
+[
+.B \-tpeszaivhblCENRVXZ
+]
+[
+.BI \-w name
+]
+[
+.BI \-W name
+]
+[
+.BI \-m name
+]
+[
+.BI \-F dir
+]
+[
+.BI \-T dev
+]
+[
+.BI \-f fam
+]
+[
+.BI \-M dir
+]
+[
+.BI \-d cs
+]
+[
+.BI \-r cn
+]
+[
+.BI \-n num
+]
+[
+.BI \-o list
+]
+[
+.BI \-P arg
+]
+[
+.IR files \|.\|.\|.\|
+]
+.SH DESCRIPTION
+.B groff
+is a front-end to the groff document formatting system.
+Normally it runs the
+.B troff
+program and a postprocessor appropriate for the selected
+device.
+Available devices are:
+.TP
+.B ps
+For PostScript printers and previewers
+.TP
+.B dvi
+For TeX dvi format
+.TP
+.B X75
+For a 75 dpi X11 previewer
+.TP
+.B X100
+For a 100dpi X11 previewer
+.TP
+.B ascii
+For typewriter-like devices
+.TP
+.B latin1
+For typewriter-like devices using the ISO Latin-1 character set.
+.LP
+The postprocessor to be used for a device is specified by the
+.B postpro
+command in the device description file.
+This can be overridden with the
+.B \-X
+option.
+.LP
+The default device is
+.BR ps .
+It can optionally preprocess with any of
+.BR pic ,
+.BR eqn ,
+.BR tbl ,
+.BR refer ,
+or
+.B soelim.
+.LP
+Options without an argument can be grouped behind a single
+.BR \- .
+A filename of
+.B \-
+denotes the standard input.
+.LP
+The
+.B grog
+command can be used to guess the correct groff command to use to
+format a file.
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.B \-e
+Preprocess with eqn.
+.TP
+.B \-t
+Preprocess with tbl.
+.TP
+.B \-p
+Preprocess with pic.
+.TP
+.B \-s
+Preprocess with soelim.
+.TP
+.B \-R
+Preprocess with refer.
+No mechanism is provided for passing arguments to
+.B refer
+because most refer options have equivalent commands
+which can be included in the file.
+See
+.BR refer (1)
+for more details.
+.TP
+.B \-v
+Make programs run by
+.B groff
+print out their version number.
+.TP
+.B \-V
+Print the pipeline on stdout instead of executing it.
+.TP
+.B \-z
+Suppress output from
+.BR troff .
+Only error messages will be printed.
+.TP
+.B \-Z
+Do not postprocess the output of
+.BR troff .
+Normally
+.B groff
+will automatically run the appropriate postprocessor.
+.TP
+.BI \-P arg
+Pass
+.I arg
+to the postprocessor.
+Each argument should be passed with a separate
+.B \-P
+option.
+Note that
+.B groff
+does not prepend
+.B \-
+to
+.I arg
+before passing it to the postprocessor.
+.TP
+.B \-l
+Send the output to a printer.
+The command used for this is specified by the
+.B print
+command in the device description file.
+.TP
+.BI \-L arg
+Pass
+.I arg
+to the spooler.
+Each argument should be passed with a separate
+.B \-L
+option.
+Note that
+.B groff
+does not prepend
+.B \-
+to
+.I arg
+before passing it to the postprocessor.
+.TP
+.BI \-T dev
+Prepare output for device
+.IR dev .
+The default device is
+.BR ps .
+.TP
+.B \-X
+Preview with
+.B gxditview
+instead of using the usual postprocessor.
+This is unlikely to produce good results except with
+.BR \-Tps .
+.TP
+.B \-N
+Don't allow newlines with eqn delimiters.
+This is the same as the
+.B \-N
+option in
+.BR eqn .
+.TP
+.B \-a
+.TQ
+.B \-b
+.TQ
+.B \-i
+.TQ
+.B \-C
+.TQ
+.B \-E
+.TQ
+.BI \-w name
+.TQ
+.BI \-W name
+.TQ
+.BI \-m name
+.TQ
+.BI \-o list
+.TQ
+.BI \-d cs
+.TQ
+.BI \-r cn
+.TQ
+.BI \-F dir
+.TQ
+.BI \-M dir
+.TQ
+.BI \-f fam
+.TQ
+.BI \-n num
+These are as described in
+.BR troff (1) .
+.SH ENVIRONMENT
+.TP
+.SM
+.B GROFF_COMMAND_PREFIX
+If this is set
+.IR X ,
+then
+.B groff
+will run
+.IB X troff
+instead of
+.BR troff .
+This also applies to
+.BR tbl ,
+.BR pic ,
+.BR eqn ,
+.B refer
+and
+.BR soelim .
+It does not apply to
+.BR grops ,
+.BR grodvi ,
+.BR grotty
+and
+.BR gxditview .
+.TP
+.SM
+.B GROFF_TMAC_PATH
+A colon separated list of directories in which to search for
+macro files.
+.TP
+.SM
+.B GROFF_TYPESETTER
+Default device.
+.TP
+.SM
+.B GROFF_FONT_PATH
+A colon separated list of directories in which to search for the
+.BI dev name
+directory.
+.TP
+.SM
+.B PATH
+The search path for commands executed by
+.BR groff .
+.TP
+.SM
+.B GROFF_TMPDIR
+The directory in which temporary files will be created.
+If this is not set and
+.B
+.SM TMPDIR
+is set, temporary files will be created in that directory.
+Otherwise temporary files will be created in
+.BR /tmp .
+The
+.BR grops (1)
+and
+.BR refer (1)
+commands can create temporary files.
+.SH FILES
+.Tp \w'\fB/usr/share/groff_font/dev\fIname\fB/DESC'u+3n
+.BI /usr/share/groff_font/dev name /DESC
+Device description file for device
+.IR name .
+.TP
+.BI /usr/share/groff_font/dev name / F
+Font file for font
+.I F
+of device
+.IR name .
+.SH AUTHOR
+James Clark <jjc@jclark.com>
+.SH BUGS
+Report bugs to bug-groff@prep.ai.mit.edu.
+Include a complete, self-contained example
+that will allow the bug to be reproduced,
+and say which version of groff you are using.
+.SH COPYRIGHT
+Copyright \(co 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+.LP
+groff is free software; you can redistribute 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.
+.LP
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+.LP
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+.SH AVAILABILITY
+The most recent released version of groff is always available for
+anonymous ftp from prep.ai.mit.edu (18.71.0.38) in the directory
+pub/gnu.
+.SH "SEE ALSO"
+.BR grog (1),
+.BR troff (1),
+.BR tbl (1),
+.BR pic (1),
+.BR eqn (1),
+.BR soelim (1) ,
+.BR refer (1),
+.BR grops (1),
+.BR grodvi (1),
+.BR grotty (1),
+.BR gxditview (1),
+.BR groff_font (5),
+.BR groff_out (5),
+.BR groff_ms (7),
+.BR groff_me (7),
+.BR groff_char (7)
diff --git a/gnu/usr.bin/groff/groff/groff.cc b/gnu/usr.bin/groff/groff/groff.cc
new file mode 100644
index 000000000000..078091315776
--- /dev/null
+++ b/gnu/usr.bin/groff/groff/groff.cc
@@ -0,0 +1,590 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+// A front end for groff.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "lib.h"
+#include "assert.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "font.h"
+#include "device.h"
+#include "pipeline.h"
+#include "defs.h"
+
+#define BSHELL "/bin/sh"
+#define GXDITVIEW "gxditview"
+
+// troff will be passed an argument of -rXREG=1 if the -X option is
+// specified
+#define XREG ".X"
+
+#ifndef STDLIB_H_DECLARES_PUTENV
+extern "C" {
+ int putenv(const char *);
+}
+#endif /* not STDLIB_H_DECLARES_PUTENV */
+
+const char *strsignal(int);
+
+const int SOELIM_INDEX = 0;
+const int REFER_INDEX = SOELIM_INDEX + 1;
+const int PIC_INDEX = REFER_INDEX + 1;
+const int TBL_INDEX = PIC_INDEX + 1;
+const int EQN_INDEX = TBL_INDEX + 1;
+const int TROFF_INDEX = EQN_INDEX + 1;
+const int POST_INDEX = TROFF_INDEX + 1;
+const int SPOOL_INDEX = POST_INDEX + 1;
+
+const int NCOMMANDS = SPOOL_INDEX + 1;
+
+class possible_command {
+ char *name;
+ string args;
+ char **argv;
+
+ void build_argv();
+public:
+ possible_command();
+ ~possible_command();
+ void set_name(const char *);
+ void set_name(const char *, const char *);
+ const char *get_name();
+ void append_arg(const char *, const char * = 0);
+ void clear_args();
+ char **get_argv();
+ void print(int is_last, FILE *fp);
+};
+
+int lflag = 0;
+char *spooler = 0;
+char *driver = 0;
+
+possible_command commands[NCOMMANDS];
+
+int run_commands();
+void print_commands();
+void append_arg_to_string(const char *arg, string &str);
+void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+const char *basename(const char *);
+
+void usage();
+void help();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ assert(NCOMMANDS <= MAX_COMMANDS);
+ string Pargs, Largs, Fargs;
+ int Vflag = 0;
+ int zflag = 0;
+ int iflag = 0;
+ int Xflag = 0;
+ int opt;
+ const char *command_prefix = getenv("GROFF_COMMAND_PREFIX");
+ if (!command_prefix)
+ command_prefix = PROG_PREFIX;
+ commands[TROFF_INDEX].set_name(command_prefix, "troff");
+ while ((opt = getopt(argc, argv,
+ "itpeRszavVhblCENXZF:m:T:f:w:W:M:d:r:n:o:P:L:"))
+ != EOF) {
+ char buf[3];
+ buf[0] = '-';
+ buf[1] = opt;
+ buf[2] = '\0';
+ switch (opt) {
+ case 'i':
+ iflag = 1;
+ break;
+ case 't':
+ commands[TBL_INDEX].set_name(command_prefix, "tbl");
+ break;
+ case 'p':
+ commands[PIC_INDEX].set_name(command_prefix, "pic");
+ break;
+ case 'e':
+ commands[EQN_INDEX].set_name(command_prefix, "eqn");
+ break;
+ case 's':
+ commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
+ break;
+ case 'R':
+ commands[REFER_INDEX].set_name(command_prefix, "refer");
+ break;
+ case 'z':
+ case 'a':
+ commands[TROFF_INDEX].append_arg(buf);
+ // fall through
+ case 'Z':
+ zflag++;
+ break;
+ case 'l':
+ lflag++;
+ break;
+ case 'V':
+ Vflag++;
+ break;
+ case 'v':
+ case 'C':
+ commands[SOELIM_INDEX].append_arg(buf);
+ commands[PIC_INDEX].append_arg(buf);
+ commands[TBL_INDEX].append_arg(buf);
+ commands[EQN_INDEX].append_arg(buf);
+ commands[TROFF_INDEX].append_arg(buf);
+ break;
+ case 'N':
+ commands[EQN_INDEX].append_arg(buf);
+ break;
+ case 'h':
+ help();
+ break;
+ case 'E':
+ case 'b':
+ commands[TROFF_INDEX].append_arg(buf);
+ break;
+ case 'T':
+ if (strcmp(optarg, "Xps") == 0) {
+ warning("-TXps option is obsolete: use -X -Tps instead");
+ device = "ps";
+ Xflag++;
+ }
+ else
+ device = optarg;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ if (Fargs.length() > 0) {
+ Fargs += ':';
+ Fargs += optarg;
+ }
+ else
+ Fargs = optarg;
+ break;
+ case 'f':
+ case 'o':
+ case 'm':
+ case 'r':
+ case 'd':
+ case 'n':
+ case 'w':
+ case 'W':
+ commands[TROFF_INDEX].append_arg(buf, optarg);
+ break;
+ case 'M':
+ commands[EQN_INDEX].append_arg(buf, optarg);
+ commands[TROFF_INDEX].append_arg(buf, optarg);
+ break;
+ case 'P':
+ Pargs += optarg;
+ Pargs += '\0';
+ break;
+ case 'L':
+ append_arg_to_string(optarg, Largs);
+ break;
+ case 'X':
+ Xflag++;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ font::set_unknown_desc_command_handler(handle_unknown_desc_command);
+ if (!font::load_desc())
+ fatal("invalid device `%1'", device);
+ if (!driver)
+ fatal("no `postpro' command in DESC file for device `%1'", device);
+ const char *real_driver = 0;
+ if (Xflag) {
+ real_driver = driver;
+ driver = GXDITVIEW;
+ commands[TROFF_INDEX].append_arg("-r" XREG "=", "1");
+ }
+ if (driver)
+ commands[POST_INDEX].set_name(driver);
+ int gxditview_flag = driver && strcmp(basename(driver), GXDITVIEW) == 0;
+ if (gxditview_flag && argc - optind == 1) {
+ commands[POST_INDEX].append_arg("-title");
+ commands[POST_INDEX].append_arg(argv[optind]);
+ commands[POST_INDEX].append_arg("-xrm");
+ commands[POST_INDEX].append_arg("*iconName:", argv[optind]);
+ string filename_string("|");
+ append_arg_to_string(argv[0], filename_string);
+ append_arg_to_string("-Z", filename_string);
+ for (int i = 1; i < argc; i++)
+ append_arg_to_string(argv[i], filename_string);
+ filename_string += '\0';
+ commands[POST_INDEX].append_arg("-filename");
+ commands[POST_INDEX].append_arg(filename_string.contents());
+ }
+ if (gxditview_flag && Xflag) {
+ string print_string(real_driver);
+ if (spooler) {
+ print_string += " | ";
+ print_string += spooler;
+ print_string += Largs;
+ }
+ print_string += '\0';
+ commands[POST_INDEX].append_arg("-printCommand");
+ commands[POST_INDEX].append_arg(print_string.contents());
+ }
+ const char *p = Pargs.contents();
+ const char *end = p + Pargs.length();
+ while (p < end) {
+ commands[POST_INDEX].append_arg(p);
+ p = strchr(p, '\0') + 1;
+ }
+ if (gxditview_flag)
+ commands[POST_INDEX].append_arg("-");
+ if (lflag && !Xflag && spooler) {
+ commands[SPOOL_INDEX].set_name(BSHELL);
+ commands[SPOOL_INDEX].append_arg("-c");
+ Largs += '\0';
+ Largs = spooler + Largs;
+ commands[SPOOL_INDEX].append_arg(Largs.contents());
+ }
+ if (zflag) {
+ commands[POST_INDEX].set_name(0);
+ commands[SPOOL_INDEX].set_name(0);
+ }
+ commands[TROFF_INDEX].append_arg("-T", device);
+ commands[EQN_INDEX].append_arg("-T", device);
+
+ for (int first_index = 0; first_index < TROFF_INDEX; first_index++)
+ if (commands[first_index].get_name() != 0)
+ break;
+ if (optind < argc) {
+ if (argv[optind][0] == '-' && argv[optind][1] != '\0')
+ commands[first_index].append_arg("--");
+ for (int i = optind; i < argc; i++)
+ commands[first_index].append_arg(argv[i]);
+ if (iflag)
+ commands[first_index].append_arg("-");
+ }
+ if (Fargs.length() > 0) {
+ string e = "GROFF_FONT_PATH";
+ e += '=';
+ e += Fargs;
+ char *fontpath = getenv("GROFF_FONT_PATH");
+ if (fontpath && *fontpath) {
+ e += ':';
+ e += fontpath;
+ }
+ e += '\0';
+ if (putenv(strsave(e.contents())))
+ fatal("putenv failed");
+ }
+ if (Vflag) {
+ print_commands();
+ exit(0);
+ }
+ exit(run_commands());
+}
+
+const char *basename(const char *s)
+{
+ if (!s)
+ return 0;
+ const char *p = strrchr(s, '/');
+ return p ? p + 1 : s;
+}
+
+void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "print") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`print' command requires an argument");
+ else
+ spooler = strsave(arg);
+ }
+ if (strcmp(command, "postpro") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`postpro' command requires an argument");
+ else {
+ for (const char *p = arg; *p; p++)
+ if (csspace(*p)) {
+ error_with_file_and_line(filename, lineno,
+ "invalid `postpro' argument `%1'"
+ ": program name required", arg);
+ return;
+ }
+ driver = strsave(arg);
+ }
+ }
+}
+
+void print_commands()
+{
+ for (int last = SPOOL_INDEX; last >= 0; last--)
+ if (commands[last].get_name() != 0)
+ break;
+ for (int i = 0; i <= last; i++)
+ if (commands[i].get_name() != 0)
+ commands[i].print(i == last, stdout);
+}
+
+// Run the commands. Return the code with which to exit.
+
+int run_commands()
+{
+ char **v[NCOMMANDS];
+ int j = 0;
+ for (int i = 0; i < NCOMMANDS; i++)
+ if (commands[i].get_name() != 0)
+ v[j++] = commands[i].get_argv();
+ return run_pipeline(j, v);
+}
+
+possible_command::possible_command()
+: name(0), argv(0)
+{
+}
+
+possible_command::~possible_command()
+{
+ a_delete name;
+ a_delete argv;
+}
+
+void possible_command::set_name(const char *s)
+{
+ a_delete name;
+ name = strsave(s);
+}
+
+void possible_command::set_name(const char *s1, const char *s2)
+{
+ a_delete name;
+ name = new char[strlen(s1) + strlen(s2) + 1];
+ strcpy(name, s1);
+ strcat(name, s2);
+}
+
+const char *possible_command::get_name()
+{
+ return name;
+}
+
+void possible_command::clear_args()
+{
+ args.clear();
+}
+
+void possible_command::append_arg(const char *s, const char *t)
+{
+ args += s;
+ if (t)
+ args += t;
+ args += '\0';
+}
+
+void possible_command::build_argv()
+{
+ if (argv)
+ return;
+ // Count the number of arguments.
+ int len = args.length();
+ int argc = 1;
+ char *p = 0;
+ if (len > 0) {
+ p = &args[0];
+ for (int i = 0; i < len; i++)
+ if (p[i] == '\0')
+ argc++;
+ }
+ // Build an argument vector.
+ argv = new char *[argc + 1];
+ argv[0] = name;
+ for (int i = 1; i < argc; i++) {
+ argv[i] = p;
+ p = strchr(p, '\0') + 1;
+ }
+ argv[argc] = 0;
+}
+
+void possible_command::print(int is_last, FILE *fp)
+{
+ build_argv();
+ if (argv[0] != 0 && strcmp(argv[0], BSHELL) == 0
+ && argv[1] != 0 && strcmp(argv[1], "-c") == 0
+ && argv[2] != 0 && argv[3] == 0)
+ fputs(argv[2], fp);
+ else {
+ fputs(argv[0], fp);
+ string str;
+ for (int i = 1; argv[i] != 0; i++) {
+ str.clear();
+ append_arg_to_string(argv[i], str);
+ put_string(str, fp);
+ }
+ }
+ if (is_last)
+ putc('\n', fp);
+ else
+ fputs(" | ", fp);
+}
+
+void append_arg_to_string(const char *arg, string &str)
+{
+ str += ' ';
+ int needs_quoting = 0;
+ int contains_single_quote = 0;
+ for (const char *p = arg; *p != '\0'; p++)
+ switch (*p) {
+ case ';':
+ case '&':
+ case '(':
+ case ')':
+ case '|':
+ case '^':
+ case '<':
+ case '>':
+ case '\n':
+ case ' ':
+ case '\t':
+ case '\\':
+ case '"':
+ case '$':
+ case '?':
+ case '*':
+ needs_quoting = 1;
+ break;
+ case '\'':
+ contains_single_quote = 1;
+ break;
+ }
+ if (contains_single_quote || arg[0] == '\0') {
+ str += '"';
+ for (p = arg; *p != '\0'; p++)
+ switch (*p) {
+ case '"':
+ case '\\':
+ case '$':
+ str += '\\';
+ // fall through
+ default:
+ str += *p;
+ break;
+ }
+ str += '"';
+ }
+ else if (needs_quoting) {
+ str += '\'';
+ str += arg;
+ str += '\'';
+ }
+ else
+ str += arg;
+}
+
+char **possible_command::get_argv()
+{
+ build_argv();
+ return argv;
+}
+
+void synopsis()
+{
+ fprintf(stderr,
+"usage: %s [-abehilpstvzCENRVXZ] [-Fdir] [-mname] [-Tdev] [-ffam] [-wname]\n"
+" [-Wname] [ -Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg] [-Larg]\n"
+" [files...]\n",
+ program_name);
+}
+
+void help()
+{
+ synopsis();
+ fputs("\n"
+"-h\tprint this message\n"
+"-t\tpreprocess with tbl\n"
+"-p\tpreprocess with pic\n"
+"-e\tpreprocess with eqn\n"
+"-s\tpreprocess with soelim\n"
+"-R\tpreprocess with refer\n"
+"-Tdev\tuse device dev\n"
+"-X\tuse X11 previewer rather than usual postprocessor\n"
+"-mname\tread macros tmac.name\n"
+"-dcs\tdefine a string c as s\n"
+"-rcn\tdefine a number register c as n\n"
+"-nnum\tnumber first page n\n"
+"-olist\toutput only pages in list\n"
+"-ffam\tuse fam as the default font family\n"
+"-Fdir\tsearch directory dir for device directories\n"
+"-Mdir\tsearch dir for macro files\n"
+"-v\tprint version number\n"
+"-z\tsuppress formatted output\n"
+"-Z\tdon't postprocess\n"
+"-a\tproduce ASCII description of output\n"
+"-i\tread standard input after named input files\n"
+"-wname\tenable warning name\n"
+"-Wname\tinhibit warning name\n"
+"-E\tinhibit all errors\n"
+"-b\tprint backtraces with errors or warnings\n"
+"-l\tspool the output\n"
+"-C\tenable compatibility mode\n"
+"-V\tprint commands on stdout instead of running them\n"
+"-Parg\tpass arg to the postprocessor\n"
+"-Larg\tpass arg to the spooler\n"
+"-N\tdon't allow newlines within eqn delimiters\n"
+"\n",
+ stderr);
+ exit(0);
+}
+
+void usage()
+{
+ synopsis();
+ fprintf(stderr, "%s -h gives more help\n", program_name);
+ exit(1);
+}
+
+extern "C" {
+
+void c_error(const char *format, const char *arg1, const char *arg2,
+ const char *arg3)
+{
+ error(format, arg1, arg2, arg3);
+}
+
+void c_fatal(const char *format, const char *arg1, const char *arg2,
+ const char *arg3)
+{
+ fatal(format, arg1, arg2, arg3);
+}
+
+}
diff --git a/gnu/usr.bin/groff/groff/pipeline.c b/gnu/usr.bin/groff/groff/pipeline.c
new file mode 100644
index 000000000000..1cf5875858e7
--- /dev/null
+++ b/gnu/usr.bin/groff/groff/pipeline.c
@@ -0,0 +1,239 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+Compile options are:
+
+-DWCOREFLAG=0200 (or whatever)
+-DHAVE_VFORK_H
+-Dvfork=fork
+-DHAVE_SYS_SIGLIST
+-DHAVE_UNISTD_H
+*/
+
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
+
+extern char *strerror();
+
+#ifdef _POSIX_VERSION
+
+#include <sys/wait.h>
+
+#define PID_T pid_t
+
+#else /* not _POSIX_VERSION */
+
+/* traditional Unix */
+
+#define WIFEXITED(s) (((s) & 0377) == 0)
+#define WIFSTOPPED(s) (((s) & 0377) == 0177)
+#define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177))
+#define WEXITSTATUS(s) (((s) >> 8) & 0377)
+#define WTERMSIG(s) ((s) & 0177)
+#define WSTOPSIG(s) (((s) >> 8) & 0377)
+
+#ifndef WCOREFLAG
+#define WCOREFLAG 0200
+#endif
+
+#define PID_T int
+
+#endif /* not _POSIX_VERSION */
+
+/* SVR4 uses WCOREFLG; Net 2 uses WCOREFLAG. */
+#ifndef WCOREFLAG
+#ifdef WCOREFLG
+#define WCOREFLAG WCOREFLG
+#endif /* WCOREFLG */
+#endif /* not WCOREFLAG */
+
+#ifndef WCOREDUMP
+#ifdef WCOREFLAG
+#define WCOREDUMP(s) ((s) & WCOREFLAG)
+#else /* not WCOREFLAG */
+#define WCOREDUMP(s) (0)
+#endif /* WCOREFLAG */
+#endif /* not WCOREDUMP */
+
+#include "pipeline.h"
+
+#ifdef __STDC__
+#define P(parms) parms
+#else
+#define P(parms) ()
+#endif
+
+#define error c_error
+extern void error P((char *, char *, char *, char *));
+
+static void sys_fatal P((char *));
+static char *strsignal P((int));
+static char *itoa P((int));
+
+int run_pipeline(ncommands, commands)
+ int ncommands;
+ char ***commands;
+{
+ int i;
+ int last_input = 0;
+ PID_T pids[MAX_COMMANDS];
+ int ret = 0;
+ int proc_count = ncommands;
+
+ for (i = 0; i < ncommands; i++) {
+ int pdes[2];
+ PID_T pid;
+ if (i != ncommands - 1) {
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+ }
+ pid = vfork();
+ if (pid < 0)
+ sys_fatal("fork");
+ if (pid == 0) {
+ /* child */
+ if (last_input != 0) {
+ if (close(0) < 0)
+ sys_fatal("close");
+ if (dup(last_input) < 0)
+ sys_fatal("dup");
+ if (close(last_input) < 0)
+ sys_fatal("close");
+ }
+ if (i != ncommands - 1) {
+ if (close(1) < 0)
+ sys_fatal("close");
+ if (dup(pdes[1]) < 0)
+ sys_fatal("dup");
+ if (close(pdes[1]) < 0)
+ sys_fatal("close");
+ if (close(pdes[0]))
+ sys_fatal("close");
+ }
+ execvp(commands[i][0], commands[i]);
+ error("couldn't exec %1: %2", commands[i][0],
+ strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ _exit(EXEC_FAILED_EXIT_STATUS);
+ }
+ /* in the parent */
+ if (last_input != 0) {
+ if (close(last_input) < 0)
+ sys_fatal("close");
+ }
+ if (i != ncommands - 1) {
+ if (close(pdes[1]) < 0)
+ sys_fatal("close");
+ last_input = pdes[0];
+ }
+ pids[i] = pid;
+ }
+ while (proc_count > 0) {
+ int status;
+ PID_T pid = wait(&status);
+ if (pid < 0)
+ sys_fatal("wait");
+ for (i = 0; i < ncommands; i++)
+ if (pids[i] == pid) {
+ pids[i] = -1;
+ --proc_count;
+ if (WIFSIGNALED(status)) {
+ int sig = WTERMSIG(status);
+#ifdef SIGPIPE
+ if (sig == SIGPIPE) {
+ if (i == ncommands - 1) {
+
+ /* This works around a problem that occurred when using the
+ rerasterize action in gxditview. What seemed to be
+ happening (on SunOS 4.1.1) was that pclose() closed the
+ pipe and waited for groff, gtroff got a SIGPIPE, but
+ gpic blocked writing to gtroff, and so groff blocked
+ waiting for gpic and gxditview blocked waiting for
+ groff. I don't understand why gpic wasn't getting a
+ SIGPIPE. */
+ int j;
+ for (j = 0; j < ncommands; j++)
+ if (pids[j] > 0)
+ (void)kill(pids[j], SIGPIPE);
+ }
+ }
+ else
+#endif /* SIGPIPE */
+ {
+ error("%1: %2%3",
+ commands[i][0],
+ strsignal(sig),
+ WCOREDUMP(status) ? " (core dumped)" : "");
+ ret |= 2;
+ }
+ }
+ else if (WIFEXITED(status)) {
+ int exit_status = WEXITSTATUS(status);
+ if (exit_status == EXEC_FAILED_EXIT_STATUS)
+ ret |= 4;
+ else if (exit_status != 0)
+ ret |= 1;
+ }
+ else
+ error("unexpected status %1",
+ itoa(status), (char *)0, (char *)0);
+ break;
+ }
+ }
+ return ret;
+}
+
+static void sys_fatal(s)
+ char *s;
+{
+ c_fatal("%1: %2", s, strerror(errno), (char *)0);
+}
+
+static char *itoa(n)
+ int n;
+{
+ static char buf[12];
+ sprintf(buf, "%d", n);
+ return buf;
+}
+
+static char *strsignal(n)
+ int n;
+{
+ static char buf[sizeof("Signal ") + 1 + sizeof(int)*3];
+#ifdef HAVE_SYS_SIGLIST
+ if (n >= 0 && n < NSIG && sys_siglist[n] != 0)
+ return sys_siglist[n];
+#endif /* HAVE_SYS_SIGLIST */
+ sprintf(buf, "Signal %d", n);
+ return buf;
+}
diff --git a/gnu/usr.bin/groff/groff/pipeline.h b/gnu/usr.bin/groff/groff/pipeline.h
new file mode 100644
index 000000000000..032b0bba68c8
--- /dev/null
+++ b/gnu/usr.bin/groff/groff/pipeline.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef __cplusplus
+extern "C" {
+ int run_pipeline(int, char ***);
+}
+#endif
+
+/* run_pipeline can handle at most this many commands */
+#define MAX_COMMANDS 10
+
+/* Children exit with this status if execvp fails. */
+#define EXEC_FAILED_EXIT_STATUS 0xff
diff --git a/gnu/usr.bin/groff/grog/Makefile b/gnu/usr.bin/groff/grog/Makefile
new file mode 100644
index 000000000000..9dfe7ba4e1de
--- /dev/null
+++ b/gnu/usr.bin/groff/grog/Makefile
@@ -0,0 +1,8 @@
+MAN1= grog.1
+
+afterinstall:
+ install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ $(.CURDIR)/grog.pl $(DESTDIR)$(BINDIR)/grog
+
+.include <../../../usr.bin/Makefile.inc>
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/grog/grog.1 b/gnu/usr.bin/groff/grog/grog.1
new file mode 100644
index 000000000000..57f1f85d26fd
--- /dev/null
+++ b/gnu/usr.bin/groff/grog/grog.1
@@ -0,0 +1,54 @@
+.TH GROG 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+grog \- guess options for groff command
+.SH SYNOPSIS
+.B grog
+[
+.BI \- option
+\|.\|.\|.
+]
+[
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grog
+reads
+.I files
+and guesses which of the
+.BR groff (1)
+options
+.BR \-e ,
+.BR \-man ,
+.BR \-me ,
+.BR \-mm ,
+.BR \-ms ,
+.BR \-p ,
+.BR \-s ,
+and
+.BR \-t
+are required for printing
+.IR files ,
+and prints the groff command including those options on the standard output.
+A filename of
+.B \-
+is taken to refer to the standard input.
+If no files are specified the standard input will be read.
+Any specified options will be included in the printed command.
+No space is allowed between options and their arguments.
+For example,
+.IP
+.B `grog \-Tdvi paper.ms`
+.LP
+will guess the approriate command to print
+.B paper.ms
+and then run it after adding the
+.B \-Tdvi
+option.
+.SH "SEE ALSO"
+.BR doctype (1),
+.BR groff (1),
+.BR troff (1),
+.BR tbl (1),
+.BR pic (1),
+.BR eqn (1),
+.BR soelim (1)
diff --git a/gnu/usr.bin/groff/grog/grog.pl b/gnu/usr.bin/groff/grog/grog.pl
new file mode 100644
index 000000000000..b131da64b236
--- /dev/null
+++ b/gnu/usr.bin/groff/grog/grog.pl
@@ -0,0 +1,149 @@
+#!/usr/bin/perl
+# grog -- guess options for groff command
+# Inspired by doctype script in Kernighan & Pike, Unix Programming
+# Environment, pp 306-8.
+
+$prog = $0;
+$prog =~ s@.*/@@;
+
+push(@command, "groff");
+
+while ($ARGV[0] =~ /^-./) {
+ $arg = shift(@ARGV);
+ last if $arg eq "--";
+ push(@command, $arg);
+}
+
+if (@ARGV) {
+ foreach $arg (@ARGV) {
+ &process($arg, 0);
+ }
+}
+else {
+ &process("-", 0);
+}
+
+sub process {
+ local($filename, $level) = @_;
+ local(*FILE);
+
+ if (!open(FILE, $filename eq "-" ? $filename : "< $filename")) {
+ print STDERR "$prog: can't open \`$filename': $!\n";
+ exit 1 unless $level;
+ return;
+ }
+ while (<FILE>) {
+ if (/^\.TS/) {
+ $_ = <FILE>;
+ if (!/^\./) {
+ $tbl++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.EQ/) {
+ $_ = <FILE>;
+ if (!/^\./ || /^\.[0-9]/) {
+ $eqn++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.PS([ 0-9.<].*)?$/) {
+ if (/^\.PS\s*<\s*(\S+)/) {
+ $pic++;
+ $soelim++ if $level;
+ &process($1, $level);
+ }
+ else {
+ $_ = <FILE>;
+ if (!/^\./ || /^\.ps/) {
+ $pic++;
+ $soelim++ if $level;
+ }
+ }
+ }
+ elsif (/^\.R1/ || /^\.\[/) {
+ $refer++;
+ $soelim++ if $level;
+ }
+ elsif (/^\.[PLI]P/) {
+ $PP++;
+ }
+ elsif (/^\.P$/) {
+ $P++;
+ }
+ elsif (/^\.(PH|SA)/) {
+ $mm++;
+ }
+ elsif (/^\.TH/) {
+ $TH++;
+ }
+ elsif (/^\.SH/) {
+ $SH++;
+ }
+ elsif (/^\.([pnil]p|sh)/) {
+ $me++;
+ }
+ elsif (/^\.Dd/) {
+ $mdoc++;
+ }
+ elsif (/^\.(Tp|Dp|De|Cx|Cl)/) {
+ $mdoc_old = 1;
+ }
+ # In the old version of -mdoc `Oo' is a toggle, in the new it's
+ # closed by `Oc'.
+ elsif (/^\.Oo/) {
+ $Oo++;
+ }
+ elsif (/^\.Oc/) {
+ $Oo--;
+ }
+ if (/^\.so/) {
+ chop;
+ s/^.so *//;
+ s/\\\".*//;
+ s/ .*$//;
+ &process($_, $level + 1) unless /\\/ || $_ eq "";
+ }
+ }
+ close(FILE);
+}
+
+if ($pic || $tbl || $eqn || $refer) {
+ $s = "-";
+ $s .= "s" if $soelim;
+ $s .= "R" if $refer;
+ $s .= "p" if $pic;
+ $s .= "t" if $tbl;
+ $s .= "e" if $eqn;
+ push(@command, $s);
+}
+
+if ($me > 0) {
+ push(@command, "-me");
+}
+elsif ($SH > 0 && $TH > 0) {
+ push(@command, "-man");
+}
+elsif ($PP > 0) {
+ push(@command, "-ms");
+}
+elsif ($P > 0 || $mm > 0) {
+ push(@command, "-mm");
+}
+elsif ($mdoc > 0) {
+ push(@command, ($mdoc_old || $Oo > 0) ? "-mdoc.old" : "-mdoc");
+}
+
+push(@command, "--") if @ARGV && $ARGV[0] =~ /^-./;
+
+push(@command, @ARGV);
+
+# We could implement an option to execute the command here.
+
+foreach (@command) {
+ next unless /[\$\\\"\';&()|<> \t\n]/;
+ s/\'/\'\\\'\'/;
+ $_ = "'" . $_ . "'";
+}
+
+print join(' ', @command), "\n";
diff --git a/gnu/usr.bin/groff/grog/grog.sh b/gnu/usr.bin/groff/grog/grog.sh
new file mode 100644
index 000000000000..755c891ce683
--- /dev/null
+++ b/gnu/usr.bin/groff/grog/grog.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+# grog -- guess options for groff command
+# Like doctype in Kernighan & Pike, Unix Programming Environment, pp 306-8.
+
+soelim=gsoelim
+
+opts=
+
+for arg
+do
+ case "$arg" in
+ --)
+ shift; break;;
+ -)
+ break;;
+ -*)
+ opts="$opts $arg"; shift;;
+ *)
+ break;;
+ esac
+done
+
+egrep -h '^\.(P|[LI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|Oc|TS|EQ|TH|SH|so|\[|R1|PH|SA)' $* \
+| sed -e '/^\.so/s/^.*$/.SO_START\
+&\
+.SO_END/' \
+| $soelim \
+| egrep '^\.(P|[LI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|Oc|TS|EQ|TH|SH|\[|R1|PH|SA|SO_START|SO_END)' \
+| awk '
+/^\.SO_START$/ { so = 1 }
+/^\.SO_END$/ { so = 0 }
+/^\.TS/ { tbl++; if (so > 0) soelim++ }
+/^\.PS([ 0-9.<].*)?$/ { pic++; if (so > 0) soelim++ }
+/^\.EQ/ { eqn++; if (so > 0) soelim++ }
+/^\.(R1|\[)/ { refer++; if (so > 0) soelim++ }
+/^\.TH/ { TH++ }
+/^\.[PLI]P/ { PP++ }
+/^\.P$/ { P++ }
+/^\.SH/ { SH++ }
+/^\.(PH|SA)/ { mm++ }
+/^\.([pnil]p|sh)/ { me++ }
+/^\.Dd/ { mdoc++ }
+/^\.(Tp|Dp|De|Cx|Cl)/ { mdoc_old++ }
+/^\.Oo/ { Oo++ }
+/^\.Oc/ { Oo-- }
+
+END {
+ if (files ~ /^-/)
+ files = "-- " files
+ printf "groff"
+ if (pic > 0 || tbl > 0 || eqn > 0 || refer > 0) {
+ printf " -"
+ if (soelim > 0) printf "s"
+ if (refer > 0) printf "R"
+ if (pic > 0) printf "p"
+ if (tbl > 0) printf "t"
+ if (eqn > 0) printf "e"
+ }
+ if (me > 0)
+ printf " -me"
+ else if (SH > 0 && TH > 0)
+ printf " -man"
+ else if (PP > 0)
+ printf " -ms"
+ else if (P > 0 || mm > 0)
+ printf " -mm"
+ else if (mdoc > 0) {
+ if (mdoc_old > 0 || Oo > 0)
+ printf " -mdoc.old"
+ else
+ printf " -mdoc"
+ }
+ if (opts != "")
+ printf "%s", opts
+ if (files != "")
+ printf " %s", files
+ print
+}' "opts=$opts" "files=$*" -
diff --git a/gnu/usr.bin/groff/grops/Makefile b/gnu/usr.bin/groff/grops/Makefile
new file mode 100644
index 000000000000..a7818edafbdf
--- /dev/null
+++ b/gnu/usr.bin/groff/grops/Makefile
@@ -0,0 +1,12 @@
+# Makefile for grops
+
+PROG= grops
+SRCS= ps.cc psrm.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBDRIVER) $(LIBGROFF) -lm
+DPADD+= $(LIBDRIVER) $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/grops/TODO b/gnu/usr.bin/groff/grops/TODO
new file mode 100644
index 000000000000..4d1e5fd618a9
--- /dev/null
+++ b/gnu/usr.bin/groff/grops/TODO
@@ -0,0 +1,25 @@
+Read PFB files directly.
+
+Generate %%DocumentMedia comment.
+
+For efficiency it might be better to have the printer interface have
+support for the t and u commands.
+
+Angles in arc command: don't generate more digits after the decimal
+point than are necessary.
+
+Possibly generate BoundingBox comment.
+
+Per font composite character mechanism (sufficient for fractions).
+
+Consider whether we ought to do rounding of graphical objects other
+than lines. What's the point?
+
+Error messages should refer to output page number.
+
+Search for downloadable fonts using their PostScript names if not
+found in download file.
+
+Separate path for searching for downloadable font files.
+
+Clip to the BoundingBox when importing documents.
diff --git a/gnu/usr.bin/groff/grops/grops.1 b/gnu/usr.bin/groff/grops/grops.1
new file mode 100644
index 000000000000..2a584d6d681c
--- /dev/null
+++ b/gnu/usr.bin/groff/grops/grops.1
@@ -0,0 +1,797 @@
+.\" -*- nroff -*-
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROPS 1 "5 April 1993" "Groff Version 1.08"
+.SH NAME
+grops \- PostScript driver for groff
+.SH SYNOPSIS
+.B grops
+[
+.B \-glv
+] [
+.BI \-b n
+] [
+.BI \-c n
+] [
+.BI \-w n
+] [
+.BI \-F dir
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grops
+translates the output of GNU
+.B troff
+to PostScript.
+Normally
+.B grops
+should be invoked by using the groff command
+with a
+.B \-Tps
+option.
+.if 'ps'ps' (Actually, this is the default for groff.)
+If no files are given,
+.B grops
+will read the standard input.
+A filename of
+.B \-
+will also cause
+.B grops
+to read the standard input.
+PostScript output is written to the standard output.
+When
+.B grops
+is run by
+.B groff
+options can be passed to
+.B grops
+using the
+.B groff
+.B \-P
+option.
+.SH OPTIONS
+.TP
+.BI \-b n
+Workaround broken spoolers and previewers.
+Normally
+.B grops
+produces output that conforms
+the Document Structuring Conventions version 3.0.
+Unfortunately some spoolers and previewers can't handle such output.
+The value of
+.I n
+controls what
+.B grops
+does to its output acceptable to such programs.
+A value of 0 will cause grops not to employ any workarounds.
+Add 1 if no
+.B %%BeginDocumentSetup
+and
+.B %%EndDocumentSetup
+comments should be generated;
+this is needed for early versions of TranScript that get confused by
+anything between the
+.B %%EndProlog
+comment and the first
+.B %%Page
+comment.
+Add 2 if lines in included files beginning with
+.B %!
+should be stripped out; this is needed for Sun's pageview previewer.
+Add 4 if
+.BR %%Page ,
+.BR %%Trailer
+and
+.B %%EndProlog
+comments should be
+stripped out of included files; this is needed for spoolers that
+don't understand the
+.B %%BeginDocument
+and
+.B %%EndDocument
+comments.
+Add 8 if the first line of the PostScript output should be
+.B %!PS-Adobe-2.0
+rather than
+.BR %!PS-Adobe-3.0 ;
+this is needed when using Sun's Newsprint with a printer that requires
+page reversal.
+The default value can be specified by a
+.RS
+.IP
+.BI broken\ n
+.LP
+command in the DESC file.
+Otherwise the default value is 0.
+.RE
+.TP
+.BI \-c n
+Print
+.I n
+copies of each page.
+.TP
+.BI \-g
+Guess the page length.
+This generates PostScript code that guesses the page length.
+The guess will be correct only if the imageable area is vertically
+centered on the page.
+This option allows you to generate documents that can be printed
+both on letter (8.5\(mu11) paper and on A4 paper without change.
+.TP
+.BI \-l
+Print the document in landscape format.
+.TP
+.BI \-F dir
+Search the directory
+.IB dir /dev name
+for font and device description files;
+.I name
+is the name of the device, usually
+.BR ps .
+.TP
+.BI \-w n
+Lines should be drawn using a thickness of
+.I n
+thousandths of an em.
+.TP
+.B \-v
+Print the version number.
+.SH USAGE
+There are styles called
+.BR R ,
+.BR I ,
+.BR B ,
+and
+.B BI
+mounted at font positions 1 to 4.
+The fonts are grouped into families
+.BR A ,
+.BR BM ,
+.BR C ,
+.BR H ,
+.BR HN ,
+.BR N ,
+.B P
+and
+.B T
+having members in each of these styles:
+.de FT
+.if '\\*(.T'ps' .ft \\$1
+..
+.TP
+.B AR
+.FT AR
+AvantGarde-Book
+.FT
+.TP
+.B AI
+.FT AI
+AvantGarde-BookOblique
+.FT
+.TP
+.B AB
+.FT AB
+AvantGarde-Demi
+.FT
+.TP
+.B ABI
+.FT ABI
+AvantGarde-DemiOblique
+.FT
+.TP
+.B BMR
+.FT BMR
+Bookman-Light
+.FT
+.TP
+.B BMI
+.FT BMI
+Bookman-LightItalic
+.FT
+.TP
+.B BMB
+.FT BMB
+Bookman-Demi
+.FT
+.TP
+.B BMBI
+.FT BMBI
+Bookman-DemiItalic
+.FT
+.TP
+.B CR
+.FT CR
+Courier
+.FT
+.TP
+.B CI
+.FT CI
+Courier-Oblique
+.FT
+.TP
+.B CB
+.FT CB
+Courier-Bold
+.FT
+.TP
+.B CBI
+.FT CBI
+Courier-BoldOblique
+.FT
+.TP
+.B HR
+.FT HR
+Helvetica
+.FT
+.TP
+.B HI
+.FT HI
+Helvetica-Oblique
+.FT
+.TP
+.B HB
+.FT HB
+Helvetica-Bold
+.FT
+.TP
+.B HBI
+.FT HBI
+Helvetica-BoldOblique
+.FT
+.TP
+.B HNR
+.FT HNR
+Helvetica-Narrow
+.FT
+.TP
+.B HNI
+.FT HNI
+Helvetica-Narrow-Oblique
+.FT
+.TP
+.B HNB
+.FT HNB
+Helvetica-Narrow-Bold
+.FT
+.TP
+.B HNBI
+.FT HNBI
+Helvetica-Narrow-BoldOblique
+.FT
+.TP
+.B NR
+.FT NR
+NewCenturySchlbk-Roman
+.FT
+.TP
+.B NI
+.FT NI
+NewCenturySchlbk-Italic
+.FT
+.TP
+.B NB
+.FT NB
+NewCenturySchlbk-Bold
+.FT
+.TP
+.B NBI
+.FT NBI
+NewCenturySchlbk-BoldItalic
+.FT
+.TP
+.B PR
+.FT PR
+Palatino-Roman
+.FT
+.TP
+.B PI
+.FT PI
+Palatino-Italic
+.FT
+.TP
+.B PB
+.FT PB
+Palatino-Bold
+.FT
+.TP
+.B PBI
+.FT PBI
+Palatino-BoldItalic
+.FT
+.TP
+.B TR
+.FT TR
+Times-Roman
+.FT
+.TP
+.B TI
+.FT TI
+Times-Italic
+.FT
+.TP
+.B TB
+.FT TB
+Times-Bold
+.FT
+.TP
+.B TBI
+.FT TBI
+Times-BoldItalic
+.FT
+.LP
+There is also the following font which is not a member of a family:
+.TP
+.B ZCMI
+.FT ZCMI
+ZapfChancery-MediumItalic
+.FT
+.LP
+There are also some special fonts called
+.B SS
+and
+.BR S .
+Zapf Dingbats is avilable as
+.BR ZD
+and a reversed version of ZapfDingbats (with symbols pointing in the opposite
+direction) is available as
+.BR ZDR ;
+most characters in these fonts are unnamed and must be accessed using
+.BR \eN .
+.LP
+.B grops
+understands various X commands produced using the
+.B \eX
+escape sequence;
+.B grops
+will only interpret commands that begin with a
+.B ps:
+tag.
+.TP
+.BI \eX'ps:\ exec\ code '
+This executes the arbitrary PostScript commands in
+.IR code .
+The PostScript currentpoint will be set to the position of the
+.B \eX
+command before executing
+.IR code .
+The origin will be at the top left corner of the page,
+and y coordinates will increase down the page.
+A procedure
+.B u
+will be defined that converts groff units
+to the coordinate system in effect.
+For example,
+.RS
+.IP
+.B
+\&.nr x 1i
+.br
+.B
+\eX'ps: exec \enx u 0 rlineto stroke'
+.br
+.RE
+.IP
+will draw a horizontal line one inch long.
+.I code
+may make changes to the graphics state,
+but any changes will persist only to the
+end of the page.
+Any definitions will also persist only until the end of the page.
+If you use the
+.B \eY
+escape sequence with an argument that names a macro,
+.I code
+can extend over multiple lines.
+For example,
+.RS
+.IP
+.nf
+.ft B
+\&.nr x 1i
+\&.de y
+\&ps: exec
+\&\enx u 0 rlineto
+\&stroke
+\&..
+\&\eYy
+.fi
+.ft R
+.LP
+is another way to draw a horizontal line one inch long.
+.RE
+.TP
+.BI \eX'ps:\ file\ name '
+This is the same as the
+.B exec
+command except that the PostScript code is read from file
+.IR name .
+.TP
+.BI \eX'ps:\ def\ code '
+Place a PostScript definition contained in
+.I code
+in the prologue.
+There should be at most one definition per
+.B \eX
+command.
+Long definitions can be split over several
+.B \eX
+commands;
+all the
+.I code
+arguments are simply joined together separated by newlines.
+The definitions are placed in a dictionary which is automatically
+pushed on the dictionary stack when an
+.B exec
+command is executed.
+If you use the
+.B \eY
+escape sequence with an argument that names a macro,
+.I code
+can extend over multiple lines.
+.TP
+.BI \eX'ps:\ mdef\ n\ code '
+Like
+.BR def ,
+except that
+.I code
+may contain up to
+.I n
+definitions.
+.B grops
+needs to know how many definitions
+.I code
+contains
+so that it can create an apppropriately sized PostScript dictionary
+to contain them.
+.TP
+.BI \eX'ps:\ import\ file\ llx\ lly\ urx\ ury\ width\ \fR[\fP\ height\ \fR]\fP '
+Import a PostScript graphic from
+.IR file .
+The arguments
+.IR llx ,
+.IR lly ,
+.IR urx ,
+and
+.I ury
+give the bounding box of the graphic in the default PostScript
+coordinate system; they should all be integers;
+.I llx
+and
+.I lly
+are the x and y coordinates of the lower left
+corner of the graphic;
+.I urx
+and
+.I ury
+are the x and y coordinates of the upper right corner of the graphic;
+.I width
+and
+.I height
+are integers that give the desired width and height in groff
+units of the graphic.
+The graphic will be scaled so that it has this width and height
+and translated so that the lower left corner of the graphic is
+located at the position associated with
+.B \eX
+command.
+If the height argument is omitted it will be scaled uniformly in the
+x and y directions so that it has the specified width.
+Note that the contents of the
+.B \eX
+command are not interpreted by
+.BR troff ;
+so vertical space for the graphic is not automatically added,
+and the
+.I width
+and
+.I height
+arguments are not allowed to have attached scaling indicators.
+If the PostScript file complies with the Adobe Document Structuring
+Conventions and contains a
+.B %%BoundingBox
+comment, then the bounding box can be automatically
+extracted from within groff by using the
+.B sy
+request to run the
+.B psbb
+command.
+.RS
+.LP
+The
+.B \-mps
+macros (which are automatically loaded when
+.B grops
+is run by the groff command) include a
+.B PSPIC
+macro which allows a picture to be easily imported.
+This has the format
+.IP
+.BI .PSPIC\ file\ \fR[ width\ \fR[ height \fR]]
+.LP
+.I file
+is the name of the file containing the illustration;
+.I width
+and
+.I height
+give the desired width and height of the graphic.
+The
+.I width
+and
+.I height
+arguments may have scaling indicators attached;
+the default scaling indicator is
+.BR i .
+This macro will scale the graphic uniformly
+in the x and y directions so that it is no more than
+.I width
+wide
+and
+.I height
+high.
+.RE
+.TP
+.B \eX'ps:\ invis'
+.br
+.ns
+.TP
+.B \eX'ps:\ endinvis'
+No output will be generated for text and drawing commands
+that are bracketed with these
+.B \eX
+commands.
+These commands are intended for use when output from
+.B troff
+will be previewed before being processed with
+.BR grops ;
+if the previewer is unable to display certain characters
+or other constructs, then other substitute characters or constructs
+can be used for previewing by bracketing them with these
+.B \eX
+commands.
+.RS
+.LP
+For example,
+.B gxditview
+is not able to display a proper
+.B \e(em
+character because the standard X11 fonts do not provide it;
+this problem can be overcome by executing the following
+request
+.IP
+.ft B
+.nf
+\&.char \e(em \eX'ps: invis'\e
+\eZ'\ev'-.25m'\eh'.05m'\eD'l .9m 0'\eh'.05m''\e
+\eX'ps: endinvis'\e(em
+.ft
+.fi
+.LP
+In this case,
+.B gxditview
+will be unable to display the
+.B \e(em
+character and will draw the line,
+whereas
+.B grops
+will print the
+.B \e(em
+character
+and ignore the line.
+.RE
+.LP
+The input to
+.B grops
+must be in the format output by
+.BR troff (1).
+This is described in
+.BR groff_out (1).
+In addition the device and font description files for the device used
+must meet certain requirements.
+The device and font description files supplied for
+.B ps
+device meet all these requirements.
+.BR afmtodit (1)
+can be used to create font files from AFM files.
+The resolution must be an integer multiple of 72 times the
+.BR sizescale .
+The
+.B ps
+device uses a resolution of 72000 and a sizescale of 1000.
+The device description file should contain a command
+.IP
+.BI paperlength\ n
+.LP
+which says that output should be generated which is suitable for
+printing on a page whose length is
+.I n
+machine units.
+Each font description file must contain a command
+.IP
+.BI internalname\ psname
+.LP
+which says that the PostScript name of the font is
+.IR psname .
+It may also contain a command
+.IP
+.BI encoding\ enc_file
+.LP
+which says that
+the PostScript font should be reencoded using the encoding described in
+.IR enc_file ;
+this file should consist of a sequence of lines of the form:
+.IP
+.I
+pschar code
+.LP
+where
+.I pschar
+is the PostScript name of the character,
+and
+.I code
+is its position in the encoding expressed as a decimal integer.
+The code for each character given in the font file must correspond
+to the code for the character in encoding file, or to the code in the default
+encoding for the font if the PostScript font is not to be reencoded.
+This code can be used with the
+.B \eN
+escape sequence in
+.B troff
+to select the character,
+even if the character does not have a groff name.
+Every character in the font file must exist in the PostScript font, and
+the widths given in the font file must match the widths used
+in the PostScript font.
+.B grops
+will assume that a character with a groff name of
+.B space
+is blank (makes no marks on the page);
+it can make use of such a character to generate more efficient and
+compact PostScript output.
+.LP
+.B grops
+can automatically include the downloadable fonts necessary
+to print the document.
+Any downloadable fonts which should, when required, be included by
+.B grops
+must be listed in the file
+.BR /usr/share/groff_font/devps/download ;
+this should consist of lines of the form
+.IP
+.I
+font filename
+.LP
+where
+.I font
+is the PostScript name of the font,
+and
+.I filename
+is the name of the file containing the font;
+lines beginning with
+.B #
+and blank lines are ignored;
+fields may be separated by tabs or spaces;
+.I filename
+will be searched for using the same mechanism that is used
+for groff font metric files.
+The
+.B download
+file itself will also be searched for using this mechanism.
+.LP
+If the file containing a downloadable font or imported document
+conforms to the Adobe Document Structuring Conventions,
+then
+.B grops
+will interpret any comments in the files sufficiently to ensure that its
+own output is conforming.
+It will also supply any needed font resources that are listed in the
+.B download
+file
+as well as any needed file resources.
+It is also able to handle inter-resource dependencies.
+For example, suppose that you have a downloadable font called Garamond,
+and also a downloadable font called Garamond-Outline
+which depends on Garamond
+(typically it would be defined to copy Garamond's font dictionary,
+and change the PaintType),
+then it is necessary for Garamond to be appear before Garamond-Outline
+in the PostScript document.
+.B grops
+will handle this automatically
+provided that the downloadable font file for Garamond-Outline
+indicates its dependence on Garamond by means of
+the Document Structuring Conventions,
+for example by beginning with the following lines
+.IP
+.B
+%!PS-Adobe-3.0 Resource-Font
+.br
+.B
+%%DocumentNeededResources: font Garamond
+.br
+.B
+%%EndComments
+.br
+.B
+%%IncludeResource: font Garamond
+.LP
+In this case both Garamond and Garamond-Outline would need to be listed
+in the
+.B download
+file.
+A downloadable font should not include its own name in a
+.B %%DocumentSuppliedResources
+comment.
+.LP
+.B grops
+will not interpret
+.B %%DocumentFonts
+comments.
+The
+.BR %%DocumentNeededResources ,
+.BR %%DocumentSuppliedResources ,
+.BR %%IncludeResource ,
+.BR %%BeginResource
+and
+.BR %%EndResource
+comments
+(or possibly the old
+.BR %%DocumentNeededFonts ,
+.BR %%DocumentSuppliedFonts ,
+.BR %%IncludeFont ,
+.BR %%BeginFont
+and
+.BR %%EndFont
+comments)
+should be used.
+.SH FILES
+.Tp \w'\fB/usr/share/groff_font/devps/download'u+2n
+.B /usr/share/groff_font/devps/DESC
+Device desciption file.
+.TP
+.BI /usr/share/groff_font/devps/ F
+Font description file for font
+.IR F .
+.TP
+.B /usr/share/groff_font/devps/download
+List of downloadable fonts.
+.TP
+.B /usr/share/groff_font/devps/text.enc
+Encoding used for text fonts.
+.TP
+.B /usr/share/tmac/tmac.ps
+Macros for use with
+.BR grops ;
+automatically loaded by
+.BR troffrc
+.TP
+.B /usr/share/tmac/tmac.pspic
+Definition of
+.B PSPIC
+macro,
+automatically loaded by
+.BR tmac.ps .
+.TP
+.B /usr/share/tmac/tmac.psold
+Macros to disable use of characters not present in older
+PostScript printers; automatically loaded by
+.BR tmac.ps .
+.TP
+.B /usr/share/tmac/tmac.psnew
+Macros to undo the effect of
+.BR tmac.psold .
+.TP
+.BI /tmp/grops XXXXXX
+Temporary file.
+.SH "SEE ALSO"
+.BR afmtodit (1),
+.BR groff (1),
+.BR troff (1),
+.BR psbb (1),
+.BR groff_out (5),
+.BR groff_font (5),
+.BR groff_char (7)
diff --git a/gnu/usr.bin/groff/grops/ps.cc b/gnu/usr.bin/groff/grops/ps.cc
new file mode 100644
index 000000000000..1dd5d8c77f75
--- /dev/null
+++ b/gnu/usr.bin/groff/grops/ps.cc
@@ -0,0 +1,1507 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include "ps.h"
+
+static int landscape_flag = 0;
+static int ncopies = 1;
+static int linewidth = -1;
+// Non-zero means generate PostScript code that guesses the paper
+// length using the imageable area.
+static int guess_flag = 0;
+
+// Non-zero if -b was specified on the command line.
+static int bflag = 0;
+unsigned broken_flags = 0;
+
+#define DEFAULT_LINEWIDTH 40 /* in ems/1000 */
+#define FILL_MAX 1000
+
+const char *const dict_name = "grops";
+const char *const defs_dict_name = "DEFS";
+const int DEFS_DICT_SPARE = 50;
+
+double degrees(double r)
+{
+ return r*180.0/M_PI;
+}
+
+double radians(double d)
+{
+ return d*M_PI/180.0;
+}
+
+inline double transform_fill(int fill)
+{
+ return 1 - fill/double(FILL_MAX);
+}
+
+ps_output::ps_output(FILE *f, int n)
+: fp(f), max_line_length(n), col(0), need_space(0), fixed_point(0)
+{
+}
+
+ps_output &ps_output::set_file(FILE *f)
+{
+ fp = f;
+ col = 0;
+ return *this;
+}
+
+ps_output &ps_output::copy_file(FILE *infp)
+{
+ int c;
+ while ((c = getc(infp)) != EOF)
+ putc(c, fp);
+ return *this;
+}
+
+ps_output &ps_output::end_line()
+{
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ return *this;
+}
+
+ps_output &ps_output::special(const char *s)
+{
+ if (s == 0 || *s == '\0')
+ return *this;
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ }
+ fputs(s, fp);
+ if (strchr(s, '\0')[-1] != '\n')
+ putc('\n', fp);
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::simple_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ putc('%', fp);
+ putc('%', fp);
+ fputs(s, fp);
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::begin_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ putc('%', fp);
+ putc('%', fp);
+ fputs(s, fp);
+ col = 2 + strlen(s);
+ return *this;
+}
+
+ps_output &ps_output::end_comment()
+{
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ }
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::comment_arg(const char *s)
+{
+ int len = strlen(s);
+ if (col + len + 1 > max_line_length) {
+ putc('\n', fp);
+ fputs("%%+", fp);
+ col = 3;
+ }
+ putc(' ', fp);
+ fputs(s, fp);
+ col += len + 1;
+ return *this;
+}
+
+ps_output &ps_output::set_fixed_point(int n)
+{
+ assert(n >= 0 && n <= 10);
+ fixed_point = n;
+ return *this;
+}
+
+ps_output &ps_output::put_delimiter(char c)
+{
+ if (col + 1 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc(c, fp);
+ col++;
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::put_string(const char *s, int n)
+{
+ int len = 0;
+ for (int i = 0; i < n; i++) {
+ char c = s[i];
+ if (isascii(c) && isprint(c)) {
+ if (c == '(' || c == ')' || c == '\\')
+ len += 2;
+ else
+ len += 1;
+ }
+ else
+ len += 4;
+ }
+ if (len > n*2) {
+ if (col + n*2 + 2 > max_line_length && n*2 + 2 <= max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ if (col + 1 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc('<', fp);
+ col++;
+ for (i = 0; i < n; i++) {
+ if (col + 2 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ fprintf(fp, "%02x", s[i] & 0377);
+ col += 2;
+ }
+ putc('>', fp);
+ col++;
+ }
+ else {
+ if (col + len + 2 > max_line_length && len + 2 <= max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ if (col + 2 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc('(', fp);
+ col++;
+ for (i = 0; i < n; i++) {
+ char c = s[i];
+ if (isascii(c) && isprint(c)) {
+ if (c == '(' || c == ')' || c == '\\')
+ len = 2;
+ else
+ len = 1;
+ }
+ else
+ len = 4;
+ if (col + len + 1 > max_line_length) {
+ putc('\\', fp);
+ putc('\n', fp);
+ col = 0;
+ }
+ switch (len) {
+ case 1:
+ putc(c, fp);
+ break;
+ case 2:
+ putc('\\', fp);
+ putc(c, fp);
+ break;
+ case 4:
+ fprintf(fp, "\\%03o", c & 0377);
+ break;
+ default:
+ assert(0);
+ }
+ col += len;
+ }
+ putc(')', fp);
+ col++;
+ }
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::put_number(int n)
+{
+ char buf[1 + INT_DIGITS + 1];
+ sprintf(buf, "%d", n);
+ int len = strlen(buf);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(buf, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_fix_number(int i)
+{
+ const char *p = iftoa(i, fixed_point);
+ int len = strlen(p);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(p, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_float(double d)
+{
+ char buf[128];
+ sprintf(buf, "%.4f", d);
+ int len = strlen(buf);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(buf, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_symbol(const char *s)
+{
+ int len = strlen(s);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(s, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_literal_symbol(const char *s)
+{
+ int len = strlen(s);
+ if (col > 0 && col + len + 1 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc('/', fp);
+ fputs(s, fp);
+ col += len + 1;
+ need_space = 1;
+ return *this;
+}
+
+class ps_font : public font {
+ ps_font(const char *);
+public:
+ int encoding_index;
+ char *encoding;
+ char *reencoded_name;
+ ~ps_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static ps_font *load_ps_font(const char *);
+};
+
+ps_font *ps_font::load_ps_font(const char *s)
+{
+ ps_font *f = new ps_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+ps_font::ps_font(const char *nm)
+: font(nm), encoding(0), reencoded_name(0), encoding_index(-1)
+{
+}
+
+ps_font::~ps_font()
+{
+ a_delete encoding;
+ a_delete reencoded_name;
+}
+
+void ps_font::handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "encoding") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`encoding' command requires an argument");
+ else
+ encoding = strsave(arg);
+ }
+}
+
+static void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "broken") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`broken' command requires an argument");
+ else if (!bflag)
+ broken_flags = atoi(arg);
+ }
+}
+
+struct style {
+ font *f;
+ int point_size;
+ int height;
+ int slant;
+ style();
+ style(font *, int, int, int);
+ int operator==(const style &) const;
+ int operator!=(const style &) const;
+};
+
+style::style() : f(0)
+{
+}
+
+style::style(font *p, int sz, int h, int sl)
+: f(p), point_size(sz), height(h), slant(sl)
+{
+}
+
+int style::operator==(const style &s) const
+{
+ return (f == s.f && point_size == s.point_size
+ && height == s.height && slant == s.slant);
+}
+
+int style::operator!=(const style &s) const
+{
+ return !(*this == s);
+}
+
+class ps_printer : public printer {
+ FILE *tempfp;
+ ps_output out;
+ int res;
+ int space_char_index;
+ int pages_output;
+ int paper_length;
+ int equalise_spaces;
+ enum { SBUF_SIZE = 256 };
+ char sbuf[SBUF_SIZE];
+ int sbuf_len;
+ int sbuf_start_hpos;
+ int sbuf_vpos;
+ int sbuf_end_hpos;
+ int sbuf_space_width;
+ int sbuf_space_count;
+ int sbuf_space_diff_count;
+ int sbuf_space_code;
+ int sbuf_kern;
+ style sbuf_style;
+ style output_style;
+ int output_hpos;
+ int output_vpos;
+ int output_draw_point_size;
+ int line_thickness;
+ int output_line_thickness;
+ int fill;
+ unsigned char output_space_code;
+ enum { MAX_DEFINED_STYLES = 50 };
+ style defined_styles[MAX_DEFINED_STYLES];
+ int ndefined_styles;
+ int next_encoding_index;
+ string defs;
+ int ndefs;
+ resource_manager rm;
+ int invis_count;
+
+ void flush_sbuf();
+ void set_style(const style &);
+ void set_space_code(unsigned char c);
+ int set_encoding_index(ps_font *);
+ void do_exec(char *, const environment *);
+ void do_import(char *, const environment *);
+ void do_def(char *, const environment *);
+ void do_mdef(char *, const environment *);
+ void do_file(char *, const environment *);
+ void do_invis(char *, const environment *);
+ void do_endinvis(char *, const environment *);
+ void set_line_thickness(const environment *);
+ void fill_path();
+ void encode_fonts();
+ void define_encoding(const char *, int);
+ void reencode_font(ps_font *);
+public:
+ ps_printer();
+ ~ps_printer();
+ void set_char(int i, font *f, const environment *env, int w);
+ void draw(int code, int *p, int np, const environment *env);
+ void begin_page(int);
+ void end_page(int);
+ void special(char *arg, const environment *env);
+ font *make_font(const char *);
+ void end_of_line();
+};
+
+ps_printer::ps_printer()
+: pages_output(0),
+ sbuf_len(0),
+ output_hpos(-1),
+ output_vpos(-1),
+ out(0, 79),
+ ndefined_styles(0),
+ next_encoding_index(0),
+ line_thickness(-1),
+ fill(FILL_MAX + 1),
+ ndefs(0),
+ invis_count(0)
+{
+ tempfp = xtmpfile();
+ out.set_file(tempfp);
+ if (linewidth < 0)
+ linewidth = DEFAULT_LINEWIDTH;
+ if (font::hor != 1)
+ fatal("horizontal resolution must be 1");
+ if (font::vert != 1)
+ fatal("vertical resolution must be 1");
+ if (font::res % (font::sizescale*72) != 0)
+ fatal("res must be a multiple of 72*sizescale");
+ int r = font::res;
+ int point = 0;
+ while (r % 10 == 0) {
+ r /= 10;
+ point++;
+ }
+ res = r;
+ out.set_fixed_point(point);
+ space_char_index = font::name_to_index("space");
+ paper_length = font::paperlength;
+ if (paper_length == 0)
+ paper_length = 11*font::res;
+ equalise_spaces = font::res >= 72000;
+}
+
+int ps_printer::set_encoding_index(ps_font *f)
+{
+ if (f->encoding_index >= 0)
+ return f->encoding_index;
+ for (font_pointer_list *p = font_list; p; p = p->next)
+ if (p->p != f) {
+ char *encoding = ((ps_font *)p->p)->encoding;
+ int encoding_index = ((ps_font *)p->p)->encoding_index;
+ if (encoding != 0 && encoding_index >= 0
+ && strcmp(f->encoding, encoding) == 0) {
+ return f->encoding_index = encoding_index;
+ }
+ }
+ return f->encoding_index = next_encoding_index++;
+}
+
+void ps_printer::set_char(int i, font *f, const environment *env, int w)
+{
+ if (i == space_char_index || invis_count > 0)
+ return;
+ unsigned char code = f->get_code(i);
+ style sty(f, env->size, env->height, env->slant);
+ if (sty.slant != 0) {
+ if (sty.slant > 80 || sty.slant < -80) {
+ error("silly slant `%1' degrees", sty.slant);
+ sty.slant = 0;
+ }
+ }
+ if (sbuf_len > 0) {
+ if (sbuf_len < SBUF_SIZE
+ && sty == sbuf_style
+ && sbuf_vpos == env->vpos) {
+ if (sbuf_end_hpos == env->hpos) {
+ sbuf[sbuf_len++] = code;
+ sbuf_end_hpos += w + sbuf_kern;
+ return;
+ }
+ if (sbuf_len == 1 && sbuf_kern == 0) {
+ sbuf_kern = env->hpos - sbuf_end_hpos;
+ sbuf_end_hpos = env->hpos + sbuf_kern + w;
+ sbuf[sbuf_len++] = code;
+ return;
+ }
+ /* If sbuf_end_hpos - sbuf_kern == env->hpos, we are better off
+ starting a new string. */
+ if (sbuf_len < SBUF_SIZE - 1 && env->hpos >= sbuf_end_hpos
+ && (sbuf_kern == 0 || sbuf_end_hpos - sbuf_kern != env->hpos)) {
+ if (sbuf_space_code < 0) {
+ if (f->contains(space_char_index)) {
+ sbuf_space_code = f->get_code(space_char_index);
+ sbuf_space_width = env->hpos - sbuf_end_hpos;
+ sbuf_end_hpos = env->hpos + w + sbuf_kern;
+ sbuf[sbuf_len++] = sbuf_space_code;
+ sbuf[sbuf_len++] = code;
+ sbuf_space_count++;
+ return;
+ }
+ }
+ else {
+ int diff = env->hpos - sbuf_end_hpos - sbuf_space_width;
+ if (diff == 0 || (equalise_spaces && (diff == 1 || diff == -1))) {
+ sbuf_end_hpos = env->hpos + w + sbuf_kern;
+ sbuf[sbuf_len++] = sbuf_space_code;
+ sbuf[sbuf_len++] = code;
+ sbuf_space_count++;
+ if (diff == 1)
+ sbuf_space_diff_count++;
+ else if (diff == -1)
+ sbuf_space_diff_count--;
+ return;
+ }
+ }
+ }
+ }
+ flush_sbuf();
+ }
+ sbuf_len = 1;
+ sbuf[0] = code;
+ sbuf_end_hpos = env->hpos + w;
+ sbuf_start_hpos = env->hpos;
+ sbuf_vpos = env->vpos;
+ sbuf_style = sty;
+ sbuf_space_code = -1;
+ sbuf_space_width = 0;
+ sbuf_space_count = sbuf_space_diff_count = 0;
+ sbuf_kern = 0;
+}
+
+int is_small_h(int n)
+{
+ return n < (font::res*2)/72 && n > -(font::res*10)/72;
+}
+
+int is_small_v(int n)
+{
+ return n < (font::res*4)/72 && n > -(font::res*4)/72;
+}
+
+static char *make_encoding_name(int encoding_index)
+{
+ static char buf[3 + INT_DIGITS + 1];
+ sprintf(buf, "ENC%d", encoding_index);
+ return buf;
+}
+
+const char *const WS = " \t\n\r";
+
+void ps_printer::define_encoding(const char *encoding, int encoding_index)
+{
+ char *vec[256];
+ for (int i = 0; i < 256; i++)
+ vec[i] = 0;
+ char *path;
+ FILE *fp = font::open_file(encoding, &path);
+ if (fp == 0)
+ fatal("can't open encoding file `%1'", encoding);
+ int lineno = 1;
+ char buf[256];
+ while (fgets(buf, 512, fp) != 0) {
+ char *p = buf;
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) {
+ char *q = strtok(0, WS);
+ int n;
+ if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256)
+ fatal_with_file_and_line(path, lineno, "bad second field");
+ vec[n] = new char[strlen(p) + 1];
+ strcpy(vec[n], p);
+ }
+ lineno++;
+ }
+ a_delete path;
+ out.put_literal_symbol(make_encoding_name(encoding_index));
+ out.put_delimiter('[');
+ for (i = 0; i < 256; i++) {
+ if (vec[i] == 0)
+ out.put_literal_symbol(".notdef");
+ else {
+ out.put_literal_symbol(vec[i]);
+ a_delete vec[i];
+ }
+ }
+ out.put_delimiter(']').put_symbol("def");
+}
+
+void ps_printer::reencode_font(ps_font *f)
+{
+ out.put_literal_symbol(f->reencoded_name)
+ .put_symbol(make_encoding_name(f->encoding_index))
+ .put_literal_symbol(f->get_internal_name())
+ .put_symbol("RE");
+}
+
+void ps_printer::encode_fonts()
+{
+ if (next_encoding_index == 0)
+ return;
+ char *done_encoding = new char[next_encoding_index];
+ for (int i = 0; i < next_encoding_index; i++)
+ done_encoding[i] = 0;
+ for (font_pointer_list *f = font_list; f; f = f->next) {
+ int encoding_index = ((ps_font *)f->p)->encoding_index;
+ if (encoding_index >= 0) {
+ assert(encoding_index < next_encoding_index);
+ if (!done_encoding[encoding_index]) {
+ done_encoding[encoding_index] = 1;
+ define_encoding(((ps_font *)f->p)->encoding, encoding_index);
+ }
+ reencode_font((ps_font *)f->p);
+ }
+ }
+ a_delete done_encoding;
+}
+
+void ps_printer::set_style(const style &sty)
+{
+ char buf[1 + INT_DIGITS + 1];
+ for (int i = 0; i < ndefined_styles; i++)
+ if (sty == defined_styles[i]) {
+ sprintf(buf, "F%d", i);
+ out.put_symbol(buf);
+ return;
+ }
+ if (ndefined_styles >= MAX_DEFINED_STYLES)
+ ndefined_styles = 0;
+ sprintf(buf, "F%d", ndefined_styles);
+ out.put_literal_symbol(buf);
+ const char *psname = sty.f->get_internal_name();
+ if (psname == 0)
+ fatal("no internalname specified for font `%1'", sty.f->get_name());
+ char *encoding = ((ps_font *)sty.f)->encoding;
+ if (encoding != 0) {
+ char *s = ((ps_font *)sty.f)->reencoded_name;
+ if (s == 0) {
+ int ei = set_encoding_index((ps_font *)sty.f);
+ char *tem = new char[strlen(psname) + 1 + INT_DIGITS + 1];
+ sprintf(tem, "%s@%d", psname, ei);
+ psname = tem;
+ ((ps_font *)sty.f)->reencoded_name = tem;
+ }
+ else
+ psname = s;
+ }
+ out.put_fix_number((font::res/(72*font::sizescale))*sty.point_size);
+ if (sty.height != 0 || sty.slant != 0) {
+ int h = sty.height == 0 ? sty.point_size : sty.height;
+ h *= font::res/(72*font::sizescale);
+ int c = int(h*tan(radians(sty.slant)) + .5);
+ out.put_fix_number(c).put_fix_number(h).put_literal_symbol(psname)
+ .put_symbol("MF");
+ }
+ else {
+ out.put_literal_symbol(psname).put_symbol("SF");
+ }
+ defined_styles[ndefined_styles++] = sty;
+}
+
+void ps_printer::set_space_code(unsigned char c)
+{
+ out.put_literal_symbol("SC").put_number(c).put_symbol("def");
+}
+
+void ps_printer::end_of_line()
+{
+ flush_sbuf();
+ // this ensures that we do an absolute motion to the beginning of a line
+ output_vpos = output_hpos = -1;
+}
+
+void ps_printer::flush_sbuf()
+{
+ enum {
+ NONE,
+ RELATIVE_H,
+ RELATIVE_V,
+ RELATIVE_HV,
+ ABSOLUTE
+ } motion = NONE;
+ int space_flag = 0;
+ if (sbuf_len == 0)
+ return;
+ if (output_style != sbuf_style) {
+ set_style(sbuf_style);
+ output_style = sbuf_style;
+ }
+ int extra_space = 0;
+ if (output_hpos < 0 || output_vpos < 0
+ || !is_small_h(output_hpos - sbuf_start_hpos)
+ || !is_small_v(output_vpos - sbuf_vpos))
+ motion = ABSOLUTE;
+ else {
+ if (output_hpos != sbuf_start_hpos)
+ motion = RELATIVE_H;
+ if (output_vpos != sbuf_vpos) {
+ if (motion != NONE)
+ motion = RELATIVE_HV;
+ else
+ motion = RELATIVE_V;
+ }
+ }
+ if (sbuf_space_code >= 0) {
+ int w = sbuf_style.f->get_width(space_char_index, sbuf_style.point_size);
+ if (w + sbuf_kern != sbuf_space_width) {
+ if (sbuf_space_code != output_space_code) {
+ set_space_code(sbuf_space_code);
+ output_space_code = sbuf_space_code;
+ }
+ space_flag = 1;
+ extra_space = sbuf_space_width - w - sbuf_kern;
+ if (sbuf_space_diff_count > sbuf_space_count/2)
+ extra_space++;
+ else if (sbuf_space_diff_count < -(sbuf_space_count/2))
+ extra_space--;
+ }
+ }
+ if (space_flag)
+ out.put_fix_number(extra_space);
+ if (sbuf_kern != 0)
+ out.put_fix_number(sbuf_kern);
+ out.put_string(sbuf, sbuf_len);
+ char sym[2];
+ sym[0] = 'A' + motion*4 + space_flag + 2*(sbuf_kern != 0);
+ sym[1] = '\0';
+ switch (motion) {
+ case NONE:
+ break;
+ case ABSOLUTE:
+ out.put_fix_number(sbuf_start_hpos)
+ .put_fix_number(sbuf_vpos);
+ break;
+ case RELATIVE_H:
+ out.put_fix_number(sbuf_start_hpos - output_hpos);
+ break;
+ case RELATIVE_V:
+ out.put_fix_number(sbuf_vpos - output_vpos);
+ break;
+ case RELATIVE_HV:
+ out.put_fix_number(sbuf_start_hpos - output_hpos)
+ .put_fix_number(sbuf_vpos - output_vpos);
+ break;
+ default:
+ assert(0);
+ }
+ out.put_symbol(sym);
+ output_hpos = sbuf_end_hpos;
+ output_vpos = sbuf_vpos;
+ sbuf_len = 0;
+}
+
+
+void ps_printer::set_line_thickness(const environment *env)
+{
+ if (line_thickness < 0) {
+ if (output_draw_point_size != env->size) {
+ // we ought to check for overflow here
+ int lw = ((font::res/(72*font::sizescale))*linewidth*env->size)/1000;
+ out.put_fix_number(lw).put_symbol("LW");
+ output_draw_point_size = env->size;
+ output_line_thickness = -1;
+ }
+ }
+ else {
+ if (output_line_thickness != line_thickness) {
+ out.put_fix_number(line_thickness).put_symbol("LW");
+ output_line_thickness = line_thickness;
+ output_draw_point_size = -1;
+ }
+ }
+}
+
+void ps_printer::fill_path()
+{
+ if (fill > FILL_MAX)
+ out.put_symbol("BL");
+ else
+ out.put_float(transform_fill(fill)).put_symbol("FL");
+}
+
+void ps_printer::draw(int code, int *p, int np, const environment *env)
+{
+ if (invis_count > 0)
+ return;
+ int fill_flag = 0;
+ switch (code) {
+ case 'C':
+ fill_flag = 1;
+ // fall through
+ case 'c':
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ out.put_fix_number(env->hpos + p[0]/2)
+ .put_fix_number(env->vpos)
+ .put_fix_number(p[0]/2)
+ .put_symbol("DC");
+ if (fill_flag) {
+ fill_path();
+ }
+ else {
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ case 'l':
+ if (np != 2) {
+ error("2 arguments required for line");
+ break;
+ }
+ set_line_thickness(env);
+ out.put_fix_number(p[0] + env->hpos)
+ .put_fix_number(p[1] + env->vpos)
+ .put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("DL");
+ break;
+ case 'E':
+ fill_flag = 1;
+ // fall through
+ case 'e':
+ if (np != 2) {
+ error("2 arguments required for ellipse");
+ break;
+ }
+ out.put_fix_number(p[0])
+ .put_fix_number(p[1])
+ .put_fix_number(env->hpos + p[0]/2)
+ .put_fix_number(env->vpos)
+ .put_symbol("DE");
+ if (fill_flag) {
+ fill_path();
+ }
+ else {
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ case 'P':
+ fill_flag = 1;
+ // fall through
+ case 'p':
+ {
+ if (np & 1) {
+ error("even number of arguments required for polygon");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for polygon");
+ break;
+ }
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("MT");
+ for (int i = 0; i < np; i += 2)
+ out.put_fix_number(p[i])
+ .put_fix_number(p[i+1])
+ .put_symbol("RL");
+ out.put_symbol("CL");
+ if (fill_flag) {
+ fill_path();
+ }
+ else {
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ }
+ case '~':
+ {
+ if (np & 1) {
+ error("even number of arguments required for spline");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for spline");
+ break;
+ }
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("MT");
+ out.put_fix_number(p[0]/2)
+ .put_fix_number(p[1]/2)
+ .put_symbol("RL");
+ /* tnum/tden should be between 0 and 1; the closer it is to 1
+ the tighter the curve will be to the guiding lines; 2/3
+ is the standard value */
+ const int tnum = 2;
+ const int tden = 3;
+ for (int i = 0; i < np - 2; i += 2) {
+ out.put_fix_number((p[i]*tnum)/(2*tden))
+ .put_fix_number((p[i + 1]*tnum)/(2*tden))
+ .put_fix_number(p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden))
+ .put_fix_number(p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden))
+ .put_fix_number((p[i] - p[i]/2) + p[i + 2]/2)
+ .put_fix_number((p[i + 1] - p[i + 1]/2) + p[i + 3]/2)
+ .put_symbol("RC");
+ }
+ out.put_fix_number(p[np - 2] - p[np - 2]/2)
+ .put_fix_number(p[np - 1] - p[np - 1]/2)
+ .put_symbol("RL");
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ case 'a':
+ {
+ if (np != 4) {
+ error("4 arguments required for arc");
+ break;
+ }
+ set_line_thickness(env);
+ double c[2];
+ if (adjust_arc_center(p, c))
+ out.put_fix_number(env->hpos + int(c[0]))
+ .put_fix_number(env->vpos + int(c[1]))
+ .put_fix_number(int(sqrt(c[0]*c[0] + c[1]*c[1])))
+ .put_float(degrees(atan2(-c[1], -c[0])))
+ .put_float(degrees(atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0])))
+ .put_symbol("DA");
+ else
+ out.put_fix_number(p[0] + p[2] + env->hpos)
+ .put_fix_number(p[1] + p[3] + env->vpos)
+ .put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("DL");
+ }
+ break;
+ case 't':
+ {
+ if (np == 0) {
+ line_thickness = -1;
+ }
+ else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2) {
+ error("0 or 1 argument required for thickness");
+ break;
+ }
+ line_thickness = p[0];
+ }
+ break;
+ }
+ case 'f':
+ {
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ }
+ fill = p[0];
+ if (fill < 0 || fill > FILL_MAX) {
+ // This means fill with the current color.
+ fill = FILL_MAX + 1;
+ }
+ break;
+ }
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+
+ output_hpos = output_vpos = -1;
+}
+
+
+void ps_printer::begin_page(int n)
+{
+ out.begin_comment("Page:").comment_arg(itoa(n));
+ out.comment_arg(itoa(++pages_output)).end_comment();
+ output_style.f = 0;
+ output_space_code = 32;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ output_hpos = output_vpos = -1;
+ ndefined_styles = 0;
+ out.simple_comment("BeginPageSetup");
+ out.put_symbol("BP");
+ out.simple_comment("EndPageSetup");
+}
+
+void ps_printer::end_page(int)
+{
+ flush_sbuf();
+ out.put_symbol("EP");
+ if (invis_count != 0) {
+ error("missing `endinvis' command");
+ invis_count = 0;
+ }
+}
+
+font *ps_printer::make_font(const char *nm)
+{
+ return ps_font::load_ps_font(nm);
+}
+
+ps_printer::~ps_printer()
+{
+ out.simple_comment("Trailer");
+ out.put_symbol("end");
+ out.simple_comment("EOF");
+ if (fseek(tempfp, 0L, 0) < 0)
+ fatal("fseek on temporary file failed");
+ fputs("%!PS-Adobe-", stdout);
+ fputs((broken_flags & USE_PS_ADOBE_2_0) ? "2.0" : "3.0", stdout);
+ putchar('\n');
+ out.set_file(stdout);
+ {
+ extern const char *version_string;
+ out.begin_comment("Creator:")
+ .comment_arg("groff")
+ .comment_arg("version")
+ .comment_arg(version_string)
+ .end_comment();
+ }
+ for (font_pointer_list *f = font_list; f; f = f->next) {
+ ps_font *psf = (ps_font *)(f->p);
+ rm.need_font(psf->get_internal_name());
+ }
+ rm.print_header_comments(out);
+ out.begin_comment("Pages:").comment_arg(itoa(pages_output)).end_comment();
+ out.begin_comment("PageOrder:").comment_arg("Ascend").end_comment();
+#if 0
+ fprintf(out.get_file(), "%%%%DocumentMedia: () %g %g 0 () ()\n",
+ font::paperwidth*72.0/font::res,
+ paper_length*72.0/font::res);
+#endif
+ out.begin_comment("Orientation:")
+ .comment_arg(landscape_flag ? "Landscape" : "Portrait")
+ .end_comment();
+ if (ncopies != 1) {
+ out.end_line();
+ fprintf(out.get_file(), "%%%%Requirements: numcopies(%d)\n", ncopies);
+ }
+ out.simple_comment("EndComments");
+ out.simple_comment("BeginProlog");
+ rm.output_prolog(out);
+ if (!(broken_flags & NO_SETUP_SECTION)) {
+ out.simple_comment("EndProlog");
+ out.simple_comment("BeginSetup");
+ }
+ rm.document_setup(out);
+ out.put_symbol(dict_name).put_symbol("begin");
+ if (ndefs > 0)
+ ndefs += DEFS_DICT_SPARE;
+ out.put_literal_symbol(defs_dict_name)
+ .put_number(ndefs + 1)
+ .put_symbol("dict")
+ .put_symbol("def");
+ out.put_symbol(defs_dict_name)
+ .put_symbol("begin");
+ out.put_literal_symbol("u")
+ .put_delimiter('{')
+ .put_fix_number(1)
+ .put_symbol("mul")
+ .put_delimiter('}')
+ .put_symbol("bind")
+ .put_symbol("def");
+ defs += '\0';
+ out.special(defs.contents());
+ out.put_symbol("end");
+ if (ncopies != 1)
+ out.put_literal_symbol("#copies").put_number(ncopies).put_symbol("def");
+ out.put_literal_symbol("RES").put_number(res).put_symbol("def");
+ out.put_literal_symbol("PL");
+ if (guess_flag)
+ out.put_symbol("PLG");
+ else
+ out.put_fix_number(paper_length);
+ out.put_symbol("def");
+ out.put_literal_symbol("LS")
+ .put_symbol(landscape_flag ? "true" : "false")
+ .put_symbol("def");
+ encode_fonts();
+ out.simple_comment((broken_flags & NO_SETUP_SECTION)
+ ? "EndProlog"
+ : "EndSetup");
+ out.end_line();
+ out.copy_file(tempfp);
+ fclose(tempfp);
+}
+
+void ps_printer::special(char *arg, const environment *env)
+{
+ typedef void (ps_printer::*SPECIAL_PROCP)(char *, const environment *);
+ static struct {
+ const char *name;
+ SPECIAL_PROCP proc;
+ } proc_table[] = {
+ "exec", &ps_printer::do_exec,
+ "def", &ps_printer::do_def,
+ "mdef", &ps_printer::do_mdef,
+ "import", &ps_printer::do_import,
+ "file", &ps_printer::do_file,
+ "invis", &ps_printer::do_invis,
+ "endinvis", &ps_printer::do_endinvis,
+ };
+ for (char *p = arg; *p == ' ' || *p == '\n'; p++)
+ ;
+ char *tag = p;
+ for (; *p != '\0' && *p != ':' && *p != ' ' && *p != '\n'; p++)
+ ;
+ if (*p == '\0' || strncmp(tag, "ps", p - tag) != 0) {
+ error("X command without `ps:' tag ignored");
+ return;
+ }
+ p++;
+ for (; *p == ' ' || *p == '\n'; p++)
+ ;
+ char *command = p;
+ for (; *p != '\0' && *p != ' ' && *p != '\n'; p++)
+ ;
+ if (*command == '\0') {
+ error("X command without `ps:' tag ignored");
+ return;
+ }
+ for (int i = 0; i < sizeof(proc_table)/sizeof(proc_table[0]); i++)
+ if (strncmp(command, proc_table[i].name, p - command) == 0) {
+ (this->*(proc_table[i].proc))(p, env);
+ return;
+ }
+ error("X command `%1' not recognised", command);
+}
+
+// A conforming PostScript document must not have lines longer
+// than 255 characters (excluding line termination characters).
+
+static int check_line_lengths(const char *p)
+{
+ for (;;) {
+ const char *end = strchr(p, '\n');
+ if (end == 0)
+ end = strchr(p, '\0');
+ if (end - p > 255)
+ return 0;
+ if (*end == '\0')
+ break;
+ p = end + 1;
+ }
+ return 1;
+}
+
+void ps_printer::do_exec(char *arg, const environment *env)
+{
+ flush_sbuf();
+ while (csspace(*arg))
+ arg++;
+ if (*arg == '\0') {
+ error("missing argument to X exec command");
+ return;
+ }
+ if (!check_line_lengths(arg)) {
+ error("lines in X exec command must not be more than 255 characters long");
+ return;
+ }
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("EBEGIN")
+ .special(arg)
+ .put_symbol("EEND");
+ output_hpos = output_vpos = -1;
+ output_style.f = 0;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ ndefined_styles = 0;
+ if (!ndefs)
+ ndefs = 1;
+}
+
+void ps_printer::do_file(char *arg, const environment *env)
+{
+ flush_sbuf();
+ while (csspace(*arg))
+ arg++;
+ if (*arg == '\0') {
+ error("missing argument to X file command");
+ return;
+ }
+ const char *filename = arg;
+ do {
+ ++arg;
+ } while (*arg != '\0' && *arg != ' ' && *arg != '\n');
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("EBEGIN");
+ rm.import_file(filename, out);
+ out.put_symbol("EEND");
+ output_hpos = output_vpos = -1;
+ output_style.f = 0;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ ndefined_styles = 0;
+ if (!ndefs)
+ ndefs = 1;
+}
+
+void ps_printer::do_def(char *arg, const environment *)
+{
+ flush_sbuf();
+ while (csspace(*arg))
+ arg++;
+ if (!check_line_lengths(arg)) {
+ error("lines in X def command must not be more than 255 characters long");
+ return;
+ }
+ defs += arg;
+ if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
+ defs += '\n';
+ ndefs++;
+}
+
+// Like def, but the first argument says how many definitions it contains.
+
+void ps_printer::do_mdef(char *arg, const environment *)
+{
+ flush_sbuf();
+ char *p;
+ int n = (int)strtol(arg, &p, 10);
+ if (n == 0 && p == arg) {
+ error("first argument to X mdef must be an integer");
+ return;
+ }
+ if (n < 0) {
+ error("out of range argument `%1' to X mdef command", int(n));
+ return;
+ }
+ arg = p;
+ while (csspace(*arg))
+ arg++;
+ if (!check_line_lengths(arg)) {
+ error("lines in X mdef command must not be more than 255 characters long");
+ return;
+ }
+ defs += arg;
+ if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
+ defs += '\n';
+ ndefs += n;
+}
+
+void ps_printer::do_import(char *arg, const environment *env)
+{
+ flush_sbuf();
+ while (*arg == ' ' || *arg == '\n')
+ arg++;
+ for (char *p = arg; *p != '\0' && *p != ' ' && *p != '\n'; p++)
+ ;
+ if (*p != '\0')
+ *p++ = '\0';
+ int parms[6];
+ int nparms = 0;
+ while (nparms < 6) {
+ char *end;
+ long n = strtol(p, &end, 10);
+ if (n == 0 && end == p)
+ break;
+ parms[nparms++] = int(n);
+ p = end;
+ }
+ if (csalpha(*p) && (p[1] == '\0' || p[1] == ' ' || p[1] == '\n')) {
+ error("scaling indicators not allowed in arguments for X import command");
+ return;
+ }
+ while (*p == ' ' || *p == '\n')
+ p++;
+ if (nparms < 5) {
+ if (*p == '\0')
+ error("too few arguments for X import command");
+ else
+ error("invalid argument `%1' for X import command", p);
+ return;
+ }
+ if (*p != '\0') {
+ error("superflous argument `%1' for X import command", p);
+ return;
+ }
+ int llx = parms[0];
+ int lly = parms[1];
+ int urx = parms[2];
+ int ury = parms[3];
+ int desired_width = parms[4];
+ int desired_height = parms[5];
+ if (desired_width <= 0) {
+ error("bad width argument `%1' for X import command: must be > 0",
+ desired_width);
+ return;
+ }
+ if (nparms == 6 && desired_height <= 0) {
+ error("bad height argument `%1' for X import command: must be > 0",
+ desired_height);
+ return;
+ }
+ if (llx == urx) {
+ error("llx and urx arguments for X import command must not be equal");
+ return;
+ }
+ if (lly == ury) {
+ error("lly and ury arguments for X import command must not be equal");
+ return;
+ }
+ if (nparms == 5) {
+ int old_wid = urx - llx;
+ int old_ht = ury - lly;
+ if (old_wid < 0)
+ old_wid = -old_wid;
+ if (old_ht < 0)
+ old_ht = -old_ht;
+ desired_height = int(desired_width*(double(old_ht)/double(old_wid)) + .5);
+ }
+ if (env->vpos - desired_height < 0)
+ warning("top of imported graphic is above the top of the page");
+ out.put_number(llx)
+ .put_number(lly)
+ .put_fix_number(desired_width)
+ .put_number(urx - llx)
+ .put_fix_number(-desired_height)
+ .put_number(ury - lly)
+ .put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("PBEGIN");
+ rm.import_file(arg, out);
+ // do this here just in case application defines PEND
+ out.put_symbol("end");
+ out.put_symbol("PEND");
+}
+
+void ps_printer::do_invis(char *, const environment *)
+{
+ invis_count++;
+}
+
+void ps_printer::do_endinvis(char *, const environment *)
+{
+ if (invis_count == 0)
+ error("unbalanced `endinvis' command");
+ else
+ --invis_count;
+}
+
+printer *make_printer()
+{
+ return new ps_printer;
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:glc:w:vb:")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "grops version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'c':
+ if (sscanf(optarg, "%d", &ncopies) != 1 || ncopies <= 0) {
+ error("bad number of copies `%s'", optarg);
+ ncopies = 1;
+ }
+ break;
+ case 'g':
+ guess_flag = 1;
+ break;
+ case 'l':
+ landscape_flag = 1;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'w':
+ if (sscanf(optarg, "%d", &linewidth) != 1 || linewidth < 0) {
+ error("bad linewidth `%s'", optarg);
+ linewidth = -1;
+ }
+ break;
+ case 'b':
+ // XXX check this
+ broken_flags = atoi(optarg);
+ bflag = 1;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ font::set_unknown_desc_command_handler(handle_unknown_desc_command);
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ exit(0);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-glv] [-b n] [-c n] [-w n] [-F dir] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/gnu/usr.bin/groff/grops/ps.h b/gnu/usr.bin/groff/grops/ps.h
new file mode 100644
index 000000000000..50be4e8ba4b6
--- /dev/null
+++ b/gnu/usr.bin/groff/grops/ps.h
@@ -0,0 +1,122 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+class ps_output {
+public:
+ ps_output(FILE *, int max_line_length);
+ ps_output &put_string(const char *, int);
+ ps_output &put_number(int);
+ ps_output &put_fix_number(int);
+ ps_output &put_float(double);
+ ps_output &put_symbol(const char *);
+ ps_output &put_literal_symbol(const char *);
+ ps_output &set_fixed_point(int);
+ ps_output &simple_comment(const char *);
+ ps_output &begin_comment(const char *);
+ ps_output &comment_arg(const char *);
+ ps_output &end_comment();
+ ps_output &set_file(FILE *);
+ ps_output &include_file(FILE *);
+ ps_output &copy_file(FILE *);
+ ps_output &end_line();
+ ps_output &put_delimiter(char);
+ ps_output &special(const char *);
+ FILE *get_file();
+private:
+ FILE *fp;
+ int col;
+ int max_line_length; // not including newline
+ int need_space;
+ int fixed_point;
+};
+
+inline FILE *ps_output::get_file()
+{
+ return fp;
+}
+
+enum resource_type {
+ RESOURCE_FONT,
+ RESOURCE_PROCSET,
+ RESOURCE_FILE,
+ RESOURCE_ENCODING,
+ RESOURCE_FORM,
+ RESOURCE_PATTERN
+ };
+
+struct resource;
+
+extern string an_empty_string;
+
+class resource_manager {
+public:
+ resource_manager();
+ ~resource_manager();
+ void import_file(const char *filename, ps_output &);
+ void need_font(const char *name);
+ void print_header_comments(ps_output &);
+ void document_setup(ps_output &);
+ void output_prolog(ps_output &);
+private:
+ unsigned extensions;
+ unsigned language_level;
+ resource *procset_resource;
+ resource *resource_list;
+ resource *lookup_resource(resource_type type, string &name,
+ string &version = an_empty_string,
+ unsigned revision = 0);
+ resource *lookup_font(const char *name);
+ void read_download_file();
+ void supply_resource(resource *r, int rank, FILE *outfp,
+ int is_document = 0);
+ void process_file(int rank, FILE *fp, const char *filename, FILE *outfp);
+ resource *read_file_arg(const char **);
+ resource *read_procset_arg(const char **);
+ resource *read_font_arg(const char **);
+ resource *read_resource_arg(const char **);
+ void print_resources_comment(unsigned flag, FILE *outfp);
+ void print_extensions_comment(FILE *outfp);
+ void print_language_level_comment(FILE *outfp);
+ int do_begin_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_document(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_document(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_procset(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_procset(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_font(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_font(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_file(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_file(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int change_to_end_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_preview(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_data(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_binary(const char *ptr, int rank, FILE *fp, FILE *outfp);
+};
+
+extern unsigned broken_flags;
+
+// broken_flags is ored from these
+
+enum {
+ NO_SETUP_SECTION = 01,
+ STRIP_PERCENT_BANG = 02,
+ STRIP_STRUCTURE_COMMENTS = 04,
+ USE_PS_ADOBE_2_0 = 010
+};
diff --git a/gnu/usr.bin/groff/grops/psfig.diff b/gnu/usr.bin/groff/grops/psfig.diff
new file mode 100644
index 000000000000..77217742dcd9
--- /dev/null
+++ b/gnu/usr.bin/groff/grops/psfig.diff
@@ -0,0 +1,106 @@
+These are patches to makes psfig work with groff. They apply to the
+version of psfig in comp.sources.unix/Volume11. After applying them,
+psfig should be recompiled with -DGROFF. The resulting psfig will
+work only with groff, so you might want to install it under a
+different name. The output of this psfig must be processed using the
+macros in the file ../macros/tmac.psfig. These will automatically add
+the necessary PostScript code to the prologue output by grops. Use of
+the `global' feature in psfig will result in non-conformant PostScript
+which will fail if processed by a page reversal program. Note that
+psfig is unsupported by me (I'm not interested in hearing about psfig
+problems.) For new documents, I recommend using the PostScript
+inclusion features provided by grops.
+
+James Clark
+jjc@jclark.com
+
+*** cmds.c.~1~ Thu Feb 14 16:09:45 1991
+--- cmds.c Mon Mar 4 12:49:26 1991
+***************
+*** 245,253 ****
+--- 245,261 ----
+ (void) sprintf(x, "%.2fp", fx);
+ (void) sprintf(y, "%.2fp", fy);
+ } else if (!*x) {
++ #ifndef GROFF
+ (void) sprintf(x,"(%.2fp*%s/%.2fp)", fx, y, fy);
++ #else /* GROFF */
++ (void) sprintf(x,"(%.0fu*%s/%.0fu)", fx, y, fy);
++ #endif /* GROFF */
+ } else if (!*y) {
++ #ifndef GROFF
+ (void) sprintf(y,"(%.2fp*%s/%.2fp)", fy, x, fx);
++ #else /* GROFF */
++ (void) sprintf(y,"(%.0fu*%s/%.0fu)", fy, x, fx);
++ #endif /* GROFF */
+ }
+
+ /*
+*** troff.c.~1~ Thu Feb 14 16:09:48 1991
+--- troff.c Mon Mar 4 12:48:46 1991
+***************
+*** 26,32 ****
+--- 26,36 ----
+ }
+
+
++ #ifndef GROFF
+ char incl_file_s[] = "\\X'f%s'";
++ #else /* GROFF */
++ char incl_file_s[] = "\\X'ps: file %s'";
++ #endif /* GROFF */
+ includeFile(filenm)
+ char *filenm; {
+ printf(incl_file_s, filenm);
+***************
+*** 40,52 ****
+--- 44,64 ----
+ error("buffer overflow");
+ }
+
++ #ifndef GROFF
+ char endfig_s[] = "\\X'pendFig'";
++ #else /* GROFF */
++ char endfig_s[] = "\\X'ps: exec psfigend'";
++ #endif /* GROFF */
+ endfig() {
+ printf(endfig_s);
+ }
+
+ char startfig_s[] =
++ #ifndef GROFF
+ "\\X'p\\w@\\h@%s@@'\\X'p\\w@\\h@%s@@'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'pstartFig'";
++ #else /* GROFF */
++ "\\X'ps: exec \\w@\\h@%s@@ \\w@\\h@%s@@ %.2f %.2f %.2f %.2f psfigstart'";
++ #endif /* GROFF */
+
+ startfig(x, y, llx, lly, urx, ury)
+ char *x, *y;
+***************
+*** 57,63 ****
+--- 69,79 ----
+ }
+
+ emitDoClip() {
++ #ifndef GROFF
+ printf("\\X'pdoclip'");
++ #else /* GROFF */
++ printf("\\X'ps: exec psfigclip'");
++ #endif /* GROFF */
+ }
+
+ flushX()
+***************
+*** 116,122 ****
+--- 132,142 ----
+
+ #define isWhite(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n')
+
++ #ifndef GROFF
+ char literal_s[] = "\\X'p%s'";
++ #else /* GROFF */
++ char literal_s[] = "\\X'ps: exec %s'";
++ #endif /* GROFF */
+ emitLiteral(text)
+ char *text; {
+ static char litbuf[BUFSZ];
diff --git a/gnu/usr.bin/groff/grops/psrm.cc b/gnu/usr.bin/groff/grops/psrm.cc
new file mode 100644
index 000000000000..5abe683f7213
--- /dev/null
+++ b/gnu/usr.bin/groff/grops/psrm.cc
@@ -0,0 +1,1092 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include "ps.h"
+
+#define PROLOGUE "prologue"
+
+static void print_ps_string(const string &s, FILE *outfp);
+
+cset white_space("\n\r \t");
+string an_empty_string;
+
+const char *extension_table[] = {
+ "DPS",
+ "CMYK",
+ "Composite",
+ "FileSystem",
+};
+
+const int NEXTENSIONS = sizeof(extension_table)/sizeof(extension_table[0]);
+
+const char *resource_table[] = {
+ "font",
+ "procset",
+ "file",
+ "encoding",
+ "form",
+ "pattern",
+};
+
+const int NRESOURCES = sizeof(resource_table)/sizeof(resource_table[0]);
+
+struct resource {
+ resource *next;
+ resource_type type;
+ string name;
+ enum { NEEDED = 01, SUPPLIED = 02, FONT_NEEDED = 04, BUSY = 010 };
+ unsigned flags;
+ string version;
+ unsigned revision;
+ char *filename;
+ int rank;
+ resource(resource_type, string &, string & = an_empty_string, unsigned = 0);
+ ~resource();
+ void print_type_and_name(FILE *outfp);
+};
+
+resource::resource(resource_type t, string &n, string &v, unsigned r)
+: type(t), revision(r), flags (0), filename(0), rank(-1), next(0)
+{
+ name.move(n);
+ version.move(v);
+ if (type == RESOURCE_FILE) {
+ if (name.search('\0') >= 0)
+ error("filename contains a character with code 0");
+ filename = name.extract();
+ }
+}
+
+resource::~resource()
+{
+ a_delete filename;
+}
+
+void resource::print_type_and_name(FILE *outfp)
+{
+ fputs(resource_table[type], outfp);
+ putc(' ', outfp);
+ print_ps_string(name, outfp);
+ if (type == RESOURCE_PROCSET) {
+ putc(' ', outfp);
+ print_ps_string(version, outfp);
+ fprintf(outfp, " %u", revision);
+ }
+}
+
+resource_manager::resource_manager()
+: resource_list(0), extensions(0), language_level(0)
+{
+ read_download_file();
+ string procset_name("grops");
+ extern const char *version_string;
+ string procset_version(version_string);
+ procset_resource = lookup_resource(RESOURCE_PROCSET, procset_name,
+ procset_version, 0);
+ procset_resource->flags |= resource::SUPPLIED;
+}
+
+resource_manager::~resource_manager()
+{
+ while (resource_list) {
+ resource *tem = resource_list;
+ resource_list = resource_list->next;
+ delete tem;
+ }
+}
+
+resource *resource_manager::lookup_resource(resource_type type,
+ string &name,
+ string &version,
+ unsigned revision)
+{
+ for (resource *r = resource_list; r; r = r->next)
+ if (r->type == type
+ && r->name == name
+ && r->version == version
+ && r->revision == revision)
+ return r;
+ r = new resource(type, name, version, revision);
+ r->next = resource_list;
+ resource_list = r;
+ return r;
+}
+
+// Just a specialized version of lookup_resource().
+
+resource *resource_manager::lookup_font(const char *name)
+{
+ for (resource *r = resource_list; r; r = r->next)
+ if (r->type == RESOURCE_FONT
+ && strlen(name) == r->name.length()
+ && memcmp(name, r->name.contents(), r->name.length()) == 0)
+ return r;
+ string s(name);
+ r = new resource(RESOURCE_FONT, s);
+ r->next = resource_list;
+ resource_list = r;
+ return r;
+}
+
+void resource_manager::need_font(const char *name)
+{
+ lookup_font(name)->flags |= resource::FONT_NEEDED;
+}
+
+typedef resource *Presource; // Work around g++ bug.
+
+void resource_manager::document_setup(ps_output &out)
+{
+ int nranks = 0;
+ for (resource *r = resource_list; r; r = r->next)
+ if (r->rank >= nranks)
+ nranks = r->rank + 1;
+ if (nranks > 0) {
+ // Sort resource_list in reverse order of rank.
+ Presource *head = new Presource[nranks + 1];
+ Presource **tail = new Presource *[nranks + 1];
+ for (int i = 0; i < nranks + 1; i++) {
+ head[i] = 0;
+ tail[i] = &head[i];
+ }
+ for (r = resource_list; r; r = r->next) {
+ i = r->rank < 0 ? 0 : r->rank + 1;
+ *tail[i] = r;
+ tail[i] = &(*tail[i])->next;
+ }
+ resource_list = 0;
+ for (i = 0; i < nranks + 1; i++)
+ if (head[i]) {
+ *tail[i] = resource_list;
+ resource_list = head[i];
+ }
+ a_delete head;
+ a_delete tail;
+ // check it
+ for (r = resource_list; r; r = r->next)
+ if (r->next)
+ assert(r->rank >= r->next->rank);
+ for (r = resource_list; r; r = r->next)
+ if (r->type == RESOURCE_FONT && r->rank >= 0)
+ supply_resource(r, -1, out.get_file());
+ }
+}
+
+void resource_manager::print_resources_comment(unsigned flag, FILE *outfp)
+{
+ int continued = 0;
+ for (resource *r = resource_list; r; r = r->next)
+ if (r->flags & flag) {
+ if (continued)
+ fputs("%%+ ", outfp);
+ else {
+ fputs(flag == resource::NEEDED
+ ? "%%DocumentNeededResources: "
+ : "%%DocumentSuppliedResources: ",
+ outfp);
+ continued = 1;
+ }
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+}
+
+void resource_manager::print_header_comments(ps_output &out)
+{
+ for (resource *r = resource_list; r; r = r->next)
+ if (r->type == RESOURCE_FONT && (r->flags & resource::FONT_NEEDED))
+ supply_resource(r, 0, 0);
+ print_resources_comment(resource::NEEDED, out.get_file());
+ print_resources_comment(resource::SUPPLIED, out.get_file());
+ print_language_level_comment(out.get_file());
+ print_extensions_comment(out.get_file());
+}
+
+void resource_manager::output_prolog(ps_output &out)
+{
+ FILE *outfp = out.get_file();
+ out.end_line();
+ char *path;
+ FILE *fp = font::open_file(PROLOGUE, &path);
+ if (!fp)
+ fatal("can't find `%1'", PROLOGUE);
+ fputs("%%BeginResource: ", outfp);
+ procset_resource->print_type_and_name(outfp);
+ putc('\n', outfp);
+ process_file(-1, fp, path, outfp);
+ fclose(fp);
+ a_delete path;
+ fputs("%%EndResource\n", outfp);
+}
+
+void resource_manager::import_file(const char *filename, ps_output &out)
+{
+ out.end_line();
+ string name(filename);
+ resource *r = lookup_resource(RESOURCE_FILE, name);
+ supply_resource(r, -1, out.get_file(), 1);
+}
+
+void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
+ int is_document)
+{
+ if (r->flags & resource::BUSY) {
+ r->name += '\0';
+ fatal("loop detected in dependency graph for %1 `%2'",
+ resource_table[r->type],
+ r->name.contents());
+ }
+ r->flags |= resource::BUSY;
+ if (rank > r->rank)
+ r->rank = rank;
+ char *path;
+ FILE *fp = 0;
+ if (r->filename != 0) {
+ if (r->type == RESOURCE_FONT) {
+ fp = font::open_file(r->filename, &path);
+ if (!fp) {
+ error("can't find `%1'", r->filename);
+ a_delete r->filename;
+ r->filename = 0;
+ }
+ }
+ else {
+ errno = 0;
+ fp = fopen(r->filename, "r");
+ if (!fp) {
+ error("can't open `%1': %2", r->filename, strerror(errno));
+ a_delete r->filename;
+ r->filename = 0;
+ }
+ else
+ path = r->filename;
+ }
+ }
+ if (fp) {
+ if (outfp) {
+ if (r->type == RESOURCE_FILE && is_document) {
+ fputs("%%BeginDocument: ", outfp);
+ print_ps_string(r->name, outfp);
+ putc('\n', outfp);
+ }
+ else {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ process_file(rank, fp, path, outfp);
+ fclose(fp);
+ if (r->type == RESOURCE_FONT)
+ a_delete path;
+ if (outfp) {
+ if (r->type == RESOURCE_FILE && is_document)
+ fputs("%%EndDocument\n", outfp);
+ else
+ fputs("%%EndResource\n", outfp);
+ }
+ r->flags |= resource::SUPPLIED;
+ }
+ else {
+ if (outfp) {
+ if (r->type == RESOURCE_FILE && is_document) {
+ fputs("%%IncludeDocument: ", outfp);
+ print_ps_string(r->name, outfp);
+ putc('\n', outfp);
+ }
+ else {
+ fputs("%%IncludeResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ r->flags |= resource::NEEDED;
+ }
+ r->flags &= ~resource::BUSY;
+}
+
+
+#define PS_LINE_MAX 255
+#define PS_MAGIC "%!PS-Adobe-"
+
+static int ps_get_line(char *buf, FILE *fp)
+{
+ int c = getc(fp);
+ if (c == EOF) {
+ buf[0] = '\0';
+ return 0;
+ }
+ current_lineno++;
+ int i = 0;
+ int err = 0;
+ while (c != '\r' && c != '\n' && c != EOF) {
+ if ((c < 0x1b && !white_space(c)) || c == 0x7f)
+ error("illegal input character code %1", int(c));
+ else if (i < PS_LINE_MAX)
+ buf[i++] = c;
+ else if (!err) {
+ err = 1;
+ error("PostScript file non-conforming "
+ "because length of line exceeds 255");
+ }
+ c = getc(fp);
+ }
+ buf[i++] = '\n';
+ buf[i] = '\0';
+ if (c == '\r') {
+ c = getc(fp);
+ if (c != EOF && c != '\n')
+ ungetc(c, fp);
+ }
+ return 1;
+}
+
+static int read_text_arg(const char **pp, string &res)
+{
+ res.clear();
+ while (white_space(**pp))
+ *pp += 1;
+ if (**pp == '\0') {
+ error("missing argument");
+ return 0;
+ }
+ if (**pp != '(') {
+ for (; **pp != '\0' && !white_space(**pp); *pp += 1)
+ res += **pp;
+ return 1;
+ }
+ *pp += 1;
+ res.clear();
+ int level = 0;
+ for (;;) {
+ if (**pp == '\0' || **pp == '\r' || **pp == '\n') {
+ error("missing ')'");
+ return 0;
+ }
+ if (**pp == ')') {
+ if (level == 0) {
+ *pp += 1;
+ break;
+ }
+ res += **pp;
+ level--;
+ }
+ else if (**pp == '(') {
+ level++;
+ res += **pp;
+ }
+ else if (**pp == '\\') {
+ *pp += 1;
+ switch (**pp) {
+ case 'n':
+ res += '\n';
+ break;
+ case 'r':
+ res += '\n';
+ break;
+ case 't':
+ res += '\t';
+ break;
+ case 'b':
+ res += '\b';
+ break;
+ case 'f':
+ res += '\f';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ int val = **pp - '0';
+ if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
+ *pp += 1;
+ val = val*8 + (**pp - '0');
+ if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
+ *pp += 1;
+ val = val*8 + (**pp - '0');
+ }
+ }
+ }
+ break;
+ default:
+ res += **pp;
+ break;
+ }
+ }
+ else
+ res += **pp;
+ *pp += 1;
+ }
+ return 1;
+}
+
+static int read_uint_arg(const char **pp, unsigned *res)
+{
+ while (white_space(**pp))
+ *pp += 1;
+ if (**pp == '\0') {
+ error("missing argument");
+ return 0;
+ }
+ const char *start = *pp;
+ // XXX use strtoul
+ long n = strtol(start, (char **)pp, 10);
+ if (n == 0 && *pp == start) {
+ error("not an integer");
+ return 0;
+ }
+ if (n < 0) {
+ error("argument must not be negative");
+ return 0;
+ }
+ *res = unsigned(n);
+ return 1;
+}
+
+resource *resource_manager::read_file_arg(const char **ptr)
+{
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ return lookup_resource(RESOURCE_FILE, arg);
+}
+
+resource *resource_manager::read_font_arg(const char **ptr)
+{
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ return lookup_resource(RESOURCE_FONT, arg);
+}
+
+resource *resource_manager::read_procset_arg(const char **ptr)
+{
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ string version;
+ if (!read_text_arg(ptr, version))
+ return 0;
+ unsigned revision;
+ if (!read_uint_arg(ptr, &revision))
+ return 0;
+ return lookup_resource(RESOURCE_PROCSET, arg, version, revision);
+}
+
+resource *resource_manager::read_resource_arg(const char **ptr)
+{
+ while (white_space(**ptr))
+ *ptr += 1;
+ const char *name = *ptr;
+ while (**ptr != '\0' && !white_space(**ptr))
+ *ptr += 1;
+ if (name == *ptr) {
+ error("missing resource type");
+ return 0;
+ }
+ for (int ri = 0; ri < NRESOURCES; ri++)
+ if (strlen(resource_table[ri]) == *ptr - name
+ && memcmp(resource_table[ri], name, *ptr - name) == 0)
+ break;
+ if (ri >= NRESOURCES) {
+ error("unknown resource type");
+ return 0;
+ }
+ if (ri == RESOURCE_PROCSET)
+ return read_procset_arg(ptr);
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ return lookup_resource(resource_type(ri), arg);
+}
+
+static const char *matches_comment(const char *buf, const char *comment)
+{
+ if (buf[0] != '%' || buf[1] != '%')
+ return 0;
+ for (buf += 2; *comment; comment++, buf++)
+ if (*buf != *comment)
+ return 0;
+ if (comment[-1] == ':')
+ return buf;
+ if (*buf == '\0' || white_space(*buf))
+ return buf;
+ return 0;
+}
+
+// Return 1 if the line should be copied out.
+
+int resource_manager::do_begin_resource(const char *ptr, int, FILE *,
+ FILE *)
+{
+ resource *r = read_resource_arg(&ptr);
+ if (r)
+ r->flags |= resource::SUPPLIED;
+ return 1;
+}
+
+int resource_manager::do_include_resource(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_resource_arg(&ptr);
+ if (r) {
+ if (r->type == RESOURCE_FONT) {
+ if (rank >= 0)
+ supply_resource(r, rank + 1, outfp);
+ else
+ r->flags |= resource::FONT_NEEDED;
+ }
+ else
+ supply_resource(r, rank, outfp);
+ }
+ return 0;
+}
+
+int resource_manager::do_begin_document(const char *ptr, int, FILE *,
+ FILE *)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r)
+ r->flags |= resource::SUPPLIED;
+ return 1;
+}
+
+int resource_manager::do_include_document(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r)
+ supply_resource(r, rank, outfp, 1);
+ return 0;
+}
+
+int resource_manager::do_begin_procset(const char *ptr, int, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_procset_arg(&ptr);
+ if (r) {
+ r->flags |= resource::SUPPLIED;
+ if (outfp) {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ return 0;
+}
+
+int resource_manager::do_include_procset(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_procset_arg(&ptr);
+ if (r)
+ supply_resource(r, rank, outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_file(const char *ptr, int, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r) {
+ r->flags |= resource::SUPPLIED;
+ if (outfp) {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ return 0;
+}
+
+int resource_manager::do_include_file(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r)
+ supply_resource(r, rank, outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_font(const char *ptr, int, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_font_arg(&ptr);
+ if (r) {
+ r->flags |= resource::SUPPLIED;
+ if (outfp) {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ return 0;
+}
+
+int resource_manager::do_include_font(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_font_arg(&ptr);
+ if (r) {
+ if (rank >= 0)
+ supply_resource(r, rank + 1, outfp);
+ else
+ r->flags |= resource::FONT_NEEDED;
+ }
+ return 0;
+}
+
+int resource_manager::change_to_end_resource(const char *, int, FILE *,
+ FILE *outfp)
+{
+ if (outfp)
+ fputs("%%EndResource\n", outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_preview(const char *, int, FILE *fp, FILE *)
+{
+ char buf[PS_LINE_MAX + 2];
+ do {
+ if (!ps_get_line(buf, fp)) {
+ error("end of file in preview section");
+ break;
+ }
+ } while (!matches_comment(buf, "EndPreview"));
+ return 0;
+}
+
+int read_one_of(const char **ptr, const char **s, int n)
+{
+ while (white_space(**ptr))
+ *ptr += 1;
+ if (**ptr == '\0')
+ return -1;
+ const char *start = *ptr;
+ do {
+ ++ptr;
+ } while (**ptr != '\0' && !white_space(**ptr));
+ for (int i = 0; i < n; i++)
+ if (strlen(s[i]) == *ptr - start
+ && memcmp(s[i], start, *ptr - start) == 0)
+ return i;
+ return -1;
+}
+
+int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
+ FILE *outfp)
+{
+ while (white_space(*ptr))
+ ptr++;
+ const char *start = ptr;
+ unsigned numberof;
+ if (!read_uint_arg(&ptr, &numberof))
+ return 0;
+ static const char *types[] = { "Binary", "Hex", "ASCII" };
+ const int Binary = 0;
+ int type = 0;
+ static const char *units[] = { "Bytes", "Lines" };
+ const int Bytes = 0;
+ int unit = Bytes;
+ while (white_space(*ptr))
+ ptr++;
+ if (*ptr != '\0') {
+ type = read_one_of(&ptr, types, 3);
+ if (type < 0) {
+ error("bad data type");
+ return 0;
+ }
+ while (white_space(*ptr))
+ ptr++;
+ if (*ptr != '\0') {
+ unit = read_one_of(&ptr, units, 2);
+ if (unit < 0) {
+ error("expected `Bytes' or `Lines'");
+ return 0;
+ }
+ }
+ }
+ if (type != Binary)
+ return 1;
+ if (outfp) {
+ fputs("%%BeginData: ", outfp);
+ fputs(start, outfp);
+ }
+ if (numberof > 0) {
+ unsigned bytecount = 0;
+ unsigned linecount = 0;
+ do {
+ int c = getc(fp);
+ if (c == EOF) {
+ error("end of file within data section");
+ return 0;
+ }
+ if (outfp)
+ putc(c, outfp);
+ bytecount++;
+ if (c == '\r') {
+ int cc = getc(fp);
+ if (cc != '\n') {
+ linecount++;
+ current_lineno++;
+ }
+ if (cc != EOF)
+ ungetc(c, fp);
+ }
+ else if (c == '\n') {
+ linecount++;
+ current_lineno++;
+ }
+ } while ((unit == Bytes ? bytecount : linecount) < numberof);
+ }
+ char buf[PS_LINE_MAX + 2];
+ if (!ps_get_line(buf, fp)) {
+ error("missing %%%%EndData line");
+ return 0;
+ }
+ if (!matches_comment(buf, "EndData"))
+ error("bad %%%%EndData line");
+ if (outfp)
+ fputs(buf, outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
+ FILE *outfp)
+{
+ if (!outfp)
+ return 0;
+ unsigned count;
+ if (!read_uint_arg(&ptr, &count))
+ return 0;
+ if (outfp)
+ fprintf(outfp, "%%%%BeginData: %u Binary Bytes\n", count);
+ while (count != 0) {
+ int c = getc(fp);
+ if (c == EOF) {
+ error("end of file within binary section");
+ return 0;
+ }
+ if (outfp)
+ putc(c, outfp);
+ --count;
+ if (c == '\r') {
+ int cc = getc(fp);
+ if (cc != '\n')
+ current_lineno++;
+ if (cc != EOF)
+ ungetc(c, fp);
+ }
+ else if (c == '\n')
+ current_lineno++;
+ }
+ char buf[PS_LINE_MAX + 2];
+ if (!ps_get_line(buf, fp)) {
+ error("missing %%%%EndBinary line");
+ return 0;
+ }
+ if (!matches_comment(buf, "EndBinary")) {
+ error("bad %%%%EndBinary line");
+ if (outfp)
+ fputs(buf, outfp);
+ }
+ else if (outfp)
+ fputs("%%EndData\n", outfp);
+ return 0;
+}
+
+static unsigned parse_extensions(const char *ptr)
+{
+ unsigned flags = 0;
+ for (;;) {
+ while (white_space(*ptr))
+ ptr++;
+ if (*ptr == '\0')
+ break;
+ const char *name = ptr;
+ do {
+ ++ptr;
+ } while (*ptr != '\0' && !white_space(*ptr));
+ for (int i = 0; i < NEXTENSIONS; i++)
+ if (strlen(extension_table[i]) == ptr - name
+ && memcmp(extension_table[i], name, ptr - name) == 0) {
+ flags |= (1 << i);
+ break;
+ }
+ if (i >= NEXTENSIONS) {
+ string s(name, ptr - name);
+ s += '\0';
+ error("unknown extension `%1'", s.contents());
+ }
+ }
+ return flags;
+}
+
+// XXX if it has not been surrounded with {Begin,End}Document need to strip
+// out Page: Trailer {Begin,End}Prolog {Begin,End}Setup sections.
+
+// XXX Perhaps the decision whether to use BeginDocument or
+// BeginResource: file should be postponed till we have seen
+// the first line of the file.
+
+void resource_manager::process_file(int rank, FILE *fp, const char *filename,
+ FILE *outfp)
+{
+ // If none of these comments appear in the header section, and we are
+ // just analyzing the file (ie outfp is 0), then we can return immediately.
+ static const char *header_comment_table[] = {
+ "DocumentNeededResources:",
+ "DocumentSuppliedResources:",
+ "DocumentNeededFonts:",
+ "DocumentSuppliedFonts:",
+ "DocumentNeededProcSets:",
+ "DocumentSuppliedProcSets:",
+ "DocumentNeededFiles:",
+ "DocumentSuppliedFiles:",
+ };
+
+ const int NHEADER_COMMENTS = (sizeof(header_comment_table)
+ / sizeof(header_comment_table[0]));
+ typedef (resource_manager::*resource_manager_mfp)(const char *, int, FILE *, FILE *);
+ struct comment_info {
+ const char *name;
+ resource_manager_mfp proc;
+ };
+
+ static comment_info comment_table[] = {
+ "BeginResource:", &resource_manager::do_begin_resource,
+ "IncludeResource:", &resource_manager::do_include_resource,
+ "BeginDocument:", &resource_manager::do_begin_document,
+ "IncludeDocument:", &resource_manager::do_include_document,
+ "BeginProcSet:", &resource_manager::do_begin_procset,
+ "IncludeProcSet:", &resource_manager::do_include_procset,
+ "BeginFont:", &resource_manager::do_begin_font,
+ "IncludeFont:", &resource_manager::do_include_font,
+ "BeginFile:", &resource_manager::do_begin_file,
+ "IncludeFile:", &resource_manager::do_include_file,
+ "EndProcSet", &resource_manager::change_to_end_resource,
+ "EndFont", &resource_manager::change_to_end_resource,
+ "EndFile", &resource_manager::change_to_end_resource,
+ "BeginPreview:", &resource_manager::do_begin_preview,
+ "BeginData:", &resource_manager::do_begin_data,
+ "BeginBinary:", &resource_manager::do_begin_binary,
+ };
+
+ const int NCOMMENTS = sizeof(comment_table)/sizeof(comment_table[0]);
+ char buf[PS_LINE_MAX + 2];
+ int saved_lineno = current_lineno;
+ const char *saved_filename = current_filename;
+ current_filename = filename;
+ current_lineno = 0;
+ if (!ps_get_line(buf, fp)) {
+ current_filename = saved_filename;
+ current_lineno = saved_lineno;
+ return;
+ }
+ if (strlen(buf) < sizeof(PS_MAGIC) - 1
+ || memcmp(buf, PS_MAGIC, sizeof(PS_MAGIC) - 1) != 0) {
+ if (outfp) {
+ do {
+ if (!(broken_flags & STRIP_PERCENT_BANG)
+ || buf[0] != '%' || buf[1] != '!')
+ fputs(buf, outfp);
+ } while (ps_get_line(buf, fp));
+ }
+ }
+ else {
+ if (!(broken_flags & STRIP_PERCENT_BANG) && outfp)
+ fputs(buf, outfp);
+ int in_header = 1;
+ int interesting = 0;
+ int had_extensions_comment = 0;
+ int had_language_level_comment = 0;
+ for (;;) {
+ if (!ps_get_line(buf, fp))
+ break;
+ int copy_this_line = 1;
+ if (buf[0] == '%') {
+ if (buf[1] == '%') {
+ const char *ptr;
+ for (int i = 0; i < NCOMMENTS; i++)
+ if (ptr = matches_comment(buf, comment_table[i].name)) {
+ copy_this_line
+ = (this->*(comment_table[i].proc))(ptr, rank, fp, outfp);
+ break;
+ }
+ if (i >= NCOMMENTS && in_header) {
+ if (ptr = matches_comment(buf, "EndComments"))
+ in_header = 0;
+ else if (!had_extensions_comment
+ && (ptr = matches_comment(buf, "Extensions:"))) {
+ extensions |= parse_extensions(ptr);
+ // XXX handle possibility that next line is %%+
+ had_extensions_comment = 1;
+ }
+ else if (!had_language_level_comment
+ && (ptr = matches_comment(buf, "LanguageLevel:"))) {
+ unsigned ll;
+ if (read_uint_arg(&ptr, &ll) && ll > language_level)
+ language_level = ll;
+ had_language_level_comment = 1;
+ }
+ else {
+ for (int i = 0; i < NHEADER_COMMENTS; i++)
+ if (matches_comment(buf, header_comment_table[i])) {
+ interesting = 1;
+ break;
+ }
+ }
+ }
+ if ((broken_flags & STRIP_STRUCTURE_COMMENTS)
+ && (matches_comment(buf, "EndProlog")
+ || matches_comment(buf, "Page:")
+ || matches_comment(buf, "Trailer")))
+ copy_this_line = 0;
+ }
+ else if (buf[1] == '!') {
+ if (broken_flags & STRIP_PERCENT_BANG)
+ copy_this_line = 0;
+ }
+ }
+ else
+ in_header = 0;
+ if (!outfp && !in_header && !interesting)
+ break;
+ if (copy_this_line && outfp)
+ fputs(buf, outfp);
+ }
+ }
+ current_filename = saved_filename;
+ current_lineno = saved_lineno;
+}
+
+void resource_manager::read_download_file()
+{
+ char *path = 0;
+ FILE *fp = font::open_file("download", &path);
+ if (!fp)
+ fatal("can't find `download'");
+ char buf[512];
+ int lineno = 0;
+ while (fgets(buf, sizeof(buf), fp)) {
+ lineno++;
+ char *p = strtok(buf, " \t\r\n");
+ if (p == 0 || *p == '#')
+ continue;
+ char *q = strtok(0, " \t\r\n");
+ if (!q)
+ fatal_with_file_and_line(path, lineno, "missing filename");
+ lookup_font(p)->filename = strsave(q);
+ }
+ a_delete path;
+ fclose(fp);
+}
+
+// XXX Can we share some code with ps_output::put_string()?
+
+static void print_ps_string(const string &s, FILE *outfp)
+{
+ int len = s.length();
+ const char *str = s.contents();
+ int funny = 0;
+ if (str[0] == '(')
+ funny = 1;
+ else {
+ for (int i = 0; i < len; i++)
+ if (str[i] <= 040 || str[i] > 0176) {
+ funny = 1;
+ break;
+ }
+ }
+ if (!funny) {
+ put_string(s, outfp);
+ return;
+ }
+ int level = 0;
+ for (int i = 0; i < len; i++)
+ if (str[i] == '(')
+ level++;
+ else if (str[i] == ')' && --level < 0)
+ break;
+ putc('(', outfp);
+ for (i = 0; i < len; i++)
+ switch (str[i]) {
+ case '(':
+ case ')':
+ if (level != 0)
+ putc('\\', outfp);
+ putc(str[i], outfp);
+ break;
+ case '\\':
+ fputs("\\\\", outfp);
+ break;
+ case '\n':
+ fputs("\\n", outfp);
+ break;
+ case '\r':
+ fputs("\\r", outfp);
+ break;
+ case '\t':
+ fputs("\\t", outfp);
+ break;
+ case '\b':
+ fputs("\\b", outfp);
+ break;
+ case '\f':
+ fputs("\\f", outfp);
+ break;
+ default:
+ if (str[i] < 040 || str[i] > 0176)
+ fprintf(outfp, "\\%03o", str[i] & 0377);
+ else
+ putc(str[i], outfp);
+ break;
+ }
+ putc(')', outfp);
+}
+
+void resource_manager::print_extensions_comment(FILE *outfp)
+{
+ if (extensions) {
+ fputs("%%Extensions:", outfp);
+ for (int i = 0; i < NEXTENSIONS; i++)
+ if (extensions & (1 << i)) {
+ putc(' ', outfp);
+ fputs(extension_table[i], outfp);
+ }
+ putc('\n', outfp);
+ }
+}
+
+void resource_manager::print_language_level_comment(FILE *outfp)
+{
+ if (language_level)
+ fprintf(outfp, "%%%%LanguageLevel: %u\n", language_level);
+}
+
diff --git a/gnu/usr.bin/groff/grotty/Makefile b/gnu/usr.bin/groff/grotty/Makefile
new file mode 100644
index 000000000000..9ca521a08207
--- /dev/null
+++ b/gnu/usr.bin/groff/grotty/Makefile
@@ -0,0 +1,12 @@
+# Makefile for grotty
+
+PROG= grotty
+SRCS= tty.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBDRIVER) $(LIBGROFF) -lm
+DPADD+= $(LIBDRIVER) $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/grotty/TODO b/gnu/usr.bin/groff/grotty/TODO
new file mode 100644
index 000000000000..3f23dc35d56b
--- /dev/null
+++ b/gnu/usr.bin/groff/grotty/TODO
@@ -0,0 +1,3 @@
+Document font and device description file usage of grotty.
+
+With -h avoid using a tab when a single space will do.
diff --git a/gnu/usr.bin/groff/grotty/grotty.1 b/gnu/usr.bin/groff/grotty/grotty.1
new file mode 100644
index 000000000000..d425655485a4
--- /dev/null
+++ b/gnu/usr.bin/groff/grotty/grotty.1
@@ -0,0 +1,204 @@
+.\" -*- nroff -*-
+.TH GROTTY 1 "11 August 1992" "Groff Version 1.08"
+.SH NAME
+grotty \- groff driver for typewriter-like devices
+.SH SYNOPSIS
+.B grotty
+[
+.B \-hfbuodBUv
+] [
+.BI \-F dir
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grotty
+translates the output of GNU
+.B troff
+into a form suitable for typewriter-like devices.
+Normally
+.B grotty
+should invoked by using the
+.B groff
+command
+with a
+.B \-Tascii
+or
+.B \-Tlatin1
+option.
+If no files are given,
+.B grotty
+will read the standard input.
+A filename of
+.B \-
+will also cause
+.B grotty
+to read the standard input.
+Output is written to the standard output.
+.LP
+Normally
+.B grotty
+prints a bold character
+.I c
+using the sequence
+.RI ` c
+.SM BACKSPACE
+.IR c '
+and a italic character
+.I c
+by the sequence
+.RB ` _
+.SM BACKSPACE
+.IR c '.
+These sequences can be displayed on a terminal
+by piping through
+.BR ul (1).
+Pagers such as
+.BR more (1)
+or
+.BR less (1)
+are also able to display these sequences.
+Use either
+.B \-B
+or
+.B \-U
+when piping into
+.BR less (1);
+use
+.B \-b
+when piping into
+.BR more (1).
+There is no need to filter the output through
+.BR col (1)
+since
+.B grotty
+never outputs reverse line feeds.
+.LP
+The font description file may contain a command
+.IP
+.BI internalname\ n
+.LP
+where
+.I n
+is a decimal integer.
+If the 01 bit in
+.I n
+is set,
+then the font will be treated as an italic font;
+if the 02 bit is set,
+then it will be treated as a bold font.
+The code field in the font description field gives the
+code which will be used to output the character.
+This code can also be used in the
+.B \eN
+escape sequence in
+.BR troff .
+.SH OPTIONS
+.TP
+.BI \-F dir
+Search the directory
+.IB dir /dev name
+for font and device description files;
+.I name
+is the name of the device, usually
+.B ascii
+or
+.BR latin1 .
+.TP
+.B \-h
+Use horizontal tabs in the output.
+Tabs are assumed to be set every 8 columns.
+.TP
+.B \-f
+Use form feeds in the output.
+A form feed will be output at the end of each page that has no output
+on its last line.
+.TP
+.B \-b
+Suppress the use of overstriking for bold characters.
+.TP
+.B \-u
+Suppress the use of underlining for italic characters.
+.TP
+.B \-B
+Use only overstriking for bold-italic characters.
+.TP
+.B \-U
+Use only underlining for bold-italic characters.
+.TP
+.B \-o
+Suppress overstriking (other than for bold or underlined characters).
+.TP
+.B \-d
+Ignore all
+.B \eD
+commands.
+Without this
+.B grotty
+will render
+.B \eD'l\|.\|.\|.'
+commands that have at least at least one zero argument
+(and so are either horizontal or vertical)
+using
+.BR \- ,
+.B |
+and
+.B +
+characters.
+.TP
+.B \-v
+Print the version number.
+.SH FILES
+.TP
+.B /usr/share/groff_font/devascii/DESC
+Device desciption file for
+.B ascii
+device.
+.TP
+.B /usr/share/groff_font/devascii/ F
+Font description file for font
+.I F
+of
+.B ascii device.
+.TP
+.B /usr/share/groff_font/devlatin1/DESC
+Device desciption file for
+.B latin1
+device.
+.TP
+.B /usr/share/groff_font/devlatin1/ F
+Font description file for font
+.I F
+of
+.B latin1 device.
+.TP
+.B /usr/share/tmac/tmac.tty
+Macros for use with
+.BR grotty .
+.TP
+.B /usr/share/tmac/tmac.tty-char
+Additional klugey character definitions for use with
+.BR grotty .
+.SH BUGS
+.LP
+.B grotty
+is intended only for simple documents.
+.LP
+There is no support for fractional horizontal or vertical motions.
+.LP
+There is no support for
+.B \eD
+commands
+other than horizontal and vertical lines.
+.LP
+Characters above the first line (ie with a vertical position of 0)
+cannot be printed.
+.SH "SEE ALSO"
+.BR groff (1),
+.BR troff (1),
+.BR groff_out (5),
+.BR groff_font (5),
+.BR groff_char (7),
+.BR ul (1),
+.BR more (1),
+.BR less (1)
diff --git a/gnu/usr.bin/groff/grotty/tty.cc b/gnu/usr.bin/groff/grotty/tty.cc
new file mode 100644
index 000000000000..8287378617c4
--- /dev/null
+++ b/gnu/usr.bin/groff/grotty/tty.cc
@@ -0,0 +1,440 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "driver.h"
+
+#ifndef USHRT_MAX
+#define USHRT_MAX 65535
+#endif
+
+#define TAB_WIDTH 8
+
+static int horizontal_tab_flag = 0;
+static int form_feed_flag = 0;
+static int bold_flag = 1;
+static int underline_flag = 1;
+static int overstrike_flag = 1;
+static int draw_flag = 1;
+
+enum {
+ UNDERLINE_MODE = 01,
+ BOLD_MODE = 02,
+ VDRAW_MODE = 04,
+ HDRAW_MODE = 010
+};
+
+// Mode to use for bold-underlining.
+static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
+
+class tty_font : public font {
+ tty_font(const char *);
+ unsigned char mode;
+public:
+ ~tty_font();
+ unsigned char get_mode() { return mode; }
+#if 0
+ void handle_x_command(int argc, const char **argv);
+#endif
+ static tty_font *load_tty_font(const char *);
+};
+
+tty_font *tty_font::load_tty_font(const char *s)
+{
+ tty_font *f = new tty_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ const char *num = f->get_internal_name();
+ long n;
+ if (num != 0 && (n = strtol(num, 0, 0)) != 0)
+ f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE));
+ if (!underline_flag)
+ f->mode &= ~UNDERLINE_MODE;
+ if (!bold_flag)
+ f->mode &= ~BOLD_MODE;
+ if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE))
+ f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode;
+ return f;
+}
+
+tty_font::tty_font(const char *nm)
+: font(nm), mode(0)
+{
+}
+
+tty_font::~tty_font()
+{
+}
+
+#if 0
+void tty_font::handle_x_command(int argc, const char **argv)
+{
+ if (argc >= 1 && strcmp(argv[0], "bold") == 0)
+ mode |= BOLD_MODE;
+ else if (argc >= 1 && strcmp(argv[0], "underline") == 0)
+ mode |= UNDERLINE_MODE;
+}
+#endif
+
+class glyph {
+ static glyph *free_list;
+public:
+ glyph *next;
+ unsigned short hpos;
+ unsigned char code;
+ unsigned char mode;
+ void *operator new(size_t);
+ void operator delete(void *);
+ inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); }
+};
+
+glyph *glyph::free_list = 0;
+
+void *glyph::operator new(size_t)
+{
+ if (!free_list) {
+ const int BLOCK = 1024;
+ free_list = (glyph *)new char[sizeof(glyph)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK - 1].next = 0;
+ }
+ glyph *p = free_list;
+ free_list = free_list->next;
+ p->next = 0;
+ return p;
+}
+
+void glyph::operator delete(void *p)
+{
+ if (p) {
+ ((glyph *)p)->next = free_list;
+ free_list = (glyph *)p;
+ }
+}
+
+class tty_printer : public printer {
+ glyph **lines;
+ int nlines;
+ int cached_v;
+ int cached_vpos;
+ void add_char(unsigned char, int, int, unsigned char);
+public:
+ tty_printer();
+ ~tty_printer();
+ void set_char(int, font *, const environment *, int);
+ void draw(int code, int *p, int np, const environment *env);
+ void begin_page(int) { }
+ void end_page(int page_length);
+ font *make_font(const char *);
+};
+
+tty_printer::tty_printer() : cached_v(0)
+{
+ nlines = 66;
+ lines = new glyph *[nlines];
+ for (int i = 0; i < nlines; i++)
+ lines[i] = 0;
+}
+
+tty_printer::~tty_printer()
+{
+ a_delete lines;
+}
+
+void tty_printer::set_char(int i, font *f, const environment *env, int w)
+{
+ if (w != font::hor)
+ fatal("width of character not equal to horizontal resolution");
+ add_char(f->get_code(i), env->hpos, env->vpos, ((tty_font *)f)->get_mode());
+}
+
+void tty_printer::add_char(unsigned char c, int h, int v, unsigned char mode)
+{
+#if 0
+ // This is too expensive.
+ if (h % font::hor != 0)
+ fatal("horizontal position not a multiple of horizontal resolution");
+#endif
+ int hpos = h / font::hor;
+ if (hpos < 0) {
+ error("character to the left of first column discarded");
+ return;
+ }
+ if (hpos > USHRT_MAX) {
+ error("character with ridiculously large horizontal position discarded");
+ return;
+ }
+ int vpos;
+ if (v == cached_v && cached_v != 0)
+ vpos = cached_vpos;
+ else {
+ if (v % font::vert != 0)
+ fatal("vertical position not a multiple of vertical resolution");
+ vpos = v / font::vert;
+ if (vpos > nlines) {
+ glyph **old_lines = lines;
+ lines = new glyph *[vpos + 1];
+ memcpy(lines, old_lines, nlines*sizeof(glyph *));
+ for (int i = nlines; i <= vpos; i++)
+ lines[i] = 0;
+ a_delete old_lines;
+ nlines = vpos + 1;
+ }
+ // Note that the first output line corresponds to groff
+ // position font::vert.
+ if (vpos <= 0) {
+ error("character above first line discarded");
+ return;
+ }
+ cached_v = v;
+ cached_vpos = vpos;
+ }
+ glyph *g = new glyph;
+ g->hpos = hpos;
+ g->code = c;
+ g->mode = mode;
+
+ // The list will be reversed later. After reversal, it must be in
+ // increasing order of hpos, with HDRAW characters before VDRAW
+ // characters before normal characters at each hpos, and otherwise
+ // in order of occurrence.
+
+ for (glyph **pp = lines + (vpos - 1); *pp; pp = &(*pp)->next)
+ if (int(((glyph *)*pp)->hpos) < hpos
+ || (((glyph *)*pp)->hpos == hpos
+ && ((glyph *)*pp)->draw_mode() >= g->draw_mode()))
+ break;
+
+ g->next = *pp;
+ *pp = g;
+}
+
+void tty_printer::draw(int code, int *p, int np, const environment *env)
+{
+ if (code != 'l' || !draw_flag)
+ return;
+ if (np != 2) {
+ error("2 arguments required for line");
+ return;
+ }
+ if (p[0] == 0) {
+ // vertical line
+ int v = env->vpos;
+ int len = p[1];
+ if (len < 0) {
+ v += len;
+ len = -len;
+ }
+ while (len >= 0) {
+ add_char('|', env->hpos, v, VDRAW_MODE);
+ len -= font::vert;
+ v += font::vert;
+ }
+ }
+ if (p[1] == 0) {
+ // horizontal line
+ int h = env->hpos;
+ int len = p[0];
+ if (len < 0) {
+ h += len;
+ len = -len;
+ }
+ while (len >= 0) {
+ add_char('-', h, env->vpos, HDRAW_MODE);
+ len -= font::hor;
+ h += font::hor;
+ }
+ }
+}
+
+void tty_printer::end_page(int page_length)
+{
+ if (page_length % font::vert != 0)
+ error("vertical position at end of page not multiple of vertical resolution");
+ int lines_per_page = page_length / font::vert;
+ for (int last_line = nlines; last_line > 0; last_line--)
+ if (lines[last_line - 1])
+ break;
+#if 0
+ if (last_line > lines_per_page) {
+ error("characters past last line discarded");
+ do {
+ --last_line;
+ while (lines[last_line]) {
+ glyph *tem = lines[last_line];
+ lines[last_line] = tem->next;
+ delete tem;
+ }
+ } while (last_line > lines_per_page);
+ }
+#endif
+ for (int i = 0; i < last_line; i++) {
+ glyph *p = lines[i];
+ lines[i] = 0;
+ glyph *g = 0;
+ while (p) {
+ glyph *tem = p->next;
+ p->next = g;
+ g = p;
+ p = tem;
+ }
+ int hpos = 0;
+
+ glyph *nextp;
+ for (p = g; p; delete p, p = nextp) {
+ nextp = p->next;
+ if (nextp && p->hpos == nextp->hpos) {
+ if (p->draw_mode() == HDRAW_MODE && nextp->draw_mode() == VDRAW_MODE) {
+ nextp->code = '+';
+ continue;
+ }
+ if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) {
+ nextp->code = p->code;
+ continue;
+ }
+ if (!overstrike_flag)
+ continue;
+ }
+ if (hpos > int(p->hpos)) {
+ putchar('\b');
+ hpos--;
+ }
+ else {
+ if (horizontal_tab_flag) {
+ for (;;) {
+ int next_tab_pos = ((hpos + TAB_WIDTH) / TAB_WIDTH) * TAB_WIDTH;
+ if (next_tab_pos > int(p->hpos))
+ break;
+ putchar('\t');
+ hpos = next_tab_pos;
+ }
+ }
+ for (; hpos < int(p->hpos); hpos++)
+ putchar(' ');
+ }
+ assert(hpos == p->hpos);
+ if (p->mode & UNDERLINE_MODE) {
+ putchar('_');
+ putchar('\b');
+ }
+ if (p->mode & BOLD_MODE) {
+ putchar(p->code);
+ putchar('\b');
+ }
+ putchar(p->code);
+ hpos++;
+ }
+ putchar('\n');
+ }
+ if (form_feed_flag) {
+ if (last_line < lines_per_page)
+ putchar('\f');
+ }
+ else {
+ for (; last_line < lines_per_page; last_line++)
+ putchar('\n');
+ }
+}
+
+font *tty_printer::make_font(const char *nm)
+{
+ return tty_font::load_tty_font(nm);
+}
+
+printer *make_printer()
+{
+ return new tty_printer;
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:vhfbuoBUd")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "grotty version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'b':
+ // Do not embolden by overstriking.
+ bold_flag = 0;
+ break;
+ case 'u':
+ // Do not underline.
+ underline_flag = 0;
+ break;
+ case 'o':
+ // Do not overstrike (other than emboldening and underlining).
+ overstrike_flag = 0;
+ break;
+ case 'B':
+ // Do bold-underlining as bold.
+ bold_underline_mode = BOLD_MODE;
+ break;
+ case 'U':
+ // Do bold-underlining as underlining.
+ bold_underline_mode = UNDERLINE_MODE;
+ break;
+ case 'h':
+ // Use horizontal tabs.
+ horizontal_tab_flag = 1;
+ break;
+ case 'f':
+ form_feed_flag = 1;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'd':
+ // Ignore \D commands.
+ draw_flag = 0;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ exit(0);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-hfvbuodBU] [-F dir] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/gnu/usr.bin/groff/include/assert.h b/gnu/usr.bin/groff/include/assert.h
new file mode 100644
index 000000000000..3963b4fb4b22
--- /dev/null
+++ b/gnu/usr.bin/groff/include/assert.h
@@ -0,0 +1,41 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef ASSERT_H
+#define ASSERT_H
+#ifdef __GNUG__
+volatile
+#endif
+void assertion_failed(int, const char *);
+
+inline void do_assert(int expr, int line, const char *file)
+{
+ if (!expr)
+ assertion_failed(line, file);
+}
+#endif /* ASSERT_H */
+
+#undef assert
+
+#ifdef NDEBUG
+#define assert(ignore) /* as nothing */
+#else
+#define assert(expr) do_assert(expr, __LINE__, __FILE__)
+#endif
diff --git a/gnu/usr.bin/groff/include/cmap.h b/gnu/usr.bin/groff/include/cmap.h
new file mode 100644
index 000000000000..18c88fb262b6
--- /dev/null
+++ b/gnu/usr.bin/groff/include/cmap.h
@@ -0,0 +1,56 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 255
+#endif
+
+enum cmap_builtin { CMAP_BUILTIN };
+
+class cmap {
+public:
+ cmap();
+ cmap(cmap_builtin);
+ int operator()(unsigned char) const;
+ unsigned char &operator[](unsigned char);
+
+ friend class cmap_init;
+private:
+ unsigned char v[UCHAR_MAX+1];
+};
+
+inline int cmap::operator()(unsigned char c) const
+{
+ return v[c];
+}
+
+inline unsigned char &cmap::operator[](unsigned char c)
+{
+ return v[c];
+}
+
+extern cmap cmlower;
+extern cmap cmupper;
+
+static class cmap_init {
+ static int initialised;
+public:
+ cmap_init();
+} _cmap_init;
diff --git a/gnu/usr.bin/groff/include/cset.h b/gnu/usr.bin/groff/include/cset.h
new file mode 100644
index 000000000000..f454cc5114d6
--- /dev/null
+++ b/gnu/usr.bin/groff/include/cset.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CC_LIMITS_H
+#include <limits.h>
+#else /* not HAVE_CC_LIMITS_H */
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 255
+#endif
+#endif /* not HAVE_CC_LIMITS_H */
+
+enum cset_builtin { CSET_BUILTIN };
+
+class cset {
+public:
+ cset();
+ cset(cset_builtin);
+ cset(const char *);
+ cset(const unsigned char *);
+ int operator()(unsigned char) const;
+
+ cset &operator|=(const cset &);
+ cset &operator|=(unsigned char);
+
+ friend class cset_init;
+private:
+ char v[UCHAR_MAX+1];
+ void clear();
+};
+
+inline int cset::operator()(unsigned char c) const
+{
+ return v[c];
+}
+
+inline cset &cset::operator|=(unsigned char c)
+{
+ v[c] = 1;
+ return *this;
+}
+
+extern cset csalpha;
+extern cset csupper;
+extern cset cslower;
+extern cset csdigit;
+extern cset csxdigit;
+extern cset csspace;
+extern cset cspunct;
+extern cset csalnum;
+extern cset csprint;
+extern cset csgraph;
+extern cset cscntrl;
+
+static class cset_init {
+ static int initialised;
+public:
+ cset_init();
+} _cset_init;
diff --git a/gnu/usr.bin/groff/include/defs.h b/gnu/usr.bin/groff/include/defs.h
new file mode 100644
index 000000000000..df2efba57eab
--- /dev/null
+++ b/gnu/usr.bin/groff/include/defs.h
@@ -0,0 +1,9 @@
+#define PROG_PREFIX ""
+#define DEVICE "ps"
+#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/include/device.h b/gnu/usr.bin/groff/include/device.h
new file mode 100644
index 000000000000..76be1334172f
--- /dev/null
+++ b/gnu/usr.bin/groff/include/device.h
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern const char *device;
diff --git a/gnu/usr.bin/groff/include/driver.h b/gnu/usr.bin/groff/include/driver.h
new file mode 100644
index 000000000000..be7a6dc6a195
--- /dev/null
+++ b/gnu/usr.bin/groff/include/driver.h
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+#include <assert.h>
+#include <math.h>
+#include "errarg.h"
+#include "error.h"
+#include "font.h"
+#include "printer.h"
+#include "lib.h"
+
+void do_file(const char *);
+extern printer *pr;
diff --git a/gnu/usr.bin/groff/include/errarg.h b/gnu/usr.bin/groff/include/errarg.h
new file mode 100644
index 000000000000..2f5ea5fc9f16
--- /dev/null
+++ b/gnu/usr.bin/groff/include/errarg.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+class errarg {
+ enum { EMPTY, STRING, CHAR, INTEGER, DOUBLE } type;
+ union {
+ const char *s;
+ int n;
+ char c;
+ double d;
+ };
+ public:
+ errarg();
+ errarg(const char *);
+ errarg(char);
+ errarg(unsigned char);
+ errarg(int);
+ errarg(double);
+ int empty() const;
+ void print() const;
+};
+
+extern errarg empty_errarg;
+
+extern void errprint(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
diff --git a/gnu/usr.bin/groff/include/error.h b/gnu/usr.bin/groff/include/error.h
new file mode 100644
index 000000000000..7a687127a399
--- /dev/null
+++ b/gnu/usr.bin/groff/include/error.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern void fatal_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void error_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void warning_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void fatal(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void error(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void warning(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+
+extern const char *program_name;
+extern int current_lineno;
+extern const char *current_filename;
+
diff --git a/gnu/usr.bin/groff/include/font.h b/gnu/usr.bin/groff/include/font.h
new file mode 100644
index 000000000000..6470b65a4c7d
--- /dev/null
+++ b/gnu/usr.bin/groff/include/font.h
@@ -0,0 +1,113 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+typedef void (*FONT_COMMAND_HANDLER)(const char *, const char *,
+ const char *, int);
+
+struct font_kern_list;
+struct font_char_metric;
+struct font_widths_cache;
+
+class font {
+public:
+ enum {
+ LIG_ff = 1,
+ LIG_fi = 2,
+ LIG_fl = 4,
+ LIG_ffi = 8,
+ LIG_ffl = 16
+ };
+
+ virtual ~font();
+ int contains(int index);
+ int is_special();
+ int get_width(int index, int point_size);
+ int get_height(int index, int point_size);
+ int get_depth(int index, int point_size);
+ int get_space_width(int point_size);
+ int get_character_type(int index);
+ int get_kern(int index1, int index2, int point_size);
+ int get_skew(int index, int point_size, int slant);
+ int has_ligature(int);
+ int get_italic_correction(int index, int point_size);
+ int get_left_italic_correction(int index, int point_size);
+ int get_subscript_correction(int index, int point_size);
+ int get_code(int i);
+ const char *get_name();
+ const char *get_internal_name();
+
+ static font *load_font(const char *, int *not_found = 0);
+ static void command_line_font_dir(const char *path);
+ static FILE *open_file(const char *name, char **pathp);
+ static int load_desc();
+ static int name_to_index(const char *);
+ static int number_to_index(int);
+ static FONT_COMMAND_HANDLER
+ set_unknown_desc_command_handler(FONT_COMMAND_HANDLER);
+
+ static int res;
+ static int hor;
+ static int vert;
+ static int unitwidth;
+ static int paperwidth;
+ static int paperlength;
+ static int biggestfont;
+ static int spare2;
+ static int sizescale;
+ static int tcommand;
+
+ static const char **font_name_table;
+ static const char **style_table;
+ static const char *family;
+ static int *sizes;
+private:
+ unsigned ligatures;
+ font_kern_list **kern_hash_table;
+ int space_width;
+ short *ch_index;
+ int nindices;
+ font_char_metric *ch;
+ int ch_used;
+ int ch_size;
+ int special;
+ char *name;
+ char *internalname;
+ double slant;
+ font_widths_cache *widths_cache;
+ static FONT_COMMAND_HANDLER unknown_desc_command_handler;
+
+ enum { KERN_HASH_TABLE_SIZE = 503 };
+
+ void add_entry(int index, const font_char_metric &);
+ void copy_entry(int new_index, int old_index);
+ void add_kern(int index1, int index2, int amount);
+ static int hash_kern(int i1, int i2);
+ void alloc_ch_index(int);
+ void extend_ch();
+ void compact();
+
+ static int scale(int w, int pointsize);
+ virtual void handle_unknown_font_command(const char *command,
+ const char *arg,
+ const char *file, int lineno);
+protected:
+ font(const char *);
+ int load(int *not_found = 0);
+};
diff --git a/gnu/usr.bin/groff/include/index.h b/gnu/usr.bin/groff/include/index.h
new file mode 100644
index 000000000000..719b0266b209
--- /dev/null
+++ b/gnu/usr.bin/groff/include/index.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define INDEX_MAGIC 0x23021964
+#define INDEX_VERSION 1
+
+struct index_header {
+ int magic;
+ int version;
+ int tags_size;
+ int table_size;
+ int lists_size;
+ int strings_size;
+ int truncate;
+ int shortest;
+ int common;
+};
+
+struct tag {
+ int filename_index;
+ int start;
+ int length;
+};
+
+unsigned hash(const char *s, int len);
diff --git a/gnu/usr.bin/groff/include/lib.h b/gnu/usr.bin/groff/include/lib.h
new file mode 100644
index 000000000000..2cee5671925b
--- /dev/null
+++ b/gnu/usr.bin/groff/include/lib.h
@@ -0,0 +1,105 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+ char *strerror(int);
+#ifndef __BORLANDC__
+ const char *itoa(int);
+ const char *iftoa(int, int);
+#endif /* __BORLANDC__ */
+};
+
+#ifdef STDLIB_H_DECLARES_GETOPT
+#include <stdlib.h>
+#else /* not STDLIB_H_DECLARES_GETOPT */
+#ifdef UNISTD_H_DECLARES_GETOPT
+#include <sys/types.h>
+#include <unistd.h>
+#else /* not UNISTD_H_DECLARES_GETOPT */
+extern "C" {
+ int getopt(int, char **, const char *);
+}
+#endif /* not UNISTD_H_DECLARES_GETOPT */
+
+extern "C" {
+ extern char *optarg;
+ extern int optind;
+ extern int opterr;
+}
+
+#endif /* not STDLIB_H_DECLARES_GETOPT */
+
+char *strsave(const char *s);
+int is_prime(unsigned);
+
+#include <stdio.h>
+
+FILE *xtmpfile();
+
+int interpret_lf_args(const char *p);
+
+extern char illegal_char_table[];
+
+inline int illegal_input_char(int c)
+{
+ return c >= 0 && illegal_char_table[c];
+}
+
+#ifdef HAVE_CC_LIMITS_H
+#include <limits.h>
+#else /* not HAVE_CC_LIMITS_H */
+#define INT_MAX 2147483647
+#endif /* not HAVE_CC_LIMITS_H */
+
+/* It's not safe to rely on people getting INT_MIN right (ie signed). */
+
+#ifdef INT_MIN
+#undef INT_MIN
+#endif
+
+#ifdef CFRONT_ANSI_BUG
+
+/* This works around a bug in cfront 2.0 used with ANSI C compilers. */
+
+#define INT_MIN ((long)(-INT_MAX-1))
+
+#else /* not CFRONT_ANSI_BUG */
+
+#define INT_MIN (-INT_MAX-1)
+
+#endif /* not CFRONT_ANSI_BUG */
+
+/* Maximum number of digits in the decimal representation of an int
+(not including the -). */
+
+#define INT_DIGITS 10
+
+/* ad_delete deletes an array of objects with destructors;
+a_delete deletes an array of objects without destructors */
+
+#ifdef ARRAY_DELETE_NEEDS_SIZE
+/* for 2.0 systems */
+#define ad_delete(size) delete [size]
+#define a_delete delete
+#else /* not ARRAY_DELETE_NEEDS_SIZE */
+/* for ARM systems */
+#define ad_delete(size) delete []
+#define a_delete delete []
+#endif /* not ARRAY_DELETE_NEEDS_SIZE */
diff --git a/gnu/usr.bin/groff/include/macropath.h b/gnu/usr.bin/groff/include/macropath.h
new file mode 100644
index 000000000000..0b0f5c307e0a
--- /dev/null
+++ b/gnu/usr.bin/groff/include/macropath.h
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern search_path macro_path;
diff --git a/gnu/usr.bin/groff/include/posix.h b/gnu/usr.bin/groff/include/posix.h
new file mode 100644
index 000000000000..fc76d90bfbb0
--- /dev/null
+++ b/gnu/usr.bin/groff/include/posix.h
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_CC_UNISTD_H
+#include <unistd.h>
+#else
+#include <osfcn.h>
+#endif
+
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#endif
+
+#ifndef S_IRGRP
+#define S_IRGRP 0040
+#endif
+
+#ifndef S_IROTH
+#define S_IROTH 0004
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
diff --git a/gnu/usr.bin/groff/include/printer.h b/gnu/usr.bin/groff/include/printer.h
new file mode 100644
index 000000000000..d517addb7208
--- /dev/null
+++ b/gnu/usr.bin/groff/include/printer.h
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct environment {
+ int fontno;
+ int size;
+ int hpos;
+ int vpos;
+ int height;
+ int slant;
+};
+
+struct font;
+
+struct font_pointer_list {
+ font *p;
+ font_pointer_list *next;
+
+ font_pointer_list(font *, font_pointer_list *);
+};
+
+class printer {
+public:
+ printer();
+ virtual ~printer();
+ void load_font(int i, const char *name);
+ void set_ascii_char(unsigned char c, const environment *env,
+ int *widthp = 0);
+ void set_special_char(const char *nm, const environment *env,
+ int *widthp = 0);
+ void set_numbered_char(int n, const environment *env, int *widthp = 0);
+ virtual void draw(int code, int *p, int np, const environment *env);
+ virtual void begin_page(int) = 0;
+ virtual void end_page(int page_length) = 0;
+ virtual font *make_font(const char *nm);
+ virtual void end_of_line();
+ virtual void special(char *arg, const environment *env);
+ static int adjust_arc_center(const int *, double *);
+protected:
+ font_pointer_list *font_list;
+private:
+ font **font_table;
+ int nfonts;
+ font *find_font(const char *);
+ virtual void set_char(int index, font *f, const environment *env,
+ int w) = 0;
+};
+
+printer *make_printer();
diff --git a/gnu/usr.bin/groff/include/ptable.h b/gnu/usr.bin/groff/include/ptable.h
new file mode 100644
index 000000000000..0e7c1996a82c
--- /dev/null
+++ b/gnu/usr.bin/groff/include/ptable.h
@@ -0,0 +1,166 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <assert.h>
+#include <string.h>
+
+#ifdef TRADITIONAL_CPP
+#define name2(a,b) a/**/b
+#else /* not TRADITIONAL_CPP */
+#define name2(a,b) name2x(a,b)
+#define name2x(a,b) a ## b
+#endif /* not TRADITIONAL_CPP */
+
+#define PTABLE(T) name2(T,_ptable)
+#define PASSOC(T) name2(T,_passoc)
+#define PTABLE_ITERATOR(T) name2(T,_ptable_iterator)
+
+extern unsigned next_ptable_size(unsigned);
+extern unsigned long hash_string(const char *);
+
+#define declare_ptable(T) \
+ \
+struct PASSOC(T) { \
+ char *key; \
+ T *val; \
+ PASSOC(T)(); \
+}; \
+ \
+struct PTABLE(T); \
+ \
+class PTABLE_ITERATOR(T) { \
+ PTABLE(T) *p; \
+ unsigned i; \
+public: \
+ PTABLE_ITERATOR(T)(PTABLE(T) *); \
+ int next(const char **, T **); \
+}; \
+ \
+class PTABLE(T) { \
+ PASSOC(T) *v; \
+ unsigned size; \
+ unsigned used; \
+ enum { FULL_NUM = 2, FULL_DEN = 3, INITIAL_SIZE = 17 }; \
+public: \
+ PTABLE(T)(); \
+ ~PTABLE(T)(); \
+ void define(const char *, T *); \
+ T *lookup(const char *); \
+ friend class PTABLE_ITERATOR(T); \
+};
+
+
+#define implement_ptable(T) \
+ \
+PASSOC(T)::PASSOC(T)() \
+: key(0), val(0) \
+{ \
+} \
+ \
+PTABLE(T)::PTABLE(T)() \
+{ \
+ v = new PASSOC(T)[size = INITIAL_SIZE]; \
+ used = 0; \
+} \
+ \
+PTABLE(T)::~PTABLE(T)() \
+{ \
+ for (unsigned i = 0; i < size; i++) { \
+ a_delete v[i].key; \
+ delete v[i].val; \
+ } \
+ a_delete v; \
+} \
+ \
+void PTABLE(T)::define(const char *key, T *val) \
+{ \
+ assert(key != 0); \
+ unsigned long h = hash_string(key); \
+ for (unsigned n = unsigned(h % size); \
+ v[n].key != 0; \
+ n = (n == 0 ? size - 1 : n - 1)) \
+ if (strcmp(v[n].key, key) == 0) { \
+ delete v[n].val; \
+ v[n].val = val; \
+ return; \
+ } \
+ if (val == 0) \
+ return; \
+ if (used*FULL_DEN >= size*FULL_NUM) { \
+ PASSOC(T) *oldv = v; \
+ unsigned old_size = size; \
+ size = next_ptable_size(size); \
+ v = new PASSOC(T)[size]; \
+ for (unsigned i = 0; i < old_size; i++) \
+ if (oldv[i].key != 0) { \
+ if (oldv[i].val == 0) \
+ a_delete oldv[i].key; \
+ else { \
+ for (unsigned j = unsigned(hash_string(oldv[i].key) % size); \
+ v[j].key != 0; \
+ j = (j == 0 ? size - 1 : j - 1)) \
+ ; \
+ v[j].key = oldv[i].key; \
+ v[j].val = oldv[i].val; \
+ } \
+ } \
+ for (n = unsigned(h % size); \
+ v[n].key != 0; \
+ n = (n == 0 ? size - 1 : n - 1)) \
+ ; \
+ a_delete oldv; \
+ } \
+ char *temp = new char[strlen(key)+1]; \
+ strcpy(temp, key); \
+ v[n].key = temp; \
+ v[n].val = val; \
+ used++; \
+} \
+ \
+T *PTABLE(T)::lookup(const char *key) \
+{ \
+ assert(key != 0); \
+ for (unsigned n = unsigned(hash_string(key) % size); \
+ v[n].key != 0; \
+ n = (n == 0 ? size - 1 : n - 1)) \
+ if (strcmp(v[n].key, key) == 0) \
+ return v[n].val; \
+ return 0; \
+} \
+ \
+PTABLE_ITERATOR(T)::PTABLE_ITERATOR(T)(PTABLE(T) *t) \
+: p(t), i(0) \
+{ \
+} \
+ \
+int PTABLE_ITERATOR(T)::next(const char **keyp, T **valp) \
+{ \
+ unsigned size = p->size; \
+ PASSOC(T) *v = p->v; \
+ for (; i < size; i++) \
+ if (v[i].key != 0) { \
+ *keyp = v[i].key; \
+ *valp = v[i].val; \
+ i++; \
+ return 1; \
+ } \
+ return 0; \
+}
+
diff --git a/gnu/usr.bin/groff/include/refid.h b/gnu/usr.bin/groff/include/refid.h
new file mode 100644
index 000000000000..a0e86a31f8fd
--- /dev/null
+++ b/gnu/usr.bin/groff/include/refid.h
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+class reference_id {
+ int filename_id;
+ int pos;
+public:
+ reference_id() : filename_id(-1) { }
+ reference_id(int fid, int off) : filename_id(fid), pos(off) { }
+ unsigned hash() const { return (filename_id << 4) + pos; }
+ int is_null() const { return filename_id < 0; }
+ friend inline int operator==(const reference_id &, const reference_id &);
+};
+
+inline int operator==(const reference_id &r1, const reference_id &r2)
+{
+ return r1.filename_id == r2.filename_id && r1.pos == r2.pos;
+}
diff --git a/gnu/usr.bin/groff/include/search.h b/gnu/usr.bin/groff/include/search.h
new file mode 100644
index 000000000000..e1fdb84530aa
--- /dev/null
+++ b/gnu/usr.bin/groff/include/search.h
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct search_item;
+struct search_item_iterator;
+
+class search_list {
+public:
+ search_list();
+ ~search_list();
+ void add_file(const char *fn, int silent = 0);
+ int nfiles() const;
+private:
+ search_item *list;
+ int niterators;
+ int next_fid;
+ friend class search_list_iterator;
+};
+
+struct bmpattern;
+
+class linear_searcher {
+ const char *ignore_fields;
+ int truncate_len;
+ bmpattern **keys;
+ int nkeys;
+ const char *search_and_check(const bmpattern *key, const char *buf,
+ const char *bufend, const char **start = 0)
+ const;
+ int check_match(const char *buf, const char *bufend, const char *match,
+ int matchlen, const char **cont, const char **start)
+ const;
+public:
+ linear_searcher(const char *query, int query_len,
+ const char *ign, int trunc);
+ ~linear_searcher();
+ int search(const char *buf, const char *bufend,
+ const char **startp, int *lengthp) const;
+};
+
+class search_list_iterator {
+ search_list *list;
+ search_item *ptr;
+ search_item_iterator *iter;
+ char *query;
+ linear_searcher searcher;
+public:
+ search_list_iterator(search_list *, const char *query);
+ ~search_list_iterator();
+ int next(const char **, int *, reference_id * = 0);
+};
+
+class search_item {
+protected:
+ char *name;
+ int filename_id;
+public:
+ search_item *next;
+ search_item(const char *nm, int fid);
+ virtual search_item_iterator *make_search_item_iterator(const char *) = 0;
+ virtual ~search_item();
+ int is_named(const char *) const;
+ virtual int next_filename_id() const;
+};
+
+class search_item_iterator {
+ char shut_g_plus_plus_up;
+public:
+ virtual ~search_item_iterator();
+ virtual int next(const linear_searcher &, const char **ptr, int *lenp,
+ reference_id *) = 0;
+};
+
+search_item *make_index_search_item(const char *filename, int fid);
+search_item *make_linear_search_item(int fd, const char *filename, int fid);
+
+extern int linear_truncate_len;
+extern const char *linear_ignore_fields;
+extern int verify_flag;
diff --git a/gnu/usr.bin/groff/include/searchpath.h b/gnu/usr.bin/groff/include/searchpath.h
new file mode 100644
index 000000000000..14a74f672dd5
--- /dev/null
+++ b/gnu/usr.bin/groff/include/searchpath.h
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+class search_path {
+ char *dirs;
+ unsigned init_len;
+public:
+ search_path(const char *envvar, const char *standard);
+ ~search_path();
+ void command_line_dir(const char *);
+ FILE *open_file(const char *, char **);
+};
diff --git a/gnu/usr.bin/groff/include/stringclass.h b/gnu/usr.bin/groff/include/stringclass.h
new file mode 100644
index 000000000000..570f47ac71a0
--- /dev/null
+++ b/gnu/usr.bin/groff/include/stringclass.h
@@ -0,0 +1,174 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+class string {
+public:
+ string();
+ string(const string &);
+ string(const char *);
+ string(const char *, int);
+ string(char);
+
+ ~string();
+
+ string &operator=(const string &);
+ string &operator=(const char *);
+ string &operator=(char);
+
+ string &operator+=(const string &);
+ string &operator+=(const char *);
+ string &operator+=(char);
+ void append(const char *, int);
+
+ int length() const;
+ int empty() const;
+ int operator*() const;
+
+ string substring(int i, int n) const;
+
+ char &operator[](int);
+ char operator[](int) const;
+
+ void set_length(int i);
+ const char *contents() const;
+ int search(char) const;
+ char *extract() const;
+ void clear();
+ void move(string &);
+
+ friend inline string operator+(const string &, const string &);
+ friend inline string operator+(const string &, const char *);
+ friend inline string operator+(const char *, const string &);
+ friend inline string operator+(const string &, char);
+ friend inline string operator+(char, const string &);
+
+ friend inline int operator==(const string &, const string &);
+ friend inline int operator!=(const string &, const string &);
+ friend int operator<=(const string &, const string &);
+ friend int operator<(const string &, const string &);
+ friend int operator>=(const string &, const string &);
+ friend int operator>(const string &, const string &);
+
+private:
+ char *ptr;
+ int len;
+ int sz;
+
+ string(const char *, int, const char *, int); // for use by operator+
+ void grow1();
+};
+
+
+inline char &string::operator[](int i)
+{
+ assert(i >= 0 && i < len);
+ return ptr[i];
+}
+
+inline char string::operator[](int i) const
+{
+ assert(i >= 0 && i < len);
+ return ptr[i];
+}
+
+inline int string::length() const
+{
+ return len;
+}
+
+inline int string::empty() const
+{
+ return len == 0;
+}
+
+inline int string::operator*() const
+{
+ return len;
+}
+
+inline const char *string::contents() const
+{
+ return ptr;
+}
+
+inline string operator+(const string &s1, const string &s2)
+{
+ return string(s1.ptr, s1.len, s2.ptr, s2.len);
+}
+
+inline string operator+(const string &s1, const char *s2)
+{
+ if (s2 == 0)
+ return s1;
+ else
+ return string(s1.ptr, s1.len, s2, strlen(s2));
+}
+
+inline string operator+(const char *s1, const string &s2)
+{
+ if (s1 == 0)
+ return s2;
+ else
+ return string(s1, strlen(s1), s2.ptr, s2.len);
+}
+
+inline string operator+(const string &s, char c)
+{
+ return string(s.ptr, s.len, &c, 1);
+}
+
+inline string operator+(char c, const string &s)
+{
+ return string(&c, 1, s.ptr, s.len);
+}
+
+inline int operator==(const string &s1, const string &s2)
+{
+ return (s1.len == s2.len
+ && (s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) == 0));
+}
+
+inline int operator!=(const string &s1, const string &s2)
+{
+ return (s1.len != s2.len
+ || (s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) != 0));
+}
+
+inline string string::substring(int i, int n) const
+{
+ assert(i >= 0 && i + n <= len);
+ return string(ptr + i, n);
+}
+
+inline string &string::operator+=(char c)
+{
+ if (len >= sz)
+ grow1();
+ ptr[len++] = c;
+ return *this;
+}
+
+void put_string(const string &, FILE *);
+
+string as_string(int);
diff --git a/gnu/usr.bin/groff/include/unix.h b/gnu/usr.bin/groff/include/unix.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/gnu/usr.bin/groff/include/unix.h
diff --git a/gnu/usr.bin/groff/indxbib/Makefile b/gnu/usr.bin/groff/indxbib/Makefile
new file mode 100644
index 000000000000..de95d7765b34
--- /dev/null
+++ b/gnu/usr.bin/groff/indxbib/Makefile
@@ -0,0 +1,20 @@
+# Makefile for indxbib
+
+PROG= indxbib
+SRCS= indxbib.cc dirnamemax.c signal.c
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBBIB) $(LIBGROFF) -lm
+DPADD+= $(LIBBIB) $(LIBGROFF) $(LIBMATH)
+
+# Ugh - I can't grab /usr/share from ../../../share/Makefile.inc
+# since I've already grabbed a BINDIR file for installing indxbib.
+# Sigh... Hardcode it. - jkh
+#
+afterinstall:
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/eign \
+ $(DESTDIR)/usr/share/dict
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/indxbib/dirnamemax.c b/gnu/usr.bin/groff/indxbib/dirnamemax.c
new file mode 100644
index 000000000000..dff7b05546e0
--- /dev/null
+++ b/gnu/usr.bin/groff/indxbib/dirnamemax.c
@@ -0,0 +1,49 @@
+/* dir_name_max(dir) does the same as pathconf(dir, _PC_NAME_MAX) */
+
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined(_POSIX_VERSION) && !defined(__FreeBSD__)
+
+long dir_name_max(dir)
+ char *dir;
+{
+ return pathconf(dir, _PC_NAME_MAX);
+}
+
+#else /* not _POSIX_VERSION */
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif /* HAVE_LIMITS_H */
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#else /* not HAVE_DIRENT_H */
+#ifdef HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif /* HAVE_SYS_DIR_H */
+#endif /* not HAVE_DIRENT_H */
+
+#ifndef NAME_MAX
+#ifdef MAXNAMLEN
+#define NAME_MAX MAXNAMLEN
+#else /* !MAXNAMLEN */
+#ifdef MAXNAMELEN
+#define NAME_MAX MAXNAMELEN
+#else /* !MAXNAMELEN */
+#define NAME_MAX 14
+#endif /* !MAXNAMELEN */
+#endif /* !MAXNAMLEN */
+#endif /* !NAME_MAX */
+
+long dir_name_max(dir)
+ char *dir;
+{
+ return NAME_MAX;
+}
+
+#endif /* not _POSIX_VERSION */
diff --git a/gnu/usr.bin/groff/indxbib/eign b/gnu/usr.bin/groff/indxbib/eign
new file mode 100644
index 000000000000..7718c8b1124c
--- /dev/null
+++ b/gnu/usr.bin/groff/indxbib/eign
@@ -0,0 +1,133 @@
+a
+i
+the
+to
+of
+and
+in
+is
+it
+for
+that
+if
+you
+this
+be
+on
+with
+not
+have
+are
+or
+as
+from
+can
+but
+by
+at
+an
+will
+no
+all
+was
+do
+there
+my
+one
+so
+we
+they
+what
+would
+any
+which
+about
+get
+your
+use
+some
+me
+then
+name
+like
+out
+when
+up
+time
+other
+more
+only
+just
+end
+also
+know
+how
+new
+should
+been
+than
+them
+he
+who
+make
+may
+people
+these
+now
+their
+here
+into
+first
+could
+way
+had
+see
+work
+well
+were
+two
+very
+where
+while
+us
+because
+good
+same
+even
+much
+most
+many
+such
+long
+his
+over
+last
+since
+right
+before
+our
+without
+too
+those
+why
+must
+part
+being
+current
+back
+still
+go
+point
+value
+each
+did
+both
+true
+off
+say
+another
+state
+might
+under
+start
+try
diff --git a/gnu/usr.bin/groff/indxbib/indxbib.1 b/gnu/usr.bin/groff/indxbib/indxbib.1
new file mode 100644
index 000000000000..54114bf12383
--- /dev/null
+++ b/gnu/usr.bin/groff/indxbib/indxbib.1
@@ -0,0 +1,187 @@
+.\" -*- nroff -*-
+.TH INDXBIB 1 "16 April 1993" "Groff Version 1.08"
+.SH NAME
+indxbib \- make inverted index for bibliographic databases
+.SH SYNOPSIS
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBindxbib 'u
+.ti \niu
+.B indxbib
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-vw
+.OP \-c file
+.OP \-d dir
+.OP \-f file
+.OP \-h n
+.OP \-i string
+.OP \-k n
+.OP \-l n
+.OP \-n n
+.OP \-o file
+.OP \-t n
+.RI [\ filename \|.\|.\|.\ ]
+.ad \na
+.SH DESCRIPTION
+.B indxbib
+makes an inverted index for the bibliographic databases in
+.IR filename \|.\|.\|.
+for use with
+.BR refer (1),
+.BR lookbib (1),
+and
+.BR lkbib (1).
+The index will be named
+.IB filename .i\fR;
+the index is written to a temporary file which is then renamed to this.
+If no filenames are given on the command line because the
+.B \-f
+option has been used, and no
+.B \-o
+option is given, the index will be named
+.BR Ind.i .
+.LP
+Bibliographic databases are divided into records by blank lines.
+Within a record, each fields starts with a
+.B %
+character at the beginning of a line.
+Fields have a one letter name which follows the
+.B %
+character.
+.LP
+The values set by the
+.BR \-c ,
+.BR \-n ,
+.BR \-l
+and
+.B \-t
+options are stored in the index;
+when the index is searched, keys will be discarded and truncated in a
+manner appropriate to these options;
+the original keys will be used for verifying that any record
+found using the index actually contains the keys.
+This means that a user of an index need not know whether these
+options were used in the creation of the index,
+provided that not all the keys to be searched for
+would have been discarded during indexing
+and that the user supplies at least the part of each key
+that would have remained after being truncated during indexing.
+The value set by the
+.B \-i
+option is also stored in the index
+and will be used in verifying records found using the index.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-w
+Index whole files.
+Each file is a separate record.
+.TP
+.BI \-c file
+Read the list of common words from
+.I file
+instead of
+.BR /usr/share/dict/eign .
+.TP
+.BI \-d dir
+Use
+.I dir
+as the pathname of the current working directory to store in the index,
+instead of the path printed by
+.BR pwd (1).
+Usually
+.I dir
+will be a symbolic link that points to the directory printed by
+.BR pwd (1).
+.TP
+.BI \-f file
+Read the files to be indexed from
+.IR file .
+If
+.I file
+is
+.BR \- ,
+files will be read from the standard input.
+The
+.B \-f
+option can be given at most once.
+.TP
+.BI \-i string
+Don't index the contents of fields whose names are in
+.IR string .
+Initially
+.I string
+is
+.BR XYZ .
+.TP
+.BI \-h n
+Use the first prime greater than or equal to
+.I n
+for the size of the hash table.
+Larger values of
+.I n
+will usually make searching faster,
+but will make the index larger
+and
+.B indxbib
+use more memory.
+Initially
+.I n
+is 997.
+.TP
+.BI \-k n
+Use at most
+.I n
+keys per input record.
+Initially
+.I n
+is 100.
+.TP
+.BI \-l n
+Discard keys that are shorter than
+.IR n .
+Initially
+.I n
+is 3.
+.TP
+.BI \-n n
+Discard the
+.I n
+most common words.
+Initially
+.I n
+is 100.
+.TP
+.BI \-o basename
+The index should be named
+.IB basename .i\fR.
+.TP
+.BI \-t n
+Truncate keys to
+.IR n .
+Initially
+.I n
+is 6.
+.SH FILES
+.TP \w'\fBindxbib\fIXXXXXX'u+2n
+.IB filename .i
+Index.
+.TP
+.B Ind.i
+Default index name.
+.TP
+.B /usr/share/dict/eign
+List of common words.
+.TP
+.BI indxbib XXXXXX
+Temporary file.
+.SH "SEE ALSO"
+.BR refer (1),
+.BR lkbib (1),
+.BR lookbib (1)
diff --git a/gnu/usr.bin/groff/indxbib/indxbib.cc b/gnu/usr.bin/groff/indxbib/indxbib.cc
new file mode 100644
index 000000000000..b2d1a263af5d
--- /dev/null
+++ b/gnu/usr.bin/groff/indxbib/indxbib.cc
@@ -0,0 +1,742 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "cmap.h"
+
+#include "defs.h"
+#include "index.h"
+
+extern "C" {
+ // Sun's stdlib.h fails to declare this.
+ char *mktemp(char *);
+}
+
+#define DEFAULT_HASH_TABLE_SIZE 997
+#define TEMP_INDEX_TEMPLATE "indxbibXXXXXX"
+
+// (2^n - MALLOC_OVERHEAD) should be a good argument for malloc().
+
+#define MALLOC_OVERHEAD 16
+
+#ifdef BLOCK_SIZE
+#undef BLOCK_SIZE
+#endif
+
+const int BLOCK_SIZE = ((1024 - MALLOC_OVERHEAD - sizeof(struct block *)
+ - sizeof(int)) / sizeof(int));
+struct block {
+ block *next;
+ int used;
+ int v[BLOCK_SIZE];
+
+ block(block *p = 0) : next(p), used(0) { }
+};
+
+struct block;
+
+union table_entry {
+ block *ptr;
+ int count;
+};
+
+struct word_list {
+ word_list *next;
+ char *str;
+ int len;
+ word_list(const char *, int, word_list *);
+};
+
+table_entry *hash_table;
+int hash_table_size = DEFAULT_HASH_TABLE_SIZE;
+// We make this the same size as hash_table so we only have to do one
+// mod per key.
+static word_list **common_words_table = 0;
+char *key_buffer;
+
+FILE *indxfp;
+int ntags = 0;
+string filenames;
+char *temp_index_file = 0;
+
+const char *ignore_fields = "XYZ";
+const char *common_words_file = COMMON_WORDS_FILE;
+int n_ignore_words = 100;
+int truncate_len = 6;
+int shortest_len = 3;
+int max_keys_per_item = 100;
+
+static void usage();
+static void write_hash_table();
+static void init_hash_table();
+static void read_common_words_file();
+static int store_key(char *s, int len);
+static void possibly_store_key(char *s, int len);
+static int do_whole_file(const char *filename);
+static int do_file(const char *filename);
+static void store_reference(int filename_index, int pos, int len);
+static void check_integer_arg(char opt, const char *arg, int min, int *res);
+static void store_filename(const char *);
+static void fwrite_or_die(const void *ptr, int size, int nitems, FILE *fp);
+static char *get_cwd();
+
+extern "C" {
+ void cleanup();
+ long dir_name_max(const char *);
+ void catch_fatal_signals();
+ void ignore_fatal_signals();
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+
+ const char *basename = 0;
+ typedef int (*parser_t)(const char *);
+ parser_t parser = do_file;
+ const char *directory = 0;
+ const char *foption = 0;
+ int opt;
+ while ((opt = getopt(argc, argv, "c:o:h:i:k:l:t:n:c:d:f:vw")) != EOF)
+ switch (opt) {
+ case 'c':
+ common_words_file = optarg;
+ break;
+ case 'd':
+ directory = optarg;
+ break;
+ case 'f':
+ foption = optarg;
+ break;
+ case 'h':
+ check_integer_arg('h', optarg, 1, &hash_table_size);
+ if (!is_prime(hash_table_size)) {
+ while (!is_prime(++hash_table_size))
+ ;
+ warning("%1 not prime: using %2 instead", optarg, hash_table_size);
+ }
+ break;
+ case 'i':
+ ignore_fields = optarg;
+ break;
+ case 'k':
+ check_integer_arg('k', optarg, 1, &max_keys_per_item);
+ break;
+ case 'l':
+ check_integer_arg('l', optarg, 0, &shortest_len);
+ break;
+ case 'n':
+ check_integer_arg('n', optarg, 0, &n_ignore_words);
+ break;
+ case 'o':
+ basename = optarg;
+ break;
+ case 't':
+ check_integer_arg('t', optarg, 1, &truncate_len);
+ break;
+ case 'w':
+ parser = do_whole_file;
+ break;
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU indxbib version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (optind >= argc && foption == 0)
+ fatal("no files and no -f option");
+ if (!directory) {
+ char *path = get_cwd();
+ store_filename(path);
+ a_delete path;
+ }
+ else
+ store_filename(directory);
+ init_hash_table();
+ store_filename(common_words_file);
+ store_filename(ignore_fields);
+ key_buffer = new char[truncate_len];
+ read_common_words_file();
+ if (!basename)
+ basename = optind < argc ? argv[optind] : DEFAULT_INDEX_NAME;
+ const char *p = strrchr(basename, '/');
+ long name_max;
+ if (p) {
+ char *dir = strsave(basename);
+ dir[p - basename] = '\0';
+ name_max = dir_name_max(dir);
+ a_delete dir;
+ }
+ else
+ name_max = dir_name_max(".");
+ const char *filename = p ? p + 1 : basename;
+ if (name_max >= 0 && strlen(filename) + sizeof(INDEX_SUFFIX) - 1 > name_max)
+ fatal("`%1.%2' is too long for a filename", filename, INDEX_SUFFIX);
+ if (p) {
+ p++;
+ temp_index_file = new char[p - basename + sizeof(TEMP_INDEX_TEMPLATE)];
+ memcpy(temp_index_file, basename, p - basename);
+ strcpy(temp_index_file + (p - basename), TEMP_INDEX_TEMPLATE);
+ }
+ else {
+ temp_index_file = strsave(TEMP_INDEX_TEMPLATE);
+ }
+ if (!mktemp(temp_index_file) || !temp_index_file[0])
+ fatal("cannot create file name for temporary file");
+ catch_fatal_signals();
+ int fd = creat(temp_index_file, S_IRUSR|S_IRGRP|S_IROTH);
+ if (fd < 0)
+ fatal("can't create temporary index file: %1", strerror(errno));
+ indxfp = fdopen(fd, "w");
+ if (indxfp == 0)
+ fatal("fdopen failed");
+ if (fseek(indxfp, sizeof(index_header), 0) < 0)
+ fatal("can't seek past index header: %1", strerror(errno));
+ int failed = 0;
+ if (foption) {
+ FILE *fp = stdin;
+ if (strcmp(foption, "-") != 0) {
+ errno = 0;
+ fp = fopen(foption, "r");
+ if (!fp)
+ fatal("can't open `%1': %2", foption, strerror(errno));
+ }
+ string path;
+ int lineno = 1;
+ for (;;) {
+ for (int c = getc(fp); c != '\n' && c != EOF; c = getc(fp)) {
+ if (c == '\0')
+ error_with_file_and_line(foption, lineno,
+ "nul character in pathname ignored");
+ else
+ path += c;
+ }
+ if (path.length() > 0) {
+ path += '\0';
+ if (!(*parser)(path.contents()))
+ failed = 1;
+ path.clear();
+ }
+ if (c == EOF)
+ break;
+ lineno++;
+ }
+ if (fp != stdin)
+ fclose(fp);
+ }
+ for (int i = optind; i < argc; i++)
+ if (!(*parser)(argv[i]))
+ failed = 1;
+ write_hash_table();
+ if (fclose(indxfp) < 0)
+ fatal("error closing temporary index file: %1", strerror(errno));
+ char *index_file = new char[strlen(basename) + sizeof(INDEX_SUFFIX)];
+ strcpy(index_file, basename);
+ strcat(index_file, INDEX_SUFFIX);
+#ifdef HAVE_RENAME
+ if (rename(temp_index_file, index_file) < 0)
+ fatal("can't rename temporary index file: %1", strerror(errno));
+#else /* not HAVE_RENAME */
+ ignore_fatal_signals();
+ if (unlink(index_file) < 0) {
+ if (errno != ENOENT)
+ fatal("can't unlink `%1': %2", index_file, strerror(errno));
+ }
+ if (link(temp_index_file, index_file) < 0)
+ fatal("can't link temporary index file: %1", strerror(errno));
+ if (unlink(temp_index_file) < 0)
+ fatal("can't unlink temporary index file: %1", strerror(errno));
+#endif /* not HAVE_RENAME */
+ temp_index_file = 0;
+ exit(failed);
+}
+
+static void usage()
+{
+ fprintf(stderr,
+"usage: %s [-vw] [-c file] [-d dir] [-f file] [-h n] [-i XYZ] [-k n]\n"
+" [-l n] [-n n] [-o base] [-t n] [files...]\n",
+ program_name);
+ exit(1);
+}
+
+static void check_integer_arg(char opt, const char *arg, int min, int *res)
+{
+ char *ptr;
+ long n = strtol(arg, &ptr, 10);
+ if (n == 0 && ptr == arg)
+ error("argument to -%1 not an integer", opt);
+ else if (n < min)
+ error("argument to -%1 must not be less than %2", opt, min);
+ else {
+ if (n > INT_MAX)
+ error("argument to -%1 greater than maximum integer", opt);
+ else if (*ptr != '\0')
+ error("junk after integer argument to -%1", opt);
+ *res = int(n);
+ }
+}
+
+static char *get_cwd()
+{
+ char *buf;
+ int size = 12;
+
+ for (;;) {
+ buf = new char[size];
+ if (getcwd(buf, size))
+ break;
+ if (errno != ERANGE)
+ fatal("cannot get current working directory: %1", strerror(errno));
+ a_delete buf;
+ if (size == INT_MAX)
+ fatal("current working directory longer than INT_MAX");
+ if (size > INT_MAX/2)
+ size = INT_MAX;
+ else
+ size *= 2;
+ }
+ return buf;
+}
+
+word_list::word_list(const char *s, int n, word_list *p)
+: next(p), len(n)
+{
+ str = new char[n];
+ memcpy(str, s, n);
+}
+
+static void read_common_words_file()
+{
+ if (n_ignore_words <= 0)
+ return;
+ errno = 0;
+ FILE *fp = fopen(common_words_file, "r");
+ if (!fp)
+ fatal("can't open `%1': %2", common_words_file, strerror(errno));
+ common_words_table = new word_list * [hash_table_size];
+ for (int i = 0; i < hash_table_size; i++)
+ common_words_table[i] = 0;
+ int count = 0;
+ int key_len = 0;
+ for (;;) {
+ int c = getc(fp);
+ while (c != EOF && !csalnum(c))
+ c = getc(fp);
+ if (c == EOF)
+ break;
+ do {
+ if (key_len < truncate_len)
+ key_buffer[key_len++] = cmlower(c);
+ c = getc(fp);
+ } while (c != EOF && csalnum(c));
+ if (key_len >= shortest_len) {
+ int h = hash(key_buffer, key_len) % hash_table_size;
+ common_words_table[h] = new word_list(key_buffer, key_len,
+ common_words_table[h]);
+ }
+ if (++count >= n_ignore_words)
+ break;
+ key_len = 0;
+ if (c == EOF)
+ break;
+ }
+ n_ignore_words = count;
+ fclose(fp);
+}
+
+static int do_whole_file(const char *filename)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (!fp) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ int count = 0;
+ int key_len = 0;
+ int c;
+ while ((c = getc(fp)) != EOF) {
+ if (csalnum(c)) {
+ key_len = 1;
+ key_buffer[0] = c;
+ while ((c = getc(fp)) != EOF) {
+ if (!csalnum(c))
+ break;
+ if (key_len < truncate_len)
+ key_buffer[key_len++] = c;
+ }
+ if (store_key(key_buffer, key_len)) {
+ if (++count >= max_keys_per_item)
+ break;
+ }
+ if (c == EOF)
+ break;
+ }
+ }
+ store_reference(filenames.length(), 0, 0);
+ store_filename(filename);
+ fclose(fp);
+ return 1;
+}
+
+static int do_file(const char *filename)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ int filename_index = filenames.length();
+ store_filename(filename);
+
+ enum {
+ START, // at the start of the file; also in between references
+ BOL, // in the middle of a reference, at the beginning of the line
+ PERCENT, // seen a percent at the beginning of the line
+ IGNORE, // ignoring a field
+ IGNORE_BOL, // at the beginning of a line ignoring a field
+ KEY, // in the middle of a key
+ DISCARD, // after truncate_len bytes of a key
+ MIDDLE // in between keys
+ } state = START;
+
+ // In states START, BOL, IGNORE_BOL, space_count how many spaces at
+ // the beginning have been seen. In states PERCENT, IGNORE, KEY,
+ // MIDDLE space_count must be 0.
+ int space_count = 0;
+ int byte_count = 0; // bytes read
+ int key_len = 0;
+ int ref_start = -1; // position of start of current reference
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ byte_count++;
+ switch (state) {
+ case START:
+ if (c == ' ' || c == '\t') {
+ space_count++;
+ break;
+ }
+ if (c == '\n') {
+ space_count = 0;
+ break;
+ }
+ ref_start = byte_count - space_count - 1;
+ space_count = 0;
+ if (c == '%')
+ state = PERCENT;
+ else if (csalnum(c)) {
+ state = KEY;
+ key_buffer[0] = c;
+ key_len = 1;
+ }
+ else
+ state = MIDDLE;
+ break;
+ case BOL:
+ switch (c) {
+ case '%':
+ if (space_count > 0) {
+ space_count = 0;
+ state = MIDDLE;
+ }
+ else
+ state = PERCENT;
+ break;
+ case ' ':
+ case '\t':
+ space_count++;
+ break;
+ case '\n':
+ store_reference(filename_index, ref_start,
+ byte_count - 1 - space_count - ref_start);
+ state = START;
+ space_count = 0;
+ break;
+ default:
+ space_count = 0;
+ if (csalnum(c)) {
+ state = KEY;
+ key_buffer[0] = c;
+ key_len = 1;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case PERCENT:
+ if (strchr(ignore_fields, c) != 0)
+ state = IGNORE;
+ else if (c == '\n')
+ state = BOL;
+ else
+ state = MIDDLE;
+ break;
+ case IGNORE:
+ if (c == '\n')
+ state = IGNORE_BOL;
+ break;
+ case IGNORE_BOL:
+ switch (c) {
+ case '%':
+ if (space_count > 0) {
+ state = IGNORE;
+ space_count = 0;
+ }
+ else
+ state = PERCENT;
+ break;
+ case ' ':
+ case '\t':
+ space_count++;
+ break;
+ case '\n':
+ store_reference(filename_index, ref_start,
+ byte_count - 1 - space_count - ref_start);
+ state = START;
+ space_count = 0;
+ break;
+ default:
+ space_count = 0;
+ state = IGNORE;
+ }
+ break;
+ case KEY:
+ if (csalnum(c)) {
+ if (key_len < truncate_len)
+ key_buffer[key_len++] = c;
+ else
+ state = DISCARD;
+ }
+ else {
+ possibly_store_key(key_buffer, key_len);
+ key_len = 0;
+ if (c == '\n')
+ state = BOL;
+ else
+ state = MIDDLE;
+ }
+ break;
+ case DISCARD:
+ if (!csalnum(c)) {
+ possibly_store_key(key_buffer, key_len);
+ key_len = 0;
+ if (c == '\n')
+ state = BOL;
+ else
+ state = MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ if (csalnum(c)) {
+ state = KEY;
+ key_buffer[0] = c;
+ key_len = 1;
+ }
+ else if (c == '\n')
+ state = BOL;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ switch (state) {
+ case START:
+ break;
+ case DISCARD:
+ case KEY:
+ possibly_store_key(key_buffer, key_len);
+ // fall through
+ case BOL:
+ case PERCENT:
+ case IGNORE_BOL:
+ case IGNORE:
+ case MIDDLE:
+ store_reference(filename_index, ref_start,
+ byte_count - ref_start - space_count);
+ break;
+ default:
+ assert(0);
+ }
+ fclose(fp);
+ return 1;
+}
+
+static void store_reference(int filename_index, int pos, int len)
+{
+ tag t;
+ t.filename_index = filename_index;
+ t.start = pos;
+ t.length = len;
+ fwrite_or_die(&t, sizeof(t), 1, indxfp);
+ ntags++;
+}
+
+static void store_filename(const char *fn)
+{
+ filenames += fn;
+ filenames += '\0';
+}
+
+static void init_hash_table()
+{
+ hash_table = new table_entry[hash_table_size];
+ for (int i = 0; i < hash_table_size; i++)
+ hash_table[i].ptr = 0;
+}
+
+static void possibly_store_key(char *s, int len)
+{
+ static int last_tagno = -1;
+ static int key_count;
+ if (last_tagno != ntags) {
+ last_tagno = ntags;
+ key_count = 0;
+ }
+ if (key_count < max_keys_per_item) {
+ if (store_key(s, len))
+ key_count++;
+ }
+}
+
+static int store_key(char *s, int len)
+{
+ if (len < shortest_len)
+ return 0;
+ int is_number = 1;
+ for (int i = 0; i < len; i++)
+ if (!csdigit(s[i])) {
+ is_number = 0;
+ s[i] = cmlower(s[i]);
+ }
+ if (is_number && !(len == 4 && s[0] == '1' && s[1] == '9'))
+ return 0;
+ int h = hash(s, len) % hash_table_size;
+ if (common_words_table) {
+ for (word_list *ptr = common_words_table[h]; ptr; ptr = ptr->next)
+ if (len == ptr->len && memcmp(s, ptr->str, len) == 0)
+ return 0;
+ }
+ table_entry *pp = hash_table + h;
+ if (!pp->ptr)
+ pp->ptr = new block;
+ else if (pp->ptr->v[pp->ptr->used - 1] == ntags)
+ return 1;
+ else if (pp->ptr->used >= BLOCK_SIZE)
+ pp->ptr = new block(pp->ptr);
+ pp->ptr->v[(pp->ptr->used)++] = ntags;
+ return 1;
+}
+
+static void write_hash_table()
+{
+ const int minus_one = -1;
+ int li = 0;
+ for (int i = 0; i < hash_table_size; i++) {
+ block *ptr = hash_table[i].ptr;
+ if (!ptr)
+ hash_table[i].count = -1;
+ else {
+ hash_table[i].count = li;
+ block *rev = 0;
+ while (ptr) {
+ block *tem = ptr;
+ ptr = ptr->next;
+ tem->next = rev;
+ rev = tem;
+ }
+ while (rev) {
+ fwrite_or_die(rev->v, sizeof(int), rev->used, indxfp);
+ li += rev->used;
+ block *tem = rev;
+ rev = rev->next;
+ delete tem;
+ }
+ fwrite_or_die(&minus_one, sizeof(int), 1, indxfp);
+ li += 1;
+ }
+ }
+ if (sizeof(table_entry) == sizeof(int))
+ fwrite_or_die(hash_table, sizeof(int), hash_table_size, indxfp);
+ else {
+ assert(0);
+ // write it out word by word
+ }
+ fwrite_or_die(filenames.contents(), 1, filenames.length(), indxfp);
+ if (fseek(indxfp, 0, 0) < 0)
+ fatal("error seeking on index file: %1", strerror(errno));
+ index_header h;
+ h.magic = INDEX_MAGIC;
+ h.version = INDEX_VERSION;
+ h.tags_size = ntags;
+ h.lists_size = li;
+ h.table_size = hash_table_size;
+ h.strings_size = filenames.length();
+ h.truncate = truncate_len;
+ h.shortest = shortest_len;
+ h.common = n_ignore_words;
+ fwrite_or_die(&h, sizeof(h), 1, indxfp);
+}
+
+static void fwrite_or_die(const void *ptr, int size, int nitems, FILE *fp)
+{
+ if (fwrite(ptr, size, nitems, fp) != nitems)
+ fatal("fwrite failed: %1", strerror(errno));
+}
+
+void fatal_error_exit()
+{
+ cleanup();
+ exit(3);
+}
+
+extern "C" {
+
+void cleanup()
+{
+ if (temp_index_file)
+ unlink(temp_index_file);
+}
+
+}
diff --git a/gnu/usr.bin/groff/indxbib/signal.c b/gnu/usr.bin/groff/indxbib/signal.c
new file mode 100644
index 000000000000..7c81f9157fbf
--- /dev/null
+++ b/gnu/usr.bin/groff/indxbib/signal.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Unfortunately vendors seem to have problems writing a <signal.h>
+that is correct for C++, so we implement all signal handling in C. */
+
+#include <sys/types.h>
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef RETSIGTYPE
+#define RETSIGTYPE void
+#endif
+
+extern void cleanup();
+
+static RETSIGTYPE handle_fatal_signal(signum)
+ int signum;
+{
+ signal(signum, SIG_DFL);
+ cleanup();
+ kill(getpid(), signum);
+}
+
+void catch_fatal_signals()
+{
+#ifdef SIGHUP
+ signal(SIGHUP, handle_fatal_signal);
+#endif
+ signal(SIGINT, handle_fatal_signal);
+ signal(SIGTERM, handle_fatal_signal);
+}
+
+#ifndef HAVE_RENAME
+
+void ignore_fatal_signals()
+{
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_IGN);
+#endif
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+}
+
+#endif /* not HAVE_RENAME */
diff --git a/gnu/usr.bin/groff/libbib/Makefile b/gnu/usr.bin/groff/libbib/Makefile
new file mode 100644
index 000000000000..0690e591caf9
--- /dev/null
+++ b/gnu/usr.bin/groff/libbib/Makefile
@@ -0,0 +1,14 @@
+# Makefile for libbib
+
+LIB= bib
+SRCS= common.cc index.cc linear.cc search.cc map.c
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+
+NOMAN= noman
+NOPROFILE= noprofile
+
+install:
+
+.include "../Makefile.cfg"
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/groff/libbib/common.cc b/gnu/usr.bin/groff/libbib/common.cc
new file mode 100644
index 000000000000..25f4078b8f0f
--- /dev/null
+++ b/gnu/usr.bin/groff/libbib/common.cc
@@ -0,0 +1,38 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+unsigned hash(const char *s, int len)
+{
+#if 0
+ unsigned h = 0, g;
+ while (*s != '\0') {
+ h <<= 4;
+ h += *s++;
+ if ((g = h & 0xf0000000) != 0) {
+ h ^= g >> 24;
+ h ^= g;
+ }
+ }
+#endif
+ unsigned h = 0;
+ while (--len >= 0)
+ h = *s++ + 65587*h;
+ return h;
+}
+
diff --git a/gnu/usr.bin/groff/libbib/index.cc b/gnu/usr.bin/groff/libbib/index.cc
new file mode 100644
index 000000000000..8fe5acdae795
--- /dev/null
+++ b/gnu/usr.bin/groff/libbib/index.cc
@@ -0,0 +1,614 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "cset.h"
+#include "cmap.h"
+#include "errarg.h"
+#include "error.h"
+
+#include "refid.h"
+#include "search.h"
+#include "index.h"
+#include "defs.h"
+
+// Interface to mmap.
+extern "C" {
+ void *mapread(int fd, int len);
+ int unmap(void *, int len);
+}
+
+const int minus_one = -1;
+
+int verify_flag = 0;
+
+struct word_list;
+
+class index_search_item : public search_item {
+ search_item *out_of_date_files;
+ index_header header;
+ char *buffer;
+ void *map_addr;
+ int map_len;
+ tag *tags;
+ int *table;
+ int *lists;
+ char *pool;
+ char *key_buffer;
+ char *filename_buffer;
+ int filename_buflen;
+ char **common_words_table;
+ int common_words_table_size;
+ const char *ignore_fields;
+ time_t mtime;
+
+ const char *do_verify();
+ const int *search1(const char **pp, const char *end);
+ const int *search(const char *ptr, int length, int **temp_listp);
+ const char *munge_filename(const char *);
+ void read_common_words_file();
+ void add_out_of_date_file(int fd, const char *filename, int fid);
+public:
+ index_search_item(const char *, int);
+ ~index_search_item();
+ int load(int fd);
+ search_item_iterator *make_search_item_iterator(const char *);
+ int verify();
+ void check_files();
+ int next_filename_id() const;
+ friend class index_search_item_iterator;
+};
+
+class index_search_item_iterator : public search_item_iterator {
+ index_search_item *indx;
+ search_item_iterator *out_of_date_files_iter;
+ search_item *next_out_of_date_file;
+ const int *found_list;
+ int *temp_list;
+ char *buf;
+ int buflen;
+ linear_searcher searcher;
+ char *query;
+ int get_tag(int tagno, const linear_searcher &, const char **, int *,
+ reference_id *);
+public:
+ index_search_item_iterator(index_search_item *, const char *);
+ ~index_search_item_iterator();
+ int next(const linear_searcher &, const char **, int *, reference_id *);
+};
+
+
+index_search_item::index_search_item(const char *filename, int fid)
+: search_item(filename, fid), out_of_date_files(0), key_buffer(0),
+ filename_buffer(0), filename_buflen(0), common_words_table(0),
+ map_addr(0), map_len(0), buffer(0)
+{
+}
+
+index_search_item::~index_search_item()
+{
+ if (buffer)
+ free(buffer);
+ if (map_addr) {
+ if (unmap(map_addr, map_len) < 0)
+ error("unmap: %1", strerror(errno));
+ }
+ while (out_of_date_files) {
+ search_item *tem = out_of_date_files;
+ out_of_date_files = out_of_date_files->next;
+ delete tem;
+ }
+ a_delete filename_buffer;
+ a_delete key_buffer;
+ if (common_words_table) {
+ for (int i = 0; i < common_words_table_size; i++)
+ a_delete common_words_table[i];
+ a_delete common_words_table;
+ }
+}
+
+class file_closer {
+ int *fdp;
+public:
+ file_closer(int &fd) : fdp(&fd) { }
+ ~file_closer() { close(*fdp); }
+};
+
+int index_search_item::load(int fd)
+{
+ file_closer fd_closer(fd); // close fd on return
+ struct stat sb;
+ if (fstat(fd, &sb) < 0) {
+ error("can't fstat `%1': %2", name, strerror(errno));
+ return 0;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ error("`%1' is not a regular file", name);
+ return 0;
+ }
+ mtime = sb.st_mtime;
+ int size = int(sb.st_size);
+ char *addr;
+ map_addr = mapread(fd, size);
+ if (map_addr) {
+ addr = (char *)map_addr;
+ map_len = size;
+ }
+ else {
+ addr = buffer = (char *)malloc(size);
+ if (buffer == 0) {
+ error("can't allocate buffer for `%1'", name);
+ return 0;
+ }
+ char *ptr = buffer;
+ int bytes_to_read = size;
+ while (bytes_to_read > 0) {
+ int nread = read(fd, ptr, bytes_to_read);
+ if (nread == 0) {
+ error("unexpected EOF on `%1'", name);
+ return 0;
+ }
+ if (nread < 0) {
+ error("read error on `%1': %2", name, strerror(errno));
+ return 0;
+ }
+ bytes_to_read -= nread;
+ ptr += nread;
+ }
+ }
+ header = *(index_header *)addr;
+ if (header.magic != INDEX_MAGIC) {
+ error("`%1' is not an index file: wrong magic number", name);
+ return 0;
+ }
+ if (header.version != INDEX_VERSION) {
+ error("version number in `%1' is wrong: was %2, should be %3",
+ name, header.version, INDEX_VERSION);
+ return 0;
+ }
+ int sz = (header.tags_size * sizeof(tag)
+ + header.lists_size * sizeof(int)
+ + header.table_size * sizeof(int)
+ + header.strings_size
+ + sizeof(header));
+ if (sz != size) {
+ error("size of `%1' is wrong: was %2, should be %3",
+ name, size, sz);
+ return 0;
+ }
+ tags = (tag *)(addr + sizeof(header));
+ lists = (int *)(tags + header.tags_size);
+ table = (int *)(lists + header.lists_size);
+ pool = (char *)(table + header.table_size);
+ ignore_fields = strchr(strchr(pool, '\0') + 1, '\0') + 1;
+ key_buffer = new char[header.truncate];
+ read_common_words_file();
+ return 1;
+}
+
+const char *index_search_item::do_verify()
+{
+ if (tags == 0)
+ return "not loaded";
+ if (lists[header.lists_size - 1] >= 0)
+ return "last list element not negative";
+ int i;
+ for (i = 0; i < header.table_size; i++) {
+ int li = table[i];
+ if (li >= header.lists_size)
+ return "bad list index";
+ if (li >= 0) {
+ for (int *ptr = lists + li; *ptr >= 0; ptr++) {
+ if (*ptr >= header.tags_size)
+ return "bad tag index";
+ if (*ptr >= ptr[1] && ptr[1] >= 0)
+ return "list not ordered";
+ }
+ }
+ }
+ for (i = 0; i < header.tags_size; i++) {
+ if (tags[i].filename_index >= header.strings_size)
+ return "bad index in tags";
+ if (tags[i].length < 0)
+ return "bad length in tags";
+ if (tags[i].start < 0)
+ return "bad start in tags";
+ }
+ if (pool[header.strings_size - 1] != '\0')
+ return "last character in pool not nul";
+ return 0;
+}
+
+int index_search_item::verify()
+{
+ const char *reason = do_verify();
+ if (!reason)
+ return 1;
+ error("`%1' is bad: %2", name, reason);
+ return 0;
+}
+
+int index_search_item::next_filename_id() const
+{
+ return filename_id + header.strings_size + 1;
+}
+
+search_item_iterator *index_search_item::make_search_item_iterator(
+ const char *query)
+{
+ return new index_search_item_iterator(this, query);
+}
+
+search_item *make_index_search_item(const char *filename, int fid)
+{
+ char *index_filename = new char[strlen(filename) + sizeof(INDEX_SUFFIX)];
+ strcpy(index_filename, filename);
+ strcat(index_filename, INDEX_SUFFIX);
+ int fd = open(index_filename, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ index_search_item *item = new index_search_item(index_filename, fid);
+ a_delete index_filename;
+ if (!item->load(fd)) {
+ close(fd);
+ delete item;
+ return 0;
+ }
+ else if (verify_flag && !item->verify()) {
+ delete item;
+ return 0;
+ }
+ else {
+ item->check_files();
+ return item;
+ }
+}
+
+
+index_search_item_iterator::index_search_item_iterator(index_search_item *ind,
+ const char *q)
+: indx(ind), buf(0), buflen(0), temp_list(0), query(strsave(q)),
+ searcher(q, strlen(q), ind->ignore_fields, ind->header.truncate),
+ out_of_date_files_iter(0), next_out_of_date_file(0)
+{
+ found_list = indx->search(q, strlen(q), &temp_list);
+ if (!found_list) {
+ found_list = &minus_one;
+ warning("all keys would have been discarded in constructing index `%1'",
+ indx->name);
+ }
+}
+
+index_search_item_iterator::~index_search_item_iterator()
+{
+ a_delete temp_list;
+ a_delete buf;
+ a_delete query;
+ delete out_of_date_files_iter;
+}
+
+int index_search_item_iterator::next(const linear_searcher &,
+ const char **pp, int *lenp,
+ reference_id *ridp)
+{
+ if (found_list) {
+ for (;;) {
+ int tagno = *found_list;
+ if (tagno == -1)
+ break;
+ found_list++;
+ if (get_tag(tagno, searcher, pp, lenp, ridp))
+ return 1;
+ }
+ found_list = 0;
+ next_out_of_date_file = indx->out_of_date_files;
+ }
+ while (next_out_of_date_file) {
+ if (out_of_date_files_iter == 0)
+ out_of_date_files_iter
+ = next_out_of_date_file->make_search_item_iterator(query);
+ if (out_of_date_files_iter->next(searcher, pp, lenp, ridp))
+ return 1;
+ delete out_of_date_files_iter;
+ out_of_date_files_iter = 0;
+ next_out_of_date_file = next_out_of_date_file->next;
+ }
+ return 0;
+}
+
+int index_search_item_iterator::get_tag(int tagno,
+ const linear_searcher &searcher,
+ const char **pp, int *lenp,
+ reference_id *ridp)
+{
+ if (tagno < 0 || tagno >= indx->header.tags_size) {
+ error("bad tag number");
+ return 0;
+ }
+ tag *tp = indx->tags + tagno;
+ const char *filename = indx->munge_filename(indx->pool + tp->filename_index);
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ struct stat sb;
+ if (fstat(fd, &sb) < 0) {
+ error("can't fstat: %1", strerror(errno));
+ close(fd);
+ return 0;
+ }
+ time_t mtime = sb.st_mtime;
+ if (mtime > indx->mtime) {
+ indx->add_out_of_date_file(fd, filename,
+ indx->filename_id + tp->filename_index);
+ return 0;
+ }
+ int res = 0;
+ FILE *fp = fdopen(fd, "r");
+ if (!fp) {
+ error("fdopen failed");
+ close(fd);
+ return 0;
+ }
+ if (tp->start != 0 && fseek(fp, long(tp->start), 0) < 0)
+ error("can't seek on `%1': %2", filename, strerror(errno));
+ else {
+ int length = tp->length;
+ int err = 0;
+ if (length == 0) {
+ struct stat sb;
+ if (fstat(fileno(fp), &sb) < 0) {
+ error("can't stat `%1': %2", filename, strerror(errno));
+ err = 1;
+ }
+ else if ((sb.st_mode & S_IFMT) != S_IFREG) {
+ error("`%1' is not a regular file", filename);
+ err = 1;
+ }
+ else
+ length = int(sb.st_size);
+ }
+ if (!err) {
+ if (length + 2 > buflen) {
+ a_delete buf;
+ buflen = length + 2;
+ buf = new char[buflen];
+ }
+ if (fread(buf + 1, 1, length, fp) != length)
+ error("fread on `%1' failed: %2", filename, strerror(errno));
+ else {
+ buf[0] = '\n';
+ buf[length + 1] = '\n';
+ res = searcher.search(buf + 1, buf + 2 + length, pp, lenp);
+ if (res && ridp)
+ *ridp = reference_id(indx->filename_id + tp->filename_index,
+ tp->start);
+ }
+ }
+ }
+ fclose(fp);
+ return res;
+}
+
+const char *index_search_item::munge_filename(const char *filename)
+{
+ if (filename[0] == '/')
+ return filename;
+ const char *cwd = pool;
+ int need_slash = (cwd[0] != 0 && strchr(cwd, '\0')[-1] != '/');
+ int len = strlen(cwd) + strlen(filename) + need_slash + 1;
+ if (len > filename_buflen) {
+ a_delete filename_buffer;
+ filename_buflen = len;
+ filename_buffer = new char[len];
+ }
+ strcpy(filename_buffer, cwd);
+ if (need_slash)
+ strcat(filename_buffer, "/");
+ strcat(filename_buffer, filename);
+ return filename_buffer;
+}
+
+const int *index_search_item::search1(const char **pp, const char *end)
+{
+ while (*pp < end && !csalnum(**pp))
+ *pp += 1;
+ if (*pp >= end)
+ return 0;
+ const char *start = *pp;
+ while (*pp < end && csalnum(**pp))
+ *pp += 1;
+ int len = *pp - start;
+ if (len < header.shortest)
+ return 0;
+ if (len > header.truncate)
+ len = header.truncate;
+ int is_number = 1;
+ for (int i = 0; i < len; i++)
+ if (csdigit(start[i]))
+ key_buffer[i] = start[i];
+ else {
+ key_buffer[i] = cmlower(start[i]);
+ is_number = 0;
+ }
+ if (is_number && !(len == 4 && start[0] == '1' && start[1] == '9'))
+ return 0;
+ unsigned hc = hash(key_buffer, len);
+ if (common_words_table) {
+ for (int h = hc % common_words_table_size;
+ common_words_table[h];
+ --h) {
+ if (strlen(common_words_table[h]) == len
+ && memcmp(common_words_table[h], key_buffer, len) == 0)
+ return 0;
+ if (h == 0)
+ h = common_words_table_size;
+ }
+ }
+ int li = table[int(hc % header.table_size)];
+ return li < 0 ? &minus_one : lists + li;
+}
+
+static void merge(int *result, const int *s1, const int *s2)
+{
+ for (; *s1 >= 0; s1++) {
+ while (*s2 >= 0 && *s2 < *s1)
+ s2++;
+ if (*s2 == *s1)
+ *result++ = *s2;
+ }
+ *result++ = -1;
+}
+
+const int *index_search_item::search(const char *ptr, int length,
+ int **temp_listp)
+{
+ const char *end = ptr + length;
+ if (*temp_listp) {
+ a_delete *temp_listp;
+ *temp_listp = 0;
+ }
+ const int *first_list = 0;
+ while (ptr < end && (first_list = search1(&ptr, end)) == 0)
+ ;
+ if (!first_list)
+ return 0;
+ if (*first_list < 0)
+ return first_list;
+ const int *second_list = 0;
+ while (ptr < end && (second_list = search1(&ptr, end)) == 0)
+ ;
+ if (!second_list)
+ return first_list;
+ if (*second_list < 0)
+ return second_list;
+ for (const int *p = first_list; *p >= 0; p++)
+ ;
+ int len = p - first_list;
+ for (p = second_list; *p >= 0; p++)
+ ;
+ if (p - second_list < len)
+ len = p - second_list;
+ int *matches = new int[len + 1];
+ merge(matches, first_list, second_list);
+ while (ptr < end) {
+ const int *list = search1(&ptr, end);
+ if (list != 0) {
+ if (*list < 0) {
+ a_delete matches;
+ return list;
+ }
+ merge(matches, matches, list);
+ if (*matches < 0) {
+ a_delete matches;
+ return &minus_one;
+ }
+ }
+ }
+ *temp_listp = matches;
+ return matches;
+}
+
+void index_search_item::read_common_words_file()
+{
+ if (header.common <= 0)
+ return;
+ const char *common_words_file = munge_filename(strchr(pool, '\0') + 1);
+ errno = 0;
+ FILE *fp = fopen(common_words_file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", common_words_file, strerror(errno));
+ return;
+ }
+ common_words_table_size = 2*header.common + 1;
+ while (!is_prime(common_words_table_size))
+ common_words_table_size++;
+ common_words_table = new char *[common_words_table_size];
+ for (int i = 0; i < common_words_table_size; i++)
+ common_words_table[i] = 0;
+ int count = 0;
+ int key_len = 0;
+ for (;;) {
+ int c = getc(fp);
+ while (c != EOF && !csalnum(c))
+ c = getc(fp);
+ if (c == EOF)
+ break;
+ do {
+ if (key_len < header.truncate)
+ key_buffer[key_len++] = cmlower(c);
+ c = getc(fp);
+ } while (c != EOF && csalnum(c));
+ if (key_len >= header.shortest) {
+ int h = hash(key_buffer, key_len) % common_words_table_size;
+ while (common_words_table[h]) {
+ if (h == 0)
+ h = common_words_table_size;
+ --h;
+ }
+ common_words_table[h] = new char[key_len + 1];
+ memcpy(common_words_table[h], key_buffer, key_len);
+ common_words_table[h][key_len] = '\0';
+ }
+ if (++count >= header.common)
+ break;
+ key_len = 0;
+ if (c == EOF)
+ break;
+ }
+ fclose(fp);
+}
+
+void index_search_item::add_out_of_date_file(int fd, const char *filename,
+ int fid)
+{
+ for (search_item **pp = &out_of_date_files; *pp; pp = &(*pp)->next)
+ if ((*pp)->is_named(filename))
+ return;
+ *pp = make_linear_search_item(fd, filename, fid);
+ warning("`%1' modified since `%2' created", filename, name);
+}
+
+void index_search_item::check_files()
+{
+ const char *pool_end = pool + header.strings_size;
+ for (const char *ptr = strchr(ignore_fields, '\0') + 1;
+ ptr < pool_end;
+ ptr = strchr(ptr, '\0') + 1) {
+ const char *path = munge_filename(ptr);
+ struct stat sb;
+ if (stat(path, &sb) < 0)
+ error("can't stat `%1': %2", path, strerror(errno));
+ else if (sb.st_mtime > mtime) {
+ int fd = open(path, O_RDONLY);
+ if (fd < 0)
+ error("can't open `%1': %2", path, strerror(errno));
+ else
+ add_out_of_date_file(fd, path, filename_id + (ptr - pool));
+ }
+ }
+}
diff --git a/gnu/usr.bin/groff/libbib/linear.cc b/gnu/usr.bin/groff/libbib/linear.cc
new file mode 100644
index 000000000000..0798008210e4
--- /dev/null
+++ b/gnu/usr.bin/groff/libbib/linear.cc
@@ -0,0 +1,484 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "cset.h"
+#include "cmap.h"
+
+#include "refid.h"
+#include "search.h"
+
+class file_buffer {
+ char *buffer;
+ char *bufend;
+public:
+ file_buffer();
+ ~file_buffer();
+ int load(int fd, const char *filename);
+ const char *get_start() const;
+ const char *get_end() const;
+};
+
+typedef unsigned char uchar;
+
+static uchar map[256];
+static uchar inv_map[256][3];
+
+struct map_init {
+ map_init();
+};
+
+static map_init the_map_init;
+
+map_init::map_init()
+{
+ for (int i = 0; i < 256; i++)
+ map[i] = csalnum(i) ? cmlower(i) : '\0';
+ for (i = 0; i < 256; i++) {
+ if (cslower(i)) {
+ inv_map[i][0] = i;
+ inv_map[i][1] = cmupper(i);
+ inv_map[i][2] = '\0';
+ }
+ else if (csdigit(i)) {
+ inv_map[i][0] = i;
+ inv_map[i][1] = 0;
+ }
+ else
+ inv_map[i][0] = '\0';
+ }
+}
+
+
+class bmpattern {
+ char *pat;
+ int len;
+ int delta[256];
+public:
+ bmpattern(const char *pattern, int pattern_length);
+ ~bmpattern();
+ const char *search(const char *p, const char *end) const;
+ int length() const;
+};
+
+bmpattern::bmpattern(const char *pattern, int pattern_length)
+: len(pattern_length)
+{
+ pat = new char[len];
+ int i;
+ for (i = 0; i < len; i++)
+ pat[i] = map[uchar(pattern[i])];
+ for (i = 0; i < 256; i++)
+ delta[i] = len;
+ for (i = 0; i < len; i++)
+ for (const unsigned char *inv = inv_map[uchar(pat[i])]; *inv; inv++)
+ delta[*inv] = len - i - 1;
+}
+
+const char *bmpattern::search(const char *buf, const char *end) const
+{
+ int buflen = end - buf;
+ if (len > buflen)
+ return 0;
+ const char *strend;
+ if (buflen > len*4)
+ strend = end - len*4;
+ else
+ strend = buf;
+ const char *k = buf + len - 1;
+ const int *del = delta;
+ const char *pattern = pat;
+ for (;;) {
+ while (k < strend) {
+ int t = del[uchar(*k)];
+ if (!t)
+ break;
+ k += t;
+ k += del[uchar(*k)];
+ k += del[uchar(*k)];
+ }
+ while (k < end && del[uchar(*k)] != 0)
+ k++;
+ if (k == end)
+ break;
+ int j = len - 1;
+ const char *s = k;
+ for (;;) {
+ if (j == 0)
+ return s;
+ if (map[uchar(*--s)] != pattern[--j])
+ break;
+ }
+ k++;
+ }
+ return 0;
+}
+
+bmpattern::~bmpattern()
+{
+ a_delete pat;
+}
+
+inline int bmpattern::length() const
+{
+ return len;
+}
+
+
+static const char *find_end(const char *bufend, const char *p);
+
+const char *linear_searcher::search_and_check(const bmpattern *key,
+ const char *buf, const char *bufend, const char **start) const
+{
+ assert(buf[-1] == '\n');
+ assert(bufend[-1] == '\n');
+ const char *ptr = buf;
+ for (;;) {
+ const char *found = key->search(ptr, bufend);
+ if (!found)
+ break;
+ if (check_match(buf, bufend, found, key->length(), &ptr, start))
+ return found;
+ }
+ return 0;
+}
+
+static const char *skip_field(const char *end, const char *p)
+{
+ for (;;)
+ if (*p++ == '\n') {
+ if (p == end || *p == '%')
+ break;
+ for (const char *q = p; *q == ' ' || *q == '\t'; q++)
+ ;
+ if (*q == '\n')
+ break;
+ p = q + 1;
+ }
+ return p;
+}
+
+static const char *find_end(const char *bufend, const char *p)
+{
+ for (;;)
+ if (*p++ == '\n') {
+ if (p == bufend)
+ break;
+ for (const char *q = p; *q == ' ' || *q == '\t'; q++)
+ ;
+ if (*q == '\n')
+ break;
+ p = q + 1;
+ }
+ return p;
+}
+
+
+int linear_searcher::check_match(const char *buf, const char *bufend,
+ const char *match, int matchlen,
+ const char **cont, const char **start) const
+{
+ *cont = match + 1;
+ // The user is required to supply only the first truncate_len characters
+ // of the key. If truncate_len <= 0, he must supply all the key.
+ if ((truncate_len <= 0 || matchlen < truncate_len)
+ && map[uchar(match[matchlen])] != '\0')
+ return 0;
+
+ // The character before the match must not be an alphanumeric
+ // character (unless the alphanumeric character follows one or two
+ // percent characters at the beginning of the line), nor must it be
+ // a percent character at the beginning of a line, nor a percent
+ // character following a percent character at the beginning of a
+ // line.
+
+ switch (match - buf) {
+ case 0:
+ break;
+ case 1:
+ if (match[-1] == '%' || map[uchar(match[-1])] != '\0')
+ return 0;
+ break;
+ case 2:
+ if (map[uchar(match[-1])] != '\0' && match[-2] != '%')
+ return 0;
+ if (match[-1] == '%'
+ && (match[-2] == '\n' || match[-2] == '%'))
+ return 0;
+ break;
+ default:
+ if (map[uchar(match[-1])] != '\0'
+ && !(match[-2] == '%'
+ && (match[-3] == '\n'
+ || (match[-3] == '%' && match[-4] == '\n'))))
+ return 0;
+ if (match[-1] == '%'
+ && (match[-2] == '\n'
+ || (match[-2] == '%' && match[-3] == '\n')))
+ return 0;
+ }
+
+ const char *p = match;
+ int had_percent = 0;
+ for (;;) {
+ if (*p == '\n') {
+ if (!had_percent && p[1] == '%') {
+ if (p[2] != '\0' && strchr(ignore_fields, p[2]) != 0) {
+ *cont = skip_field(bufend, match + matchlen);
+ return 0;
+ }
+ if (!start)
+ break;
+ had_percent = 1;
+ }
+ if (p <= buf) {
+ if (start)
+ *start = p + 1;
+ return 1;
+ }
+ for (const char *q = p - 1; *q == ' ' || *q == '\t'; q--)
+ ;
+ if (*q == '\n') {
+ if (start)
+ *start = p + 1;
+ break;
+ }
+ p = q;
+ }
+ p--;
+ }
+ return 1;
+}
+
+file_buffer::file_buffer()
+: buffer(0), bufend(0)
+{
+}
+
+file_buffer::~file_buffer()
+{
+ a_delete buffer;
+}
+
+const char *file_buffer::get_start() const
+{
+ return buffer ? buffer + 4 : 0;
+}
+
+const char *file_buffer::get_end() const
+{
+ return bufend;
+}
+
+int file_buffer::load(int fd, const char *filename)
+{
+ struct stat sb;
+ if (fstat(fd, &sb) < 0)
+ error("can't fstat `%1': %2", filename, strerror(errno));
+ else if ((sb.st_mode & S_IFMT) != S_IFREG)
+ error("`%1' is not a regular file", filename);
+ else {
+ // We need one character extra at the beginning for an additional newline
+ // used as a sentinel. We get 4 instead so that the read buffer will be
+ // word-aligned. This seems to make the read slightly faster. We also
+ // need one character at the end also for an addional newline used as a
+ // sentinel.
+ int size = int(sb.st_size);
+ buffer = new char[size + 4 + 1];
+ int nread = read(fd, buffer + 4, size);
+ if (nread < 0)
+ error("error reading `%1': %2", filename, strerror(errno));
+ else if (nread != size)
+ error("size of `%1' decreased", filename);
+ else {
+ char c;
+ nread = read(fd, &c, 1);
+ if (nread != 0)
+ error("size of `%1' increased", filename);
+ else if (memchr(buffer + 4, '\0', size < 1024 ? size : 1024) != 0)
+ error("database `%1' is a binary file", filename);
+ else {
+ close(fd);
+ buffer[3] = '\n';
+ bufend = buffer + 4 + size;
+ if (bufend[-1] != '\n')
+ *bufend++ = '\n';
+ return 1;
+ }
+ }
+ a_delete buffer;
+ buffer = 0;
+ }
+ close(fd);
+ return 0;
+}
+
+linear_searcher::linear_searcher(const char *query, int query_len,
+ const char *ign, int trunc)
+: keys(0), nkeys(0), truncate_len(trunc), ignore_fields(ign)
+{
+ const char *query_end = query + query_len;
+ int nk = 0;
+ const char *p;
+ for (p = query; p < query_end; p++)
+ if (map[uchar(*p)] != '\0'
+ && (p[1] == '\0' || map[uchar(p[1])] == '\0'))
+ nk++;
+ if (nk == 0)
+ return;
+ keys = new bmpattern*[nk];
+ p = query;
+ for (;;) {
+ while (p < query_end && map[uchar(*p)] == '\0')
+ p++;
+ if (p == query_end)
+ break;
+ const char *start = p;
+ while (p < query_end && map[uchar(*p)] != '\0')
+ p++;
+ keys[nkeys++] = new bmpattern(start, p - start);
+ }
+ assert(nkeys <= nk);
+ if (nkeys == 0) {
+ a_delete keys;
+ keys = 0;
+ }
+}
+
+linear_searcher::~linear_searcher()
+{
+ for (int i = 0; i < nkeys; i++)
+ delete keys[i];
+ a_delete keys;
+}
+
+int linear_searcher::search(const char *buffer, const char *bufend,
+ const char **startp, int *lengthp) const
+{
+ assert(bufend - buffer > 0);
+ assert(buffer[-1] == '\n');
+ assert(bufend[-1] == '\n');
+ if (nkeys == 0)
+ return 0;
+ for (;;) {
+ const char *refstart;
+ const char *found = search_and_check(keys[0], buffer, bufend, &refstart);
+ if (!found)
+ break;
+ const char *refend = find_end(bufend, found + keys[0]->length());
+ for (int i = 1; i < nkeys; i++)
+ if (!search_and_check(keys[i], refstart, refend))
+ break;
+ if (i >= nkeys) {
+ *startp = refstart;
+ *lengthp = refend - refstart;
+ return 1;
+ }
+ buffer = refend;
+ }
+ return 0;
+}
+
+class linear_search_item : public search_item {
+ file_buffer fbuf;
+public:
+ linear_search_item(const char *filename, int fid);
+ ~linear_search_item();
+ int load(int fd);
+ search_item_iterator *make_search_item_iterator(const char *);
+ friend class linear_search_item_iterator;
+};
+
+class linear_search_item_iterator : public search_item_iterator {
+ linear_search_item *lsi;
+ int pos;
+public:
+ linear_search_item_iterator(linear_search_item *, const char *query);
+ ~linear_search_item_iterator();
+ int next(const linear_searcher &, const char **ptr, int *lenp,
+ reference_id *ridp);
+};
+
+search_item *make_linear_search_item(int fd, const char *filename, int fid)
+{
+ linear_search_item *item = new linear_search_item(filename, fid);
+ if (!item->load(fd)) {
+ delete item;
+ return 0;
+ }
+ else
+ return item;
+}
+
+linear_search_item::linear_search_item(const char *filename, int fid)
+: search_item(filename, fid)
+{
+}
+
+linear_search_item::~linear_search_item()
+{
+}
+
+int linear_search_item::load(int fd)
+{
+ return fbuf.load(fd, name);
+}
+
+search_item_iterator *linear_search_item::make_search_item_iterator(
+ const char *query)
+{
+ return new linear_search_item_iterator(this, query);
+}
+
+linear_search_item_iterator::linear_search_item_iterator(
+ linear_search_item *p, const char *)
+: lsi(p), pos(0)
+{
+}
+
+linear_search_item_iterator::~linear_search_item_iterator()
+{
+}
+
+int linear_search_item_iterator::next(const linear_searcher &searcher,
+ const char **startp, int *lengthp,
+ reference_id *ridp)
+{
+ const char *bufstart = lsi->fbuf.get_start();
+ const char *bufend = lsi->fbuf.get_end();
+ const char *ptr = bufstart + pos;
+ if (ptr < bufend && searcher.search(ptr, bufend, startp, lengthp)) {
+ pos = *startp + *lengthp - bufstart;
+ if (ridp)
+ *ridp = reference_id(lsi->filename_id, *startp - bufstart);
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/gnu/usr.bin/groff/libbib/map.c b/gnu/usr.bin/groff/libbib/map.c
new file mode 100644
index 000000000000..9d0f13f89323
--- /dev/null
+++ b/gnu/usr.bin/groff/libbib/map.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_MMAP
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+/* The Net-2 man pages says that a MAP_FILE flag is required. */
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+char *mapread(fd, nbytes)
+ int fd;
+ int nbytes;
+{
+ char *p = (char *)mmap((caddr_t)0, (size_t)nbytes, PROT_READ,
+ MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
+ if (p == (char *)-1)
+ return 0;
+ /* mmap() shouldn't return 0 since MAP_FIXED wasn't specified. */
+ if (p == 0)
+ abort();
+ return p;
+}
+
+int unmap(p, len)
+ char *p;
+ int len;
+{
+ return munmap((caddr_t)p, len);
+}
+
+#else /* not HAVE_MMAP */
+
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+char *mapread(fd, nbytes)
+ int fd;
+ int nbytes;
+{
+ errno = ENODEV;
+ return 0;
+}
+
+int unmap(p, len)
+ char *p;
+ int len;
+{
+ errno = EINVAL;
+ return -1;
+}
+
+#endif /* not HAVE_MMAP */
diff --git a/gnu/usr.bin/groff/libbib/search.cc b/gnu/usr.bin/groff/libbib/search.cc
new file mode 100644
index 000000000000..ffdd8721232e
--- /dev/null
+++ b/gnu/usr.bin/groff/libbib/search.cc
@@ -0,0 +1,130 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+
+#include "refid.h"
+#include "search.h"
+
+int linear_truncate_len = 6;
+const char *linear_ignore_fields = "XYZ";
+
+search_list::search_list()
+: list(0), niterators(0), next_fid(1)
+{
+}
+
+search_list::~search_list()
+{
+ assert(niterators == 0);
+ while (list) {
+ search_item *tem = list->next;
+ delete list;
+ list = tem;
+ }
+}
+
+void search_list::add_file(const char *filename, int silent)
+{
+ search_item *p = make_index_search_item(filename, next_fid);
+ if (!p) {
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ if (!silent)
+ error("can't open `%1': %2", filename, strerror(errno));
+ }
+ else
+ p = make_linear_search_item(fd, filename, next_fid);
+ }
+ if (p) {
+ for (search_item **pp = &list; *pp; pp = &(*pp)->next)
+ ;
+ *pp = p;
+ next_fid = p->next_filename_id();
+ }
+}
+
+int search_list::nfiles() const
+{
+ int n = 0;
+ for (search_item *ptr = list; ptr; ptr = ptr->next)
+ n++;
+ return n;
+}
+
+search_list_iterator::search_list_iterator(search_list *p, const char *q)
+: list(p), ptr(p->list), iter(0), query(strsave(q)),
+ searcher(q, strlen(q), linear_ignore_fields, linear_truncate_len)
+{
+ list->niterators += 1;
+}
+
+search_list_iterator::~search_list_iterator()
+{
+ list->niterators -= 1;
+ a_delete query;
+ delete iter;
+}
+
+int search_list_iterator::next(const char **pp, int *lenp, reference_id *ridp)
+{
+ while (ptr) {
+ if (iter == 0)
+ iter = ptr->make_search_item_iterator(query);
+ if (iter->next(searcher, pp, lenp, ridp))
+ return 1;
+ delete iter;
+ iter = 0;
+ ptr = ptr->next;
+ }
+ return 0;
+}
+
+search_item::search_item(const char *nm, int fid)
+: next(0), name(strsave(nm)), filename_id(fid)
+{
+}
+
+search_item::~search_item()
+{
+ a_delete name;
+}
+
+int search_item::is_named(const char *nm) const
+{
+ return strcmp(name, nm) == 0;
+}
+
+int search_item::next_filename_id() const
+{
+ return filename_id + 1;
+}
+
+search_item_iterator::~search_item_iterator()
+{
+}
diff --git a/gnu/usr.bin/groff/libdriver/Makefile b/gnu/usr.bin/groff/libdriver/Makefile
new file mode 100644
index 000000000000..39f8189fe373
--- /dev/null
+++ b/gnu/usr.bin/groff/libdriver/Makefile
@@ -0,0 +1,14 @@
+# Makefile for libdriver
+
+LIB= driver
+SRCS= input.cc printer.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+
+NOMAN= noman
+NOPROFILE= noprofile
+
+install:
+
+.include "../Makefile.cfg"
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/groff/libdriver/input.cc b/gnu/usr.bin/groff/libdriver/input.cc
new file mode 100644
index 000000000000..d046e864e14f
--- /dev/null
+++ b/gnu/usr.bin/groff/libdriver/input.cc
@@ -0,0 +1,473 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "driver.h"
+#include "device.h"
+
+const char *current_filename;
+int current_lineno;
+const char *device = 0;
+FILE *current_file;
+
+int get_integer(); // don't read the newline
+int possibly_get_integer(int *);
+char *get_string(int is_long = 0);
+void skip_line();
+
+struct environment_list {
+ environment env;
+ environment_list *next;
+
+ environment_list(const environment &, environment_list *);
+};
+
+environment_list::environment_list(const environment &e, environment_list *p)
+: env(e), next(p)
+{
+}
+
+inline int get_char()
+{
+ return getc(current_file);
+}
+
+void do_file(const char *filename)
+{
+ int npages = 0;
+ if (filename[0] == '-' && filename[1] == '\0') {
+ current_filename = "<standard input>";
+ current_file = stdin;
+ }
+ else {
+ errno = 0;
+ current_file = fopen(filename, "r");
+ if (current_file == 0) {
+ error("can't open `%1'", filename);
+ return;
+ }
+ current_filename = filename;
+ }
+ environment env;
+ env.vpos = -1;
+ env.hpos = -1;
+ env.fontno = -1;
+ env.height = 0;
+ env.slant = 0;
+ environment_list *env_list = 0;
+ current_lineno = 1;
+ int command;
+ char *s;
+ command = get_char();
+ if (command == EOF)
+ return;
+ if (command != 'x')
+ fatal("the first command must be `x T'");
+ s = get_string();
+ if (s[0] != 'T')
+ fatal("the first command must be `x T'");
+ char *dev = get_string();
+ if (pr == 0) {
+ device = strsave(dev);
+ if (!font::load_desc())
+ fatal("sorry, I can't continue");
+ }
+ else {
+ if (device == 0 || strcmp(device, dev) != 0)
+ fatal("all files must use the same device");
+ }
+ skip_line();
+ env.size = 10*font::sizescale;
+ command = get_char();
+ if (command != 'x')
+ fatal("the second command must be `x res'");
+ s = get_string();
+ if (s[0] != 'r')
+ fatal("the second command must be `x res'");
+ int n = get_integer();
+ if (n != font::res)
+ fatal("resolution does not match");
+ n = get_integer();
+ if (n != font::hor)
+ fatal("horizontal resolution does not match");
+ n = get_integer();
+ if (n != font::vert)
+ fatal("vertical resolution does not match");
+ skip_line();
+ command = get_char();
+ if (command != 'x')
+ fatal("the third command must be `x init'");
+ s = get_string();
+ if (s[0] != 'i')
+ fatal("the third command must be `x init'");
+ skip_line();
+ if (pr == 0)
+ pr = make_printer();
+ while ((command = get_char()) != EOF) {
+ switch (command) {
+ case 's':
+ env.size = get_integer();
+ if (env.height == env.size)
+ env.height = 0;
+ break;
+ case 'f':
+ env.fontno = get_integer();
+ break;
+ case 'C':
+ {
+ if (npages == 0)
+ fatal("`C' command illegal before first `p' command");
+ char *s = get_string();
+ pr->set_special_char(s, &env);
+ }
+ break;
+ case 'N':
+ {
+ if (npages == 0)
+ fatal("`N' command illegal before first `p' command");
+ pr->set_numbered_char(get_integer(), &env);
+ }
+ break;
+ case 'H':
+ env.hpos = get_integer();
+ break;
+ case 'h':
+ env.hpos += get_integer();
+ break;
+ case 'V':
+ env.vpos = get_integer();
+ break;
+ case 'v':
+ env.vpos += get_integer();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int c = get_char();
+ if (!isascii(c) || !isdigit(c))
+ fatal("digit expected");
+ env.hpos += (command - '0')*10 + (c - '0');
+ }
+ // fall through
+ case 'c':
+ {
+ if (npages == 0)
+ fatal("`c' command illegal before first `p' command");
+ int c = get_char();
+ if (c == EOF)
+ fatal("missing argument to `c' command");
+ pr->set_ascii_char(c, &env);
+ }
+ break;
+ case 'n':
+ if (npages == 0)
+ fatal("`n' command illegal before first `p' command");
+ pr->end_of_line();
+ (void)get_integer();
+ (void)get_integer();
+ break;
+ case 'w':
+ case ' ':
+ break;
+ case '\n':
+ current_lineno++;
+ break;
+ case 'p':
+ if (npages)
+ pr->end_page(env.vpos);
+ npages++;
+ pr->begin_page(get_integer());
+ env.vpos = 0;
+ break;
+ case '{':
+ env_list = new environment_list(env, env_list);
+ break;
+ case '}':
+ if (!env_list) {
+ fatal("can't pop");
+ }
+ else {
+ env = env_list->env;
+ environment_list *tem = env_list;
+ env_list = env_list->next;
+ delete tem;
+ }
+ break;
+ case 'u':
+ {
+ if (npages == 0)
+ fatal("`u' command illegal before first `p' command");
+ int kern = get_integer();
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ while (c != EOF) {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ int w;
+ pr->set_ascii_char(c, &env, &w);
+ env.hpos += w + kern;
+ c = get_char();
+ if (c == ' ')
+ break;
+ }
+ }
+ break;
+ case 't':
+ {
+ if (npages == 0)
+ fatal("`t' command illegal before first `p' command");
+ int c;
+ while ((c = get_char()) != EOF && c != ' ') {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ int w;
+ pr->set_ascii_char(c, &env, &w);
+ env.hpos += w;
+ }
+ }
+ break;
+ case '#':
+ skip_line();
+ break;
+ case 'D':
+ {
+ if (npages == 0)
+ fatal("`D' command illegal before first `p' command");
+ int c;
+ while ((c = get_char()) == ' ')
+ ;
+ int n;
+ int *p = 0;
+ int szp = 0;
+ for (int np = 0; possibly_get_integer(&n); np++) {
+ if (np >= szp) {
+ if (szp == 0) {
+ szp = 16;
+ p = new int[szp];
+ }
+ else {
+ int *oldp = p;
+ p = new int[szp*2];
+ memcpy(p, oldp, szp*sizeof(int));
+ szp *= 2;
+ a_delete oldp;
+ }
+ }
+ p[np] = n;
+ }
+ pr->draw(c, p, np, &env);
+ if (c == 'e') {
+ if (np > 0)
+ env.hpos += p[0];
+ }
+ else {
+ for (int i = 0; i < np/2; i++) {
+ env.hpos += p[i*2];
+ env.vpos += p[i*2 + 1];
+ }
+ // there might be an odd number of characters
+ if (i*2 < np)
+ env.hpos += p[i*2];
+ }
+ a_delete p;
+ skip_line();
+ }
+ break;
+ case 'x':
+ {
+ char *s = get_string();
+ int suppress_skip = 0;
+ switch (s[0]) {
+ case 'i':
+ error("duplicate `x init' command");
+ break;
+ case 'T':
+ error("duplicate `x T' command");
+ break;
+ case 'r':
+ error("duplicate `x res' command");
+ break;
+ case 'p':
+ break;
+ case 's':
+ break;
+ case 't':
+ break;
+ case 'f':
+ {
+ int n = get_integer();
+ char *name = get_string();
+ pr->load_font(n, name);
+ }
+ break;
+ case 'H':
+ env.height = get_integer();
+ if (env.height == env.size)
+ env.height = 0;
+ break;
+ case 'S':
+ env.slant = get_integer();
+ break;
+ case 'X':
+ if (npages == 0)
+ fatal("`x X' command illegal before first `p' command");
+ pr->special(get_string(1), &env);
+ suppress_skip = 1;
+ break;
+ default:
+ error("unrecognised x command `%1'", s);
+ }
+ if (!suppress_skip)
+ skip_line();
+ }
+ break;
+ default:
+ error("unrecognised command code %1", int(command));
+ skip_line();
+ break;
+ }
+ }
+ if (npages)
+ pr->end_page(env.vpos);
+}
+
+int get_integer()
+{
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ int neg = 0;
+ if (c == '-') {
+ neg = 1;
+ c = get_char();
+ }
+ if (!isascii(c) || !isdigit(c))
+ fatal("integer expected");
+ int total = 0;
+ do {
+ total = total*10;
+ if (neg)
+ total -= c - '0';
+ else
+ total += c - '0';
+ c = get_char();
+ } while (isascii(c) && isdigit(c));
+ if (c != EOF)
+ ungetc(c, current_file);
+ return total;
+}
+
+int possibly_get_integer(int *res)
+{
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ int neg = 0;
+ if (c == '-') {
+ neg = 1;
+ c = get_char();
+ }
+ if (!isascii(c) || !isdigit(c)) {
+ if (c != EOF)
+ ungetc(c, current_file);
+ return 0;
+ }
+ int total = 0;
+ do {
+ total = total*10;
+ if (neg)
+ total -= c - '0';
+ else
+ total += c - '0';
+ c = get_char();
+ } while (isascii(c) && isdigit(c));
+ if (c != EOF)
+ ungetc(c, current_file);
+ *res = total;
+ return 1;
+}
+
+
+char *get_string(int is_long)
+{
+ static char *buf;
+ static int buf_size;
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ for (int i = 0;; i++) {
+ if (i >= buf_size) {
+ if (buf_size == 0) {
+ buf_size = 16;
+ buf = new char[buf_size];
+ }
+ else {
+ char *old_buf = buf;
+ int old_size = buf_size;
+ buf_size *= 2;
+ buf = new char[buf_size];
+ memcpy(buf, old_buf, old_size);
+ a_delete old_buf;
+ }
+ }
+ if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
+ buf[i] = '\0';
+ break;
+ }
+ if (is_long && c == '\n') {
+ current_lineno++;
+ c = get_char();
+ if (c == '+')
+ c = '\n';
+ else {
+ buf[i] = '\0';
+ break;
+ }
+ }
+ buf[i] = c;
+ c = get_char();
+ }
+ if (c != EOF)
+ ungetc(c, current_file);
+ return buf;
+}
+
+void skip_line()
+{
+ int c;
+ while ((c = get_char()) != EOF)
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+}
+
diff --git a/gnu/usr.bin/groff/libdriver/printer.cc b/gnu/usr.bin/groff/libdriver/printer.cc
new file mode 100644
index 000000000000..f7e0b5fc43ea
--- /dev/null
+++ b/gnu/usr.bin/groff/libdriver/printer.cc
@@ -0,0 +1,240 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "driver.h"
+
+printer *pr = 0;
+
+font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
+: p(f), next(fp)
+{
+}
+
+printer::printer()
+: font_table(0), nfonts(0), font_list(0)
+{
+}
+
+printer::~printer()
+{
+ a_delete font_table;
+ while (font_list) {
+ font_pointer_list *tem = font_list;
+ font_list = font_list->next;
+ delete tem->p;
+ delete tem;
+ }
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+}
+
+void printer::load_font(int n, const char *nm)
+{
+ assert(n >= 0);
+ if (n >= nfonts) {
+ if (nfonts == 0) {
+ nfonts = 10;
+ if (nfonts <= n)
+ nfonts = n + 1;
+ font_table = new font *[nfonts];
+ for (int i = 0; i < nfonts; i++)
+ font_table[i] = 0;
+ }
+ else {
+ font **old_font_table = font_table;
+ int old_nfonts = nfonts;
+ nfonts *= 2;
+ if (n >= nfonts)
+ nfonts = n + 1;
+ font_table = new font *[nfonts];
+ for (int i = 0; i < old_nfonts; i++)
+ font_table[i] = old_font_table[i];
+ for (i = old_nfonts; i < nfonts; i++)
+ font_table[i] = 0;
+ a_delete old_font_table;
+ }
+ }
+ font *f = find_font(nm);
+ font_table[n] = f;
+}
+
+font *printer::find_font(const char *nm)
+{
+ for (font_pointer_list *p = font_list; p; p = p->next)
+ if (strcmp(p->p->get_name(), nm) == 0)
+ return p->p;
+ font *f = make_font(nm);
+ if (!f)
+ fatal("sorry, I can't continue");
+ font_list = new font_pointer_list(f, font_list);
+ return f;
+}
+
+font *printer::make_font(const char *nm)
+{
+ return font::load_font(nm);
+}
+
+void printer::end_of_line()
+{
+}
+
+void printer::special(char *, const environment *)
+{
+}
+
+void printer::draw(int, int *, int, const environment *)
+{
+}
+
+void printer::set_ascii_char(unsigned char c, const environment *env,
+ int *widthp)
+{
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ set_special_char(buf, env, widthp);
+}
+
+void printer::set_special_char(const char *nm, const environment *env,
+ int *widthp)
+{
+ int i = font::name_to_index(nm);
+ int fn = env->fontno;
+ if (fn < 0 || fn >= nfonts) {
+ error("bad font position `%1'", fn);
+ return;
+ }
+ font *f = font_table[fn];
+ if (f == 0) {
+ error("no font mounted at `%1'", fn);
+ return;
+ }
+ if (!f->contains(i)) {
+ if (nm[0] != '\0' && nm[1] == '\0')
+ error("font `%1' does not contain ascii character `%2'",
+ f->get_name(),
+ nm[0]);
+ else
+ error("font `%1' does not contain special character `%2'",
+ f->get_name(),
+ nm);
+ return;
+ }
+ int w = f->get_width(i, env->size);
+ if (widthp)
+ *widthp = w;
+ set_char(i, f, env, w);
+}
+
+void printer::set_numbered_char(int num, const environment *env, int *widthp)
+{
+ int i = font::number_to_index(num);
+ int fn = env->fontno;
+ if (fn < 0 || fn >= nfonts) {
+ error("bad font position `%1'", fn);
+ return;
+ }
+ font *f = font_table[fn];
+ if (f == 0) {
+ error("no font mounted at `%1'", fn);
+ return;
+ }
+ if (!f->contains(i)) {
+ error("font `%1' does not contain numbered character %2",
+ f->get_name(),
+ num);
+ return;
+ }
+ int w = f->get_width(i, env->size);
+ if (widthp)
+ *widthp = w;
+ set_char(i, f, env, w);
+}
+
+// This utility function adjusts the specified center of the
+// arc so that it is equidistant between the specified start
+// and end points. (p[0], p[1]) is a vector from the current
+// point to the center; (p[2], p[3]) is a vector from the
+// center to the end point. If the center can be adjusted,
+// a vector from the current point to the adjusted center is
+// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
+// returned.
+
+#if 1
+int printer::adjust_arc_center(const int *p, double *c)
+{
+ // We move the center along a line parallel to the line between
+ // the specified start point and end point so that the center
+ // is equidistant between the start and end point.
+ // It can be proved (using Lagrange multipliers) that this will
+ // give the point nearest to the specified center that is equidistant
+ // between the start and end point.
+
+ double x = p[0] + p[2]; // (x, y) is the end point
+ double y = p[1] + p[3];
+ double n = x*x + y*y;
+ if (n != 0) {
+ c[0]= double(p[0]);
+ c[1] = double(p[1]);
+ double k = .5 - (c[0]*x + c[1]*y)/n;
+ c[0] += k*x;
+ c[1] += k*y;
+ return 1;
+ }
+ else
+ return 0;
+}
+#else
+int printer::adjust_arc_center(const int *p, double *c)
+{
+ int x = p[0] + p[2]; // (x, y) is the end point
+ int y = p[1] + p[3];
+ // Start at the current point; go in the direction of the specified
+ // center point until we reach a point that is equidistant between
+ // the specified starting point and the specified end point. Place
+ // the center of the arc there.
+ double n = p[0]*double(x) + p[1]*double(y);
+ if (n > 0) {
+ double k = (double(x)*x + double(y)*y)/(2.0*n);
+ // (cx, cy) is our chosen center
+ c[0] = k*p[0];
+ c[1] = k*p[1];
+ return 1;
+ }
+ else {
+ // We would never reach such a point. So instead start at the
+ // specified end point of the arc. Go towards the specified
+ // center point until we reach a point that is equidistant between
+ // the specified start point and specified end point. Place
+ // the center of the arc there.
+ n = p[2]*double(x) + p[3]*double(y);
+ if (n > 0) {
+ double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
+ // (c[0], c[1]) is our chosen center
+ c[0] = p[0] + k*p[2];
+ c[1] = p[1] + k*p[3];
+ return 1;
+ }
+ else
+ return 0;
+ }
+}
+#endif
diff --git a/gnu/usr.bin/groff/libgroff/Makefile b/gnu/usr.bin/groff/libgroff/Makefile
new file mode 100644
index 000000000000..e724ab2e867e
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/Makefile
@@ -0,0 +1,24 @@
+# Makefile for libgroff
+
+LIB= groff
+SRCS= assert.cc change_lf.cc cmap.cc cset.cc device.cc errarg.cc\
+ error.cc fatal.cc filename.cc font.cc fontfile.cc lf.cc\
+ lineno.cc macropath.cc nametoindex.cc new.cc prime.cc\
+ progname.cc ptable.cc searchpath.cc string.cc strsave.cc\
+ tmpfile.cc illegal.cc version.cc
+SRCS+= iftoa.c itoa.c matherr.c
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+
+NOMAN= noman
+NOPROFILE= noprofile
+
+CLEANFILES+= version.cc
+version.cc: $(.CURDIR)/../VERSION
+ @${ECHO} Making version.cc
+ @echo const char \*version_string = \"`cat $(.CURDIR)/../VERSION`\"\; >$@
+
+install:
+
+.include "../Makefile.cfg"
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/groff/libgroff/assert.cc b/gnu/usr.bin/groff/libgroff/assert.cc
new file mode 100644
index 000000000000..1dc0745168e5
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/assert.cc
@@ -0,0 +1,39 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <stdio.h>
+#include <stdlib.h>
+}
+#include "assert.h"
+
+extern const char *program_name;
+
+#ifdef __GNUG__
+volatile
+#endif
+void assertion_failed(int lineno, const char *filename)
+{
+ if (program_name != 0)
+ fprintf(stderr, "%s: ", program_name);
+ fprintf(stderr, "Failed assertion at line %d, file `%s'.\n",
+ lineno, filename);
+ fflush(stderr);
+ abort();
+}
diff --git a/gnu/usr.bin/groff/libgroff/change_lf.cc b/gnu/usr.bin/groff/libgroff/change_lf.cc
new file mode 100644
index 000000000000..34ee6a04ce43
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/change_lf.cc
@@ -0,0 +1,39 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <string.h>
+}
+
+extern char *strsave(const char *);
+
+extern const char *current_filename;
+extern int current_lineno;
+
+void change_filename(const char *f)
+{
+ if (current_filename != 0 && strcmp(current_filename, f) == 0)
+ return;
+ current_filename = strsave(f);
+}
+
+void change_lineno(int ln)
+{
+ current_lineno = ln;
+}
diff --git a/gnu/usr.bin/groff/libgroff/cmap.cc b/gnu/usr.bin/groff/libgroff/cmap.cc
new file mode 100644
index 000000000000..4b1a43e22b24
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/cmap.cc
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <ctype.h>
+#include "cmap.h"
+
+cmap cmlower(CMAP_BUILTIN);
+cmap cmupper(CMAP_BUILTIN);
+
+#define ISASCII(c) isascii(c)
+#if 0
+#define ISASCII(c) 1 /* use this is you have an ANSI ctype.h */
+#endif
+
+cmap::cmap()
+{
+ unsigned char *p = v;
+ for (int i = 0; i <= UCHAR_MAX; i++)
+ p[i] = i;
+}
+
+cmap::cmap(cmap_builtin)
+{
+ // these are initialised by cmap_init::cmap_init()
+}
+
+int cmap_init::initialised = 0;
+
+cmap_init::cmap_init()
+{
+ if (initialised)
+ return;
+ initialised = 1;
+ for (int i = 0; i <= UCHAR_MAX; i++) {
+ cmupper.v[i] = ISASCII(i) && islower(i) ? toupper(i) : i;
+ cmlower.v[i] = ISASCII(i) && isupper(i) ? tolower(i) : i;
+ }
+}
diff --git a/gnu/usr.bin/groff/libgroff/cset.cc b/gnu/usr.bin/groff/libgroff/cset.cc
new file mode 100644
index 000000000000..3a170477446e
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/cset.cc
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <ctype.h>
+#include "cset.h"
+
+cset csalpha(CSET_BUILTIN);
+cset csupper(CSET_BUILTIN);
+cset cslower(CSET_BUILTIN);
+cset csdigit(CSET_BUILTIN);
+cset csxdigit(CSET_BUILTIN);
+cset csspace(CSET_BUILTIN);
+cset cspunct(CSET_BUILTIN);
+cset csalnum(CSET_BUILTIN);
+cset csprint(CSET_BUILTIN);
+cset csgraph(CSET_BUILTIN);
+cset cscntrl(CSET_BUILTIN);
+
+#if 0
+#define ISASCII(c) isascii(c)
+#endif
+#define ISASCII(c) 1 /* use this is you have an ANSI ctype.h */
+
+void cset::clear()
+{
+ char *p = v;
+ for (int i = 0; i <= UCHAR_MAX; i++)
+ p[i] = 0;
+}
+
+cset::cset()
+{
+ clear();
+}
+
+cset::cset(const char *s)
+{
+ clear();
+ while (*s)
+ v[(unsigned char)*s++] = 1;
+}
+
+cset::cset(const unsigned char *s)
+{
+ clear();
+ while (*s)
+ v[*s++] = 1;
+}
+
+cset::cset(cset_builtin)
+{
+ // these are initialised by cset_init::cset_init()
+}
+
+cset &cset::operator|=(const cset &cs)
+{
+ for (int i = 0; i <= UCHAR_MAX; i++)
+ if (cs.v[i])
+ v[i] = 1;
+ return *this;
+}
+
+
+int cset_init::initialised = 0;
+
+cset_init::cset_init()
+{
+ if (initialised)
+ return;
+ initialised = 1;
+ for (int i = 0; i <= UCHAR_MAX; i++) {
+ csalpha.v[i] = ISASCII(i) && isalpha(i);
+ csupper.v[i] = ISASCII(i) && isupper(i);
+ cslower.v[i] = ISASCII(i) && islower(i);
+ csdigit.v[i] = ISASCII(i) && isdigit(i);
+ csxdigit.v[i] = ISASCII(i) && isxdigit(i);
+ csspace.v[i] = ISASCII(i) && isspace(i);
+ cspunct.v[i] = ISASCII(i) && ispunct(i);
+ csalnum.v[i] = ISASCII(i) && isalnum(i);
+ csprint.v[i] = ISASCII(i) && isprint(i);
+ csgraph.v[i] = ISASCII(i) && isgraph(i);
+ cscntrl.v[i] = ISASCII(i) && iscntrl(i);
+ }
+}
diff --git a/gnu/usr.bin/groff/libgroff/device.cc b/gnu/usr.bin/groff/libgroff/device.cc
new file mode 100644
index 000000000000..84a26259e954
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/device.cc
@@ -0,0 +1,38 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <stdlib.h>
+}
+#include "device.h"
+#include "defs.h"
+
+const char *device = DEVICE;
+
+struct device_init {
+ device_init();
+} _device_init;
+
+device_init::device_init()
+{
+ char *tem = getenv("GROFF_TYPESETTER");
+ if (tem)
+ device = tem;
+}
diff --git a/gnu/usr.bin/groff/libgroff/errarg.cc b/gnu/usr.bin/groff/libgroff/errarg.cc
new file mode 100644
index 000000000000..7598c8d91a00
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/errarg.cc
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <stdio.h>
+}
+#include "assert.h"
+#include "errarg.h"
+
+errarg::errarg(const char *p) : type(STRING)
+{
+ s = p ? p : "(null)";
+}
+
+errarg::errarg() : type(EMPTY)
+{
+}
+
+errarg::errarg(unsigned char cc) : type(CHAR)
+{
+ c = cc;
+}
+
+errarg::errarg(int nn) : type(INTEGER)
+{
+ n = nn;
+}
+
+errarg::errarg(char cc) : type(CHAR)
+{
+ c = cc;
+}
+
+errarg::errarg(double dd) : type(DOUBLE)
+{
+ d = dd;
+}
+
+int errarg::empty() const
+{
+ return type == EMPTY;
+}
+
+extern "C" {
+ const char *itoa(int);
+}
+
+void errarg::print() const
+{
+ switch (type) {
+ case INTEGER:
+ fputs(itoa(n), stderr);
+ break;
+ case CHAR:
+ putc(c, stderr);
+ break;
+ case STRING:
+ fputs(s, stderr);
+ break;
+ case DOUBLE:
+ fprintf(stderr, "%g", d);
+ break;
+ case EMPTY:
+ break;
+ }
+}
+
+errarg empty_errarg;
+
+void errprint(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ assert(format != 0);
+ char c;
+ while ((c = *format++) != '\0') {
+ if (c == '%') {
+ c = *format++;
+ switch(c) {
+ case '%':
+ fputc('%', stderr);
+ break;
+ case '1':
+ assert(!arg1.empty());
+ arg1.print();
+ break;
+ case '2':
+ assert(!arg2.empty());
+ arg2.print();
+ break;
+ case '3':
+ assert(!arg3.empty());
+ arg3.print();
+ break;
+ default:
+ assert(0);
+ }
+ }
+ else
+ putc(c, stderr);
+ }
+}
diff --git a/gnu/usr.bin/groff/libgroff/error.cc b/gnu/usr.bin/groff/libgroff/error.cc
new file mode 100644
index 000000000000..adf02d4a02e9
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/error.cc
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+}
+#include "errarg.h"
+#include "error.h"
+
+extern void fatal_error_exit();
+
+enum error_type { WARNING, ERROR, FATAL };
+
+static void do_error_with_file_and_line(const char *filename, int lineno,
+ error_type type,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ int need_space = 0;
+ if (program_name) {
+ fprintf(stderr, "%s:", program_name);
+ need_space = 1;
+ }
+ if (lineno >= 0 && filename != 0) {
+ if (strcmp(filename, "-") == 0)
+ filename = "<standard input>";
+ fprintf(stderr, "%s:%d:", filename, lineno);
+ need_space = 1;
+ }
+ switch (type) {
+ case FATAL:
+ fputs("fatal error:", stderr);
+ need_space = 1;
+ break;
+ case ERROR:
+ break;
+ case WARNING:
+ fputs("warning:", stderr);
+ need_space = 1;
+ break;
+ }
+ if (need_space)
+ fputc(' ', stderr);
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+ if (type == FATAL)
+ fatal_error_exit();
+}
+
+
+static void do_error(error_type type,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(current_filename, current_lineno,
+ type, format, arg1, arg2, arg3);
+}
+
+
+void error(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(ERROR, format, arg1, arg2, arg3);
+}
+
+void warning(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(WARNING, format, arg1, arg2, arg3);
+}
+
+void fatal(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(FATAL, format, arg1, arg2, arg3);
+}
+
+void error_with_file_and_line(const char *filename,
+ int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(filename, lineno,
+ ERROR, format, arg1, arg2, arg3);
+}
+
+void warning_with_file_and_line(const char *filename,
+ int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(filename, lineno,
+ WARNING, format, arg1, arg2, arg3);
+}
+
+void fatal_with_file_and_line(const char *filename,
+ int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(filename, lineno,
+ FATAL, format, arg1, arg2, arg3);
+}
diff --git a/gnu/usr.bin/groff/libgroff/fatal.cc b/gnu/usr.bin/groff/libgroff/fatal.cc
new file mode 100644
index 000000000000..7ab5b07dbd42
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/fatal.cc
@@ -0,0 +1,29 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <stdlib.h>
+}
+
+#define FATAL_ERROR_EXIT_CODE 3
+
+void fatal_error_exit()
+{
+ exit(FATAL_ERROR_EXIT_CODE);
+}
diff --git a/gnu/usr.bin/groff/libgroff/filename.cc b/gnu/usr.bin/groff/libgroff/filename.cc
new file mode 100644
index 000000000000..1cbaa93dddfc
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/filename.cc
@@ -0,0 +1 @@
+const char *current_filename = 0;
diff --git a/gnu/usr.bin/groff/libgroff/fmod.c b/gnu/usr.bin/groff/libgroff/fmod.c
new file mode 100644
index 000000000000..74c5c36b68cd
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/fmod.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <math.h>
+
+double fmod(x, y)
+ double x, y;
+{
+ double quot = x/y;
+ return x - (quot < 0.0 ? ceil(quot) : floor(quot)) * y;
+}
+
diff --git a/gnu/usr.bin/groff/libgroff/font.cc b/gnu/usr.bin/groff/libgroff/font.cc
new file mode 100644
index 000000000000..cda4e113ae2f
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/font.cc
@@ -0,0 +1,911 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include "errarg.h"
+#include "error.h"
+#include "cset.h"
+#include "font.h"
+#include "lib.h"
+
+const char *const WS = " \t\n\r";
+
+struct font_char_metric {
+ char type;
+ int code;
+ int width;
+ int height;
+ int depth;
+ int pre_math_space;
+ int italic_correction;
+ int subscript_correction;
+};
+
+struct font_kern_list {
+ int i1;
+ int i2;
+ int amount;
+ font_kern_list *next;
+
+ font_kern_list(int, int, int, font_kern_list * = 0);
+};
+
+struct font_widths_cache {
+ font_widths_cache *next;
+ int point_size;
+ int *width;
+
+ font_widths_cache(int, int, font_widths_cache *);
+ ~font_widths_cache();
+};
+
+/* text_file */
+
+struct text_file {
+ FILE *fp;
+ char *path;
+ int lineno;
+ int size;
+ int skip_comments;
+ char *buf;
+ text_file(FILE *fp, char *p);
+ ~text_file();
+ int next();
+ void error(const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+};
+
+text_file::text_file(FILE *p, char *s)
+: lineno(0), buf(0), size(0), skip_comments(1), fp(p), path(s)
+{
+}
+
+text_file::~text_file()
+{
+ a_delete buf;
+ a_delete path;
+ if (fp)
+ fclose(fp);
+}
+
+
+int text_file::next()
+{
+ if (fp == 0)
+ return 0;
+ if (buf == 0) {
+ buf = new char [128];
+ size = 128;
+ }
+ for (;;) {
+ int i = 0;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ error("illegal input character code `%1'", int(c));
+ else {
+ if (i + 1 >= size) {
+ char *old_buf = buf;
+ buf = new char[size*2];
+ memcpy(buf, old_buf, size);
+ a_delete old_buf;
+ size *= 2;
+ }
+ buf[i++] = c;
+ if (c == '\n')
+ break;
+ }
+ }
+ if (i == 0)
+ break;
+ buf[i] = '\0';
+ lineno++;
+ char *ptr = buf;
+ while (csspace(*ptr))
+ ptr++;
+ if (*ptr != 0 && (!skip_comments || *ptr != '#'))
+ return 1;
+ }
+ return 0;
+}
+
+void text_file::error(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ error_with_file_and_line(path, lineno, format, arg1, arg2, arg3);
+}
+
+
+/* font functions */
+
+font::font(const char *s)
+: special(0), ligatures(0), kern_hash_table(0), space_width(0),
+ ch(0), ch_used(0), ch_size(0), ch_index(0), nindices(0), widths_cache(0)
+{
+ name = new char[strlen(s) + 1];
+ strcpy(name, s);
+ internalname = 0;
+ slant = 0.0;
+ // load(); // for testing
+}
+
+font::~font()
+{
+ a_delete ch;
+ a_delete ch_index;
+ if (kern_hash_table) {
+ for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++) {
+ font_kern_list *kerns = kern_hash_table[i];
+ while (kerns) {
+ font_kern_list *tem = kerns;
+ kerns = kerns->next;
+ delete tem;
+ }
+ }
+ a_delete kern_hash_table;
+ }
+ a_delete name;
+ a_delete internalname;
+ while (widths_cache) {
+ font_widths_cache *tem = widths_cache;
+ widths_cache = widths_cache->next;
+ delete tem;
+ }
+}
+
+static int scale_round(int n, int x, int y)
+{
+ assert(x >= 0 && y > 0);
+ int y2 = y/2;
+ if (x == 0)
+ return 0;
+ if (n >= 0) {
+ if (n <= (INT_MAX - y2)/x)
+ return (n*x + y2)/y;
+ return int(n*double(x)/double(y) + .5);
+ }
+ else {
+ if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)
+ {
+ // XXX simplify expression to work around bug in gcc-2.6.0
+ int tmp = n*x - y2;
+ return tmp/y;
+ }
+ return int(n*double(x)/double(y) - .5);
+ }
+}
+
+inline int font::scale(int w, int sz)
+{
+ return sz == unitwidth ? w : scale_round(w, sz, unitwidth);
+}
+
+int font::get_skew(int c, int point_size, int sl)
+{
+ int h = get_height(c, point_size);
+ return int(h*tan((slant+sl)*M_PI/180.0) + .5);
+}
+
+int font::contains(int c)
+{
+ return c >= 0 && c < nindices && ch_index[c] >= 0;
+}
+
+int font::is_special()
+{
+ return special;
+}
+
+font_widths_cache::font_widths_cache(int ps, int ch_size,
+ font_widths_cache *p = 0)
+: next(p), point_size(ps)
+{
+ width = new int[ch_size];
+ for (int i = 0; i < ch_size; i++)
+ width[i] = -1;
+}
+
+font_widths_cache::~font_widths_cache()
+{
+ a_delete width;
+}
+
+int font::get_width(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices);
+ int i = ch_index[c];
+ assert(i >= 0);
+
+ if (point_size == unitwidth)
+ return ch[i].width;
+
+ if (!widths_cache)
+ widths_cache = new font_widths_cache(point_size, ch_size);
+ else if (widths_cache->point_size != point_size) {
+ for (font_widths_cache **p = &widths_cache; *p; p = &(*p)->next)
+ if ((*p)->point_size == point_size)
+ break;
+ if (*p) {
+ font_widths_cache *tem = *p;
+ *p = (*p)->next;
+ tem->next = widths_cache;
+ widths_cache = tem;
+ }
+ else
+ widths_cache = new font_widths_cache(point_size, ch_size, widths_cache);
+ }
+ int &w = widths_cache->width[i];
+ if (w < 0)
+ w = scale(ch[i].width, point_size);
+ return w;
+}
+
+int font::get_height(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].height, point_size);
+}
+
+int font::get_depth(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].depth, point_size);
+}
+
+int font::get_italic_correction(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].italic_correction, point_size);
+}
+
+int font::get_left_italic_correction(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].pre_math_space, point_size);
+}
+
+int font::get_subscript_correction(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].subscript_correction, point_size);
+}
+
+int font::get_space_width(int point_size)
+{
+ return scale(space_width, point_size);
+}
+
+font_kern_list::font_kern_list(int c1, int c2, int n, font_kern_list *p)
+ : i1(c1), i2(c2), amount(n), next(p)
+{
+}
+
+inline int font::hash_kern(int i1, int i2)
+{
+ int n = ((i1 << 10) + i2) % KERN_HASH_TABLE_SIZE;
+ return n < 0 ? -n : n;
+}
+
+void font::add_kern(int i1, int i2, int amount)
+{
+ if (!kern_hash_table) {
+ kern_hash_table = new font_kern_list *[KERN_HASH_TABLE_SIZE];
+ for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++)
+ kern_hash_table[i] = 0;
+ }
+ font_kern_list **p = kern_hash_table + hash_kern(i1, i2);
+ *p = new font_kern_list(i1, i2, amount, *p);
+}
+
+int font::get_kern(int i1, int i2, int point_size)
+{
+ if (kern_hash_table) {
+ for (font_kern_list *p = kern_hash_table[hash_kern(i1, i2)]; p; p = p->next)
+ if (i1 == p->i1 && i2 == p->i2)
+ return scale(p->amount, point_size);
+ }
+ return 0;
+}
+
+int font::has_ligature(int mask)
+{
+ return mask & ligatures;
+}
+
+int font::get_character_type(int c)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return ch[ch_index[c]].type;
+}
+
+int font::get_code(int c)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return ch[ch_index[c]].code;
+}
+
+const char *font::get_name()
+{
+ return name;
+}
+
+const char *font::get_internal_name()
+{
+ return internalname;
+}
+
+void font::alloc_ch_index(int index)
+{
+ if (nindices == 0) {
+ nindices = 128;
+ if (index >= nindices)
+ nindices = index + 10;
+ ch_index = new short[nindices];
+ for (int i = 0; i < nindices; i++)
+ ch_index[i] = -1;
+ }
+ else {
+ int old_nindices = nindices;
+ nindices *= 2;
+ if (index >= nindices)
+ nindices = index + 10;
+ short *old_ch_index = ch_index;
+ ch_index = new short[nindices];
+ memcpy(ch_index, old_ch_index, sizeof(short)*old_nindices);
+ for (int i = old_nindices; i < nindices; i++)
+ ch_index[i] = -1;
+ a_delete old_ch_index;
+ }
+}
+
+void font::extend_ch()
+{
+ if (ch == 0)
+ ch = new font_char_metric[ch_size = 16];
+ else {
+ int old_ch_size = ch_size;
+ ch_size *= 2;
+ font_char_metric *old_ch = ch;
+ ch = new font_char_metric[ch_size];
+ memcpy(ch, old_ch, old_ch_size*sizeof(font_char_metric));
+ a_delete old_ch;
+ }
+}
+
+void font::compact()
+{
+ for (int i = nindices - 1; i >= 0; i--)
+ if (ch_index[i] >= 0)
+ break;
+ i++;
+ if (i < nindices) {
+ short *old_ch_index = ch_index;
+ ch_index = new short[i];
+ memcpy(ch_index, old_ch_index, i*sizeof(short));
+ a_delete old_ch_index;
+ nindices = i;
+ }
+ if (ch_used < ch_size) {
+ font_char_metric *old_ch = ch;
+ ch = new font_char_metric[ch_used];
+ memcpy(ch, old_ch, ch_used*sizeof(font_char_metric));
+ a_delete old_ch;
+ ch_size = ch_used;
+ }
+}
+
+void font::add_entry(int index, const font_char_metric &metric)
+{
+ assert(index >= 0);
+ if (index >= nindices)
+ alloc_ch_index(index);
+ assert(index < nindices);
+ if (ch_used + 1 >= ch_size)
+ extend_ch();
+ assert(ch_used + 1 < ch_size);
+ ch_index[index] = ch_used;
+ ch[ch_used++] = metric;
+}
+
+void font::copy_entry(int new_index, int old_index)
+{
+ assert(new_index >= 0 && old_index >= 0 && old_index < nindices);
+ if (new_index >= nindices)
+ alloc_ch_index(new_index);
+ ch_index[new_index] = ch_index[old_index];
+}
+
+font *font::load_font(const char *s, int *not_found)
+{
+ font *f = new font(s);
+ if (!f->load(not_found)) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+static char *trim_arg(char *p)
+{
+ if (!p)
+ return 0;
+ while (csspace(*p))
+ p++;
+ char *q = strchr(p, '\0');
+ while (q > p && csspace(q[-1]))
+ q--;
+ *q = '\0';
+ return p;
+}
+
+// If the font can't be found, then if not_found is NULL it will be set
+// to 1 otherwise a message will be printed.
+
+int font::load(int *not_found)
+{
+ char *path;
+ FILE *fp;
+ if ((fp = open_file(name, &path)) == NULL) {
+ if (not_found)
+ *not_found = 1;
+ else
+ error("can't find font file `%1'", name);
+ return 0;
+ }
+ text_file t(fp, path);
+ t.skip_comments = 1;
+ char *p;
+ for (;;) {
+ if (!t.next()) {
+ t.error("missing charset command");
+ return 0;
+ }
+ p = strtok(t.buf, WS);
+ if (strcmp(p, "name") == 0) {
+ }
+ else if (strcmp(p, "spacewidth") == 0) {
+ p = strtok(0, WS);
+ int n;
+ if (p == 0 || sscanf(p, "%d", &n) != 1 || n <= 0) {
+ t.error("bad argument for spacewidth command");
+ return 0;
+ }
+ space_width = n;
+ }
+ else if (strcmp(p, "slant") == 0) {
+ p = strtok(0, WS);
+ double n;
+ if (p == 0 || sscanf(p, "%lf", &n) != 1 || n >= 90.0 || n <= -90.0) {
+ t.error("bad argument for slant command", p);
+ return 0;
+ }
+ slant = n;
+ }
+ else if (strcmp(p, "ligatures") == 0) {
+ for (;;) {
+ p = strtok(0, WS);
+ if (p == 0 || strcmp(p, "0") == 0)
+ break;
+ if (strcmp(p, "ff") == 0)
+ ligatures |= LIG_ff;
+ else if (strcmp(p, "fi") == 0)
+ ligatures |= LIG_fi;
+ else if (strcmp(p, "fl") == 0)
+ ligatures |= LIG_fl;
+ else if (strcmp(p, "ffi") == 0)
+ ligatures |= LIG_ffi;
+ else if (strcmp(p, "ffl") == 0)
+ ligatures |= LIG_ffl;
+ else {
+ t.error("unrecognised ligature `%1'", p);
+ return 0;
+ }
+ }
+ }
+ else if (strcmp(p, "internalname") == 0) {
+ p = strtok(0, WS);
+ if (!p) {
+ t.error("`internalname command requires argument");
+ return 0;
+ }
+ internalname = new char[strlen(p) + 1];
+ strcpy(internalname, p);
+ }
+ else if (strcmp(p, "special") == 0) {
+ special = 1;
+ }
+ else if (strcmp(p, "kernpairs") != 0 && strcmp(p, "charset") != 0) {
+ char *command = p;
+ p = strtok(0, "\n");
+ handle_unknown_font_command(command, trim_arg(p), t.path, t.lineno);
+ }
+ else
+ break;
+ }
+ char *command = p;
+ int had_charset = 0;
+ t.skip_comments = 0;
+ while (command) {
+ if (strcmp(command, "kernpairs") == 0) {
+ for (;;) {
+ if (!t.next()) {
+ command = 0;
+ break;
+ }
+ char *c1 = strtok(t.buf, WS);
+ if (c1 == 0)
+ continue;
+ char *c2 = strtok(0, WS);
+ if (c2 == 0) {
+ command = c1;
+ break;
+ }
+ p = strtok(0, WS);
+ if (p == 0) {
+ t.error("missing kern amount");
+ return 0;
+ }
+ int n;
+ if (sscanf(p, "%d", &n) != 1) {
+ t.error("bad kern amount `%1'", p);
+ return 0;
+ }
+ int i1 = name_to_index(c1);
+ if (i1 < 0) {
+ t.error("illegal character `%1'", c1);
+ return 0;
+ }
+ int i2 = name_to_index(c2);
+ if (i2 < 0) {
+ t.error("illegal character `%1'", c2);
+ return 0;
+ }
+ add_kern(i1, i2, n);
+ }
+ }
+ else if (strcmp(command, "charset") == 0) {
+ had_charset = 1;
+ int last_index = -1;
+ for (;;) {
+ if (!t.next()) {
+ command = 0;
+ break;
+ }
+ char *nm = strtok(t.buf, WS);
+ if (nm == 0)
+ continue; // I dont think this should happen
+ p = strtok(0, WS);
+ if (p == 0) {
+ command = nm;
+ break;
+ }
+ if (p[0] == '"') {
+ if (last_index == -1) {
+ t.error("first charset entry is duplicate");
+ return 0;
+ }
+ if (strcmp(nm, "---") == 0) {
+ t.error("unnamed character cannot be duplicate");
+ return 0;
+ }
+ int index = name_to_index(nm);
+ if (index < 0) {
+ t.error("illegal character `%1'", nm);
+ return 0;
+ }
+ copy_entry(index, last_index);
+ }
+ else {
+ font_char_metric metric;
+ metric.height = 0;
+ metric.depth = 0;
+ metric.pre_math_space = 0;
+ metric.italic_correction = 0;
+ metric.subscript_correction = 0;
+ int nparms = sscanf(p, "%d,%d,%d,%d,%d,%d",
+ &metric.width, &metric.height, &metric.depth,
+ &metric.italic_correction,
+ &metric.pre_math_space,
+ &metric.subscript_correction);
+ if (nparms < 1) {
+ t.error("bad width for `%1'", nm);
+ return 0;
+ }
+ p = strtok(0, WS);
+ if (p == 0) {
+ t.error("missing character type for `%1'", nm);
+ return 0;
+ }
+ int type;
+ if (sscanf(p, "%d", &type) != 1) {
+ t.error("bad character type for `%1'", nm);
+ return 0;
+ }
+ if (type < 0 || type > 255) {
+ t.error("character code `%1' out of range", type);
+ return 0;
+ }
+ metric.type = type;
+ p = strtok(0, WS);
+ if (p == 0) {
+ t.error("missing code for `%1'", nm);
+ return 0;
+ }
+ char *ptr;
+ metric.code = (int)strtol(p, &ptr, 0);
+ if (metric.code == 0 && ptr == p) {
+ t.error("bad code `%1' for character `%2'", p, nm);
+ return 0;
+ }
+ if (strcmp(nm, "---") == 0) {
+ last_index = number_to_index(metric.code);
+ add_entry(last_index, metric);
+ }
+ else {
+ last_index = name_to_index(nm);
+ if (last_index < 0) {
+ t.error("illegal character `%1'", nm);
+ return 0;
+ }
+ add_entry(last_index, metric);
+ copy_entry(number_to_index(metric.code), last_index);
+ }
+ }
+ }
+ if (last_index == -1) {
+ t.error("I didn't seem to find any characters");
+ return 0;
+ }
+ }
+ else {
+ t.error("unrecognised command `%1' after `kernpairs' or `charset' command", command);
+ return 0;
+ }
+ }
+ if (!had_charset) {
+ t.error("missing charset command");
+ return 0;
+ }
+ if (space_width == 0)
+ space_width = scale_round(unitwidth, res, 72*3*sizescale);
+ compact();
+ return 1;
+}
+
+static struct {
+ const char *command;
+ int *ptr;
+} table[] = {
+ "res", &font::res,
+ "hor", &font::hor,
+ "vert", &font::vert,
+ "unitwidth", &font::unitwidth,
+ "paperwidth", &font::paperwidth,
+ "paperlength", &font::paperlength,
+ "spare1", &font::biggestfont,
+ "biggestfont", &font::biggestfont,
+ "spare2", &font::spare2,
+ "sizescale", &font::sizescale
+ };
+
+
+int font::load_desc()
+{
+ int nfonts = 0;
+ FILE *fp;
+ char *path;
+ if ((fp = open_file("DESC", &path)) == 0) {
+ error("can't find `DESC' file");
+ return 0;
+ }
+ text_file t(fp, path);
+ t.skip_comments = 1;
+ res = 0;
+ while (t.next()) {
+ char *p = strtok(t.buf, WS);
+ int found = 0;
+ for (int i = 0; !found && i < sizeof(table)/sizeof(table[0]); i++)
+ if (strcmp(table[i].command, p) == 0)
+ found = 1;
+ if (found) {
+ char *q = strtok(0, WS);
+ if (!q) {
+ t.error("missing value for command `%1'", p);
+ return 0;
+ }
+ //int *ptr = &(this->*(table[i-1].ptr));
+ int *ptr = table[i-1].ptr;
+ if (sscanf(q, "%d", ptr) != 1) {
+ t.error("bad number `%1'", q);
+ return 0;
+ }
+ }
+ else if (strcmp("tcommand", p) == 0) {
+ tcommand = 1;
+ }
+ else if (strcmp("family", p) == 0) {
+ p = strtok(0, WS);
+ if (!p) {
+ t.error("family command requires an argument");
+ return 0;
+ }
+ char *tem = new char[strlen(p)+1];
+ strcpy(tem, p);
+ family = tem;
+ }
+ else if (strcmp("fonts", p) == 0) {
+ p = strtok(0, WS);
+ if (!p || sscanf(p, "%d", &nfonts) != 1 || nfonts <= 0) {
+ t.error("bad number of fonts `%1'", p);
+ return 0;
+ }
+ font_name_table = (const char **)new char *[nfonts+1];
+ for (int i = 0; i < nfonts; i++) {
+ p = strtok(0, WS);
+ while (p == 0) {
+ if (!t.next()) {
+ t.error("end of file while reading list of fonts");
+ return 0;
+ }
+ p = strtok(t.buf, WS);
+ }
+ char *temp = new char[strlen(p)+1];
+ strcpy(temp, p);
+ font_name_table[i] = temp;
+ }
+ p = strtok(0, WS);
+ if (p != 0) {
+ t.error("font count does not match number of fonts");
+ return 0;
+ }
+ font_name_table[nfonts] = 0;
+ }
+ else if (strcmp("sizes", p) == 0) {
+ int n = 16;
+ sizes = new int[n];
+ int i = 0;
+ for (;;) {
+ p = strtok(0, WS);
+ while (p == 0) {
+ if (!t.next()) {
+ t.error("list of sizes must be terminated by `0'");
+ return 0;
+ }
+ p = strtok(t.buf, WS);
+ }
+ int lower, upper;
+ switch (sscanf(p, "%d-%d", &lower, &upper)) {
+ case 1:
+ upper = lower;
+ // fall through
+ case 2:
+ if (lower <= upper && lower >= 0)
+ break;
+ // fall through
+ default:
+ t.error("bad size range `%1'", p);
+ return 0;
+ }
+ if (i + 2 > n) {
+ int *old_sizes = sizes;
+ sizes = new int[n*2];
+ memcpy(sizes, old_sizes, n*sizeof(int));
+ n *= 2;
+ a_delete old_sizes;
+ }
+ sizes[i++] = lower;
+ if (lower == 0)
+ break;
+ sizes[i++] = upper;
+ }
+ if (i == 1) {
+ t.error("must have some sizes");
+ return 0;
+ }
+ }
+ else if (strcmp("styles", p) == 0) {
+ int style_table_size = 5;
+ style_table = (const char **)new char *[style_table_size];
+ for (int j = 0; j < style_table_size; j++)
+ style_table[j] = 0;
+ int i = 0;
+ for (;;) {
+ p = strtok(0, WS);
+ if (p == 0)
+ break;
+ // leave room for terminating 0
+ if (i + 1 >= style_table_size) {
+ const char **old_style_table = style_table;
+ style_table_size *= 2;
+ style_table = (const char **)new char*[style_table_size];
+ for (j = 0; j < i; j++)
+ style_table[j] = old_style_table[j];
+ for (; j < style_table_size; j++)
+ style_table[j] = 0;
+ a_delete old_style_table;
+ }
+ char *tem = new char[strlen(p) + 1];
+ strcpy(tem, p);
+ style_table[i++] = tem;
+ }
+ }
+ else if (strcmp("charset", p) == 0)
+ break;
+ else if (unknown_desc_command_handler) {
+ char *command = p;
+ p = strtok(0, "\n");
+ (*unknown_desc_command_handler)(command, trim_arg(p), t.path, t.lineno);
+ }
+ }
+ if (res == 0) {
+ t.error("missing `res' command");
+ return 0;
+ }
+ if (unitwidth == 0) {
+ t.error("missing `unitwidth' command");
+ return 0;
+ }
+ if (font_name_table == 0) {
+ t.error("missing `fonts' commmand");
+ return 0;
+ }
+ if (sizes == 0) {
+ t.error("missing `sizes' command");
+ return 0;
+ }
+ if (sizescale < 1) {
+ t.error("bad `sizescale' value");
+ return 0;
+ }
+ if (hor < 1) {
+ t.error("bad `hor' value");
+ return 0;
+ }
+ if (vert < 1) {
+ t.error("bad `vert' value");
+ return 0;
+ }
+ return 1;
+}
+
+void font::handle_unknown_font_command(const char *, const char *,
+ const char *, int)
+{
+}
+
+FONT_COMMAND_HANDLER
+font::set_unknown_desc_command_handler(FONT_COMMAND_HANDLER func)
+{
+ FONT_COMMAND_HANDLER prev = unknown_desc_command_handler;
+ unknown_desc_command_handler = func;
+ return prev;
+}
+
diff --git a/gnu/usr.bin/groff/libgroff/fontfile.cc b/gnu/usr.bin/groff/libgroff/fontfile.cc
new file mode 100644
index 000000000000..5353958dbedc
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/fontfile.cc
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "font.h"
+#include "lib.h"
+#include "searchpath.h"
+#include "device.h"
+#include "defs.h"
+
+const char *const FONT_ENV_VAR = "GROFF_FONT_PATH";
+
+static search_path font_path(FONT_ENV_VAR, FONTPATH);
+
+int font::res = 0;
+int font::hor = 1;
+int font::vert = 1;
+int font::unitwidth = 0;
+int font::paperwidth = 0;
+int font::paperlength = 0;
+int font::biggestfont = 0;
+int font::spare2 = 0;
+int font::sizescale = 1;
+int font::tcommand = 0;
+const char **font::font_name_table = 0;
+int *font::sizes = 0;
+const char *font::family = 0;
+const char **font::style_table = 0;
+FONT_COMMAND_HANDLER font::unknown_desc_command_handler = 0;
+
+void font::command_line_font_dir(const char *dir)
+{
+ font_path.command_line_dir(dir);
+}
+
+FILE *font::open_file(const char *name, char **pathp)
+{
+ char *filename = new char[strlen(name) + strlen(device) + 5];
+ sprintf(filename, "dev%s/%s", device, name);
+ FILE *fp = font_path.open_file(filename, pathp);
+ a_delete filename;
+ return fp;
+}
diff --git a/gnu/usr.bin/groff/libgroff/getcwd.c b/gnu/usr.bin/groff/libgroff/getcwd.c
new file mode 100644
index 000000000000..208e81118530
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/getcwd.c
@@ -0,0 +1,38 @@
+/* Partial emulation of getcwd in terms of getwd. */
+
+#include <sys/param.h>
+#include <string.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+char *getwd();
+
+char *getcwd(buf, size)
+ char *buf;
+ int size; /* POSIX says this should be size_t */
+{
+ if (size <= 0) {
+ errno = EINVAL;
+ return 0;
+ }
+ else {
+ char mybuf[MAXPATHLEN];
+ int saved_errno = errno;
+
+ errno = 0;
+ if (!getwd(mybuf)) {
+ if (errno == 0)
+ ; /* what to do? */
+ return 0;
+ }
+ errno = saved_errno;
+ if (strlen(mybuf) + 1 > size) {
+ errno = ERANGE;
+ return 0;
+ }
+ strcpy(buf, mybuf);
+ return buf;
+ }
+}
diff --git a/gnu/usr.bin/groff/libgroff/iftoa.c b/gnu/usr.bin/groff/libgroff/iftoa.c
new file mode 100644
index 000000000000..ac37183a4d78
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/iftoa.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define INT_DIGITS 19 /* enough for 64-bit integer */
+
+char *iftoa(i, decimal_point)
+ int i, decimal_point;
+{
+ /* room for a -, INT_DIGITS digits, a decimal point, and a terminating '\0' */
+ static char buf[INT_DIGITS + 3];
+ char *p = buf + INT_DIGITS + 2;
+ int point = 0;
+ buf[INT_DIGITS + 2] = '\0';
+ /* assert(decimal_point <= INT_DIGITS); */
+ if (i >= 0) {
+ do {
+ *--p = '0' + (i % 10);
+ i /= 10;
+ if (++point == decimal_point)
+ *--p = '.';
+ } while (i != 0 || point < decimal_point);
+ }
+ else { /* i < 0 */
+ do {
+ *--p = '0' - (i % 10);
+ i /= 10;
+ if (++point == decimal_point)
+ *--p = '.';
+ } while (i != 0 || point < decimal_point);
+ *--p = '-';
+ }
+ if (decimal_point > 0) {
+ char *q;
+ /* there must be a dot, so this will terminate */
+ for (q = buf + INT_DIGITS + 2; q[-1] == '0'; --q)
+ ;
+ if (q[-1] == '.') {
+ if (q - 1 == p) {
+ q[-1] = '0';
+ q[0] = '\0';
+ }
+ else
+ q[-1] = '\0';
+ }
+ else
+ *q = '\0';
+ }
+ return p;
+}
diff --git a/gnu/usr.bin/groff/libgroff/illegal.cc b/gnu/usr.bin/groff/libgroff/illegal.cc
new file mode 100644
index 000000000000..10f4d5bd7d54
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/illegal.cc
@@ -0,0 +1,22 @@
+#include "lib.h"
+
+// Table of illegal input characters.
+
+char illegal_char_table[256]= {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
diff --git a/gnu/usr.bin/groff/libgroff/itoa.c b/gnu/usr.bin/groff/libgroff/itoa.c
new file mode 100644
index 000000000000..e10d9dcfb82e
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/itoa.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define INT_DIGITS 19 /* enough for 64 bit integer */
+
+char *itoa(i)
+ int i;
+{
+ /* Room for INT_DIGITS digits, - and '\0' */
+ static char buf[INT_DIGITS + 2];
+ char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */
+ if (i >= 0) {
+ do {
+ *--p = '0' + (i % 10);
+ i /= 10;
+ } while (i != 0);
+ return p;
+ }
+ else { /* i < 0 */
+ do {
+ *--p = '0' - (i % 10);
+ i /= 10;
+ } while (i != 0);
+ *--p = '-';
+ }
+ return p;
+}
diff --git a/gnu/usr.bin/groff/libgroff/lf.cc b/gnu/usr.bin/groff/libgroff/lf.cc
new file mode 100644
index 000000000000..482b102a479a
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/lf.cc
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <string.h>
+#include <ctype.h>
+}
+#include "cset.h"
+#include "stringclass.h"
+
+extern void change_filename(const char *);
+extern void change_lineno(int);
+
+int interpret_lf_args(const char *p)
+{
+ while (*p == ' ')
+ p++;
+ if (!csdigit(*p))
+ return 0;
+ int ln = 0;
+ do {
+ ln *= 10;
+ ln += *p++ - '0';
+ } while (csdigit(*p));
+ if (*p != ' ' && *p != '\n' && *p != '\0')
+ return 0;
+ while (*p == ' ')
+ p++;
+ if (*p == '\0' || *p == '\n') {
+ change_lineno(ln);
+ return 1;
+ }
+ for (const char *q = p;
+ *q != '\0' && *q != ' ' && *q != '\n' && *q != '\\';
+ q++)
+ ;
+ string tem(p, q - p);
+ while (*q == ' ')
+ q++;
+ if (*q != '\n' && *q != '\0')
+ return 0;
+ tem += '\0';
+ change_filename(tem.contents());
+ change_lineno(ln);
+ return 1;
+}
diff --git a/gnu/usr.bin/groff/libgroff/lineno.cc b/gnu/usr.bin/groff/libgroff/lineno.cc
new file mode 100644
index 000000000000..f7138dba0210
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/lineno.cc
@@ -0,0 +1 @@
+int current_lineno = 0;
diff --git a/gnu/usr.bin/groff/libgroff/macropath.cc b/gnu/usr.bin/groff/libgroff/macropath.cc
new file mode 100644
index 000000000000..7297977e911c
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/macropath.cc
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "lib.h"
+#include "searchpath.h"
+#include "macropath.h"
+#include "defs.h"
+
+#define MACROPATH_ENVVAR "GROFF_TMAC_PATH"
+
+extern "C" { search_path macro_path(MACROPATH_ENVVAR, MACROPATH); }
diff --git a/gnu/usr.bin/groff/libgroff/matherr.c b/gnu/usr.bin/groff/libgroff/matherr.c
new file mode 100644
index 000000000000..1f334f405279
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/matherr.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <math.h>
+#include <errno.h>
+
+#ifdef HAVE_STRUCT_EXCEPTION
+#ifdef TLOSS
+
+int matherr(exc)
+struct exception *exc;
+{
+ switch (exc->type) {
+ case SING:
+ case DOMAIN:
+ errno = EDOM;
+ break;
+ case OVERFLOW:
+ case UNDERFLOW:
+ case TLOSS:
+ case PLOSS:
+ errno = ERANGE;
+ break;
+ }
+ return 1;
+}
+
+#endif /* TLOSS */
+#endif /* HAVE_STRUCT_EXCEPTION */
diff --git a/gnu/usr.bin/groff/libgroff/nametoindex.cc b/gnu/usr.bin/groff/libgroff/nametoindex.cc
new file mode 100644
index 000000000000..827e15a1ee44
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/nametoindex.cc
@@ -0,0 +1,117 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "font.h"
+#include "ptable.h"
+
+declare_ptable(int)
+implement_ptable(int)
+
+class character_indexer {
+public:
+ character_indexer();
+ ~character_indexer();
+ int ascii_char_index(unsigned char);
+ int named_char_index(const char *);
+ int numbered_char_index(int);
+private:
+ enum { NSMALL = 256 };
+ int next_index;
+ int ascii_index[256];
+ int small_number_index[NSMALL];
+ PTABLE(int) table;
+ int lookup_char(const char *, int);
+};
+
+character_indexer::character_indexer()
+: next_index(0)
+{
+ for (int i = 0; i < 256; i++)
+ ascii_index[i] = -1;
+ for (i = 0; i < NSMALL; i++)
+ small_number_index[i] = -1;
+}
+
+character_indexer::~character_indexer()
+{
+}
+
+int character_indexer::ascii_char_index(unsigned char c)
+{
+ if (ascii_index[c] < 0)
+ ascii_index[c] = next_index++;
+ return ascii_index[c];
+}
+
+int character_indexer::numbered_char_index(int n)
+{
+ if (n >= 0 && n < NSMALL) {
+ if (small_number_index[n] < 0)
+ small_number_index[n] = next_index++;
+ return small_number_index[n];
+ }
+ // Not the most efficient possible implementation.
+ char buf[INT_DIGITS + 3];
+ buf[0] = ' ';
+ strcpy(buf + 1, itoa(n));
+ return named_char_index(buf);
+}
+
+int character_indexer::named_char_index(const char *s)
+{
+ int *np = table.lookup(s);
+ if (!np) {
+ np = new int;
+ *np = next_index++;
+ table.define(s, np);
+ }
+ return *np;
+}
+
+static character_indexer indexer;
+
+int font::number_to_index(int n)
+{
+ return indexer.numbered_char_index(n);
+}
+
+int font::name_to_index(const char *s)
+{
+ assert(s != 0 && s[0] != '\0' && s[0] != ' ');
+ if (s[1] == '\0')
+ return indexer.ascii_char_index(s[0]);
+ /* char128 and \200 are synonyms */
+ if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
+ char *res;
+ long n = strtol(s + 4, &res, 10);
+ if (res != s + 4 && *res == '\0' && n >= 0 && n < 256)
+ return indexer.ascii_char_index((unsigned char)n);
+ }
+ return indexer.named_char_index(s);
+}
+
diff --git a/gnu/usr.bin/groff/libgroff/new.cc b/gnu/usr.bin/groff/libgroff/new.cc
new file mode 100644
index 000000000000..fbb038376fe5
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/new.cc
@@ -0,0 +1,67 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+}
+
+#include "posix.h"
+
+extern const char *program_name;
+
+static void ewrite(const char *s)
+{
+ write(2, s, strlen(s));
+}
+
+void *operator new(size_t size)
+{
+ // Avoid relying on the behaviour of malloc(0).
+ if (size == 0)
+ size++;
+#ifdef COOKIE_BUG
+ char *p = (char *)malloc(unsigned(size + 8));
+ if (p != 0) {
+ ((unsigned *)p)[1] = 0;
+ return p + 8;
+ }
+#else /* not COOKIE_BUG */
+ char *p = (char *)malloc(unsigned(size));
+ if (p != 0)
+ return p;
+#endif /* not COOKIE_BUG */
+ if (program_name) {
+ ewrite(program_name);
+ ewrite(": ");
+ }
+ ewrite("out of memory\n");
+ _exit(-1);
+}
+
+#ifdef COOKIE_BUG
+
+void operator delete(void *p)
+{
+ if (p)
+ free((void *)((char *)p - 8));
+}
+
+#endif /* COOKIE_BUG */
diff --git a/gnu/usr.bin/groff/libgroff/prime.cc b/gnu/usr.bin/groff/libgroff/prime.cc
new file mode 100644
index 000000000000..531856c2a59a
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/prime.cc
@@ -0,0 +1,28 @@
+extern "C" {
+#include <math.h>
+}
+
+int is_prime(unsigned n)
+{
+ if (n <= 3)
+ return 1;
+ if (!(n & 1))
+ return 0;
+ if (n % 3 == 0)
+ return 0;
+ unsigned lim = unsigned(sqrt((double)n));
+ unsigned d = 5;
+ for (;;) {
+ if (d > lim)
+ break;
+ if (n % d == 0)
+ return 0;
+ d += 2;
+ if (d > lim)
+ break;
+ if (n % d == 0)
+ return 0;
+ d += 4;
+ }
+ return 1;
+}
diff --git a/gnu/usr.bin/groff/libgroff/progname.cc b/gnu/usr.bin/groff/libgroff/progname.cc
new file mode 100644
index 000000000000..a70e3419c2be
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/progname.cc
@@ -0,0 +1 @@
+const char *program_name = 0;
diff --git a/gnu/usr.bin/groff/libgroff/ptable.cc b/gnu/usr.bin/groff/libgroff/ptable.cc
new file mode 100644
index 000000000000..a6086de9934b
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/ptable.cc
@@ -0,0 +1,51 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "ptable.h"
+#include "errarg.h"
+#include "error.h"
+
+unsigned long hash_string(const char *s)
+{
+ assert(s != 0);
+ unsigned long h = 0, g;
+ while (*s != 0) {
+ h <<= 4;
+ h += *s++;
+ if ((g = h & 0xf0000000) != 0) {
+ h ^= g >> 24;
+ h ^= g;
+ }
+ }
+ return h;
+}
+
+static const unsigned table_sizes[] = {
+101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009,
+80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009,
+16000057, 32000011, 64000031, 128000003, 0
+};
+
+unsigned next_ptable_size(unsigned n)
+{
+ for (const unsigned *p = table_sizes; *p <= n; p++)
+ if (*p == 0)
+ fatal("cannot expand table");
+ return *p;
+}
diff --git a/gnu/usr.bin/groff/libgroff/putenv.c b/gnu/usr.bin/groff/libgroff/putenv.c
new file mode 100644
index 000000000000..9e1cd322cac2
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/putenv.c
@@ -0,0 +1,96 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Hacked slightly by jjc@jclark.com for groff. */
+
+#include <string.h>
+
+#ifdef __STDC__
+#include <stddef.h>
+typedef void *PTR;
+typedef size_t SIZE_T;
+#else /* not __STDC__ */
+typedef char *PTR;
+typedef int SIZE_T;
+#endif /* not __STDC__ */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else /* not HAVE_STDLIB_H */
+PTR malloc();
+#endif /* not HAVE_STDLIB_H */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+extern char **environ;
+
+/* Put STRING, which is of the form "NAME=VALUE", in the environment. */
+
+int putenv(string)
+ char *string;
+{
+ char *name_end = strchr(string, '=');
+ SIZE_T size;
+ char **ep;
+
+ if (name_end == NULL)
+ {
+ /* Remove the variable from the environment. */
+ size = strlen(string);
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp(*ep, string, size) && (*ep)[size] == '=')
+ {
+ while (ep[1] != NULL)
+ {
+ ep[0] = ep[1];
+ ++ep;
+ }
+ *ep = NULL;
+ return 0;
+ }
+ }
+
+ size = 0;
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp(*ep, string, name_end - string)
+ && (*ep)[name_end - string] == '=')
+ break;
+ else
+ ++size;
+
+ if (*ep == NULL)
+ {
+ static char **last_environ = NULL;
+ char **new_environ = (char **) malloc((size + 2) * sizeof(char *));
+ if (new_environ == NULL)
+ return -1;
+ (void) memcpy((PTR) new_environ, (PTR) environ, size * sizeof(char *));
+ new_environ[size] = (char *) string;
+ new_environ[size + 1] = NULL;
+ if (last_environ != NULL)
+ free((PTR) last_environ);
+ last_environ = new_environ;
+ environ = new_environ;
+ }
+ else
+ *ep = (char *) string;
+
+ return 0;
+}
diff --git a/gnu/usr.bin/groff/libgroff/searchpath.cc b/gnu/usr.bin/groff/libgroff/searchpath.cc
new file mode 100644
index 000000000000..eb7a6690cd3b
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/searchpath.cc
@@ -0,0 +1,117 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "lib.h"
+#include "searchpath.h"
+
+search_path::search_path(const char *envvar, const char *standard)
+{
+ char *e = envvar ? getenv(envvar) : 0;
+ if (e && standard) {
+ dirs = new char[strlen(e) + strlen(standard) + 2];
+ strcpy(dirs, e);
+ strcat(dirs, ":");
+ strcat(dirs, standard);
+ }
+ else
+ dirs = strsave(e ? e : standard);
+ init_len = dirs ? strlen(dirs) : 0;
+}
+
+search_path::~search_path()
+{
+ if (dirs)
+ a_delete dirs;
+}
+
+void search_path::command_line_dir(const char *s)
+{
+ if (!dirs)
+ dirs = strsave(s);
+ else {
+ char *old = dirs;
+ unsigned old_len = strlen(old);
+ unsigned slen = strlen(s);
+ dirs = new char[old_len + 1 + slen + 1];
+ memcpy(dirs, old, old_len - init_len);
+ char *p = dirs;
+ p += old_len - init_len;
+ if (init_len == 0)
+ *p++ = ':';
+ memcpy(p, s, slen);
+ p += slen;
+ if (init_len > 0) {
+ *p++ = ':';
+ memcpy(p, old + old_len - init_len, init_len);
+ p += init_len;
+ }
+ *p++ = '\0';
+ a_delete old;
+ }
+}
+
+FILE *search_path::open_file(const char *name, char **pathp)
+{
+ assert(name != 0);
+ if (*name == '/' || dirs == 0 || *dirs == '\0') {
+ FILE *fp = fopen(name, "r");
+ if (fp) {
+ if (pathp)
+ *pathp = strsave(name);
+ return fp;
+ }
+ else
+ return 0;
+ }
+ unsigned namelen = strlen(name);
+ char *p = dirs;
+ for (;;) {
+ char *end = strchr(p, ':');
+ if (!end)
+ end = strchr(p, '\0');
+ int need_slash = end > p && end[-1] != '/';
+ char *path = new char[(end - p) + need_slash + namelen + 1];
+ memcpy(path, p, end - p);
+ if (need_slash)
+ path[end - p] = '/';
+ strcpy(path + (end - p) + need_slash, name);
+#if 0
+ fprintf(stderr, "trying `%s'\n", path);
+#endif
+ FILE *fp = fopen(path, "r");
+ if (fp) {
+ if (pathp)
+ *pathp = path;
+ else
+ a_delete path;
+ return fp;
+ }
+ a_delete path;
+ if (*end == '\0')
+ break;
+ p = end + 1;
+ }
+ return 0;
+}
diff --git a/gnu/usr.bin/groff/libgroff/strerror.c b/gnu/usr.bin/groff/libgroff/strerror.c
new file mode 100644
index 000000000000..de42b838468d
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/strerror.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#define INT_DIGITS 19 /* enough for 64 bit integer */
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char *strerror(n)
+ int n;
+{
+ static char buf[sizeof("Error ") + 1 + INT_DIGITS];
+ if (n >= 0 && n < sys_nerr && sys_errlist[n] != 0)
+ return sys_errlist[n];
+ else {
+ sprintf(buf, "Error %d", n);
+ return buf;
+ }
+}
diff --git a/gnu/usr.bin/groff/libgroff/string.cc b/gnu/usr.bin/groff/libgroff/string.cc
new file mode 100644
index 000000000000..e20e24906864
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/string.cc
@@ -0,0 +1,310 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "stringclass.h"
+#include "lib.h"
+
+static char *salloc(int len, int *sizep);
+static void sfree(char *ptr, int size);
+static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
+static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep);
+
+static char *salloc(int len, int *sizep)
+{
+ if (len == 0) {
+ *sizep = 0;
+ return 0;
+ }
+ else
+ return new char[*sizep = len*2];
+}
+
+static void sfree(char *ptr, int)
+{
+ a_delete ptr;
+}
+
+static char *sfree_alloc(char *ptr, int oldsz, int len, int *sizep)
+{
+ if (oldsz >= len) {
+ *sizep = oldsz;
+ return ptr;
+ }
+ a_delete ptr;
+ if (len == 0) {
+ *sizep = 0;
+ return 0;
+ }
+ else
+ return new char[*sizep = len*2];
+}
+
+static char *srealloc(char *ptr, int oldsz, int oldlen, int newlen, int *sizep)
+{
+ if (oldsz >= newlen) {
+ *sizep = oldsz;
+ return ptr;
+ }
+ if (newlen == 0) {
+ a_delete ptr;
+ *sizep = 0;
+ return 0;
+ }
+ else {
+ char *p = new char[*sizep = newlen*2];
+ if (oldlen < newlen && oldlen != 0)
+ memcpy(p, ptr, oldlen);
+ a_delete ptr;
+ return p;
+ }
+}
+
+string::string() : len(0), ptr(0), sz(0)
+{
+}
+
+string::string(const char *p, int n) : len(n)
+{
+ assert(n >= 0);
+ ptr = salloc(n, &sz);
+ if (n != 0)
+ memcpy(ptr, p, n);
+}
+
+string::string(const char *p)
+{
+ if (p == 0) {
+ len = 0;
+ ptr = 0;
+ sz = 0;
+ }
+ else {
+ len = strlen(p);
+ ptr = salloc(len, &sz);
+ memcpy(ptr, p, len);
+ }
+}
+
+string::string(char c) : len(1)
+{
+ ptr = salloc(1, &sz);
+ *ptr = c;
+}
+
+string::string(const string &s) : len(s.len)
+{
+ ptr = salloc(len, &sz);
+ if (len != 0)
+ memcpy(ptr, s.ptr, len);
+}
+
+string::~string()
+{
+ sfree(ptr, sz);
+}
+
+string &string::operator=(const string &s)
+{
+ ptr = sfree_alloc(ptr, sz, s.len, &sz);
+ len = s.len;
+ if (len != 0)
+ memcpy(ptr, s.ptr, len);
+ return *this;
+}
+
+string &string::operator=(const char *p)
+{
+ if (p == 0) {
+ sfree(ptr, len);
+ len = 0;
+ ptr = 0;
+ sz = 0;
+ }
+ else {
+ int slen = strlen(p);
+ ptr = sfree_alloc(ptr, sz, slen, &sz);
+ len = slen;
+ memcpy(ptr, p, len);
+ }
+ return *this;
+}
+
+string &string::operator=(char c)
+{
+ ptr = sfree_alloc(ptr, sz, 1, &sz);
+ len = 1;
+ *ptr = c;
+ return *this;
+}
+
+void string::move(string &s)
+{
+ sfree(ptr, sz);
+ ptr = s.ptr;
+ len = s.len;
+ sz = s.sz;
+ s.ptr = 0;
+ s.len = 0;
+ s.sz = 0;
+}
+
+void string::grow1()
+{
+ ptr = srealloc(ptr, sz, len, len + 1, &sz);
+}
+
+string &string::operator+=(const char *p)
+{
+ if (p != 0) {
+ int n = strlen(p);
+ int newlen = len + n;
+ if (newlen > sz)
+ ptr = srealloc(ptr, sz, len, newlen, &sz);
+ memcpy(ptr + len, p, n);
+ len = newlen;
+ }
+ return *this;
+}
+
+string &string::operator+=(const string &s)
+{
+ if (s.len != 0) {
+ int newlen = len + s.len;
+ if (newlen > sz)
+ ptr = srealloc(ptr, sz, len, newlen, &sz);
+ memcpy(ptr + len, s.ptr, s.len);
+ len = newlen;
+ }
+ return *this;
+}
+
+void string::append(const char *p, int n)
+{
+ if (n > 0) {
+ int newlen = len + n;
+ if (newlen > sz)
+ ptr = srealloc(ptr, sz, len, newlen, &sz);
+ memcpy(ptr + len, p, n);
+ len = newlen;
+ }
+}
+
+string::string(const char *s1, int n1, const char *s2, int n2)
+{
+ assert(n1 >= 0 && n2 >= 0);
+ len = n1 + n2;
+ if (len == 0) {
+ sz = 0;
+ ptr = 0;
+ }
+ else {
+ ptr = salloc(len, &sz);
+ if (n1 == 0)
+ memcpy(ptr, s2, n2);
+ else {
+ memcpy(ptr, s1, n1);
+ if (n2 != 0)
+ memcpy(ptr + n1, s2, n2);
+ }
+ }
+}
+
+int operator<=(const string &s1, const string &s2)
+{
+ return (s1.len <= s2.len
+ ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
+ : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
+}
+
+int operator<(const string &s1, const string &s2)
+{
+ return (s1.len < s2.len
+ ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
+ : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
+}
+
+int operator>=(const string &s1, const string &s2)
+{
+ return (s1.len >= s2.len
+ ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
+ : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
+}
+
+int operator>(const string &s1, const string &s2)
+{
+ return (s1.len > s2.len
+ ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
+ : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
+}
+
+void string::set_length(int i)
+{
+ assert(i >= 0);
+ if (i > sz)
+ ptr = srealloc(ptr, sz, len, i, &sz);
+ len = i;
+}
+
+void string::clear()
+{
+ len = 0;
+}
+
+int string::search(char c) const
+{
+ char *p = (char *)memchr(ptr, c, len);
+ return p ? p - ptr : -1;
+}
+
+// we silently strip nuls
+
+char *string::extract() const
+{
+ char *p = ptr;
+ int n = len;
+ int nnuls = 0;
+ for (int i = 0; i < n; i++)
+ if (p[i] == '\0')
+ nnuls++;
+ char *q = new char[n + 1 - nnuls];
+ char *r = q;
+ for (i = 0; i < n; i++)
+ if (p[i] != '\0')
+ *r++ = p[i];
+ q[n] = '\0';
+ return q;
+}
+
+void put_string(const string &s, FILE *fp)
+{
+ int len = s.length();
+ const char *ptr = s.contents();
+ for (int i = 0; i < len; i++)
+ putc(ptr[i], fp);
+}
+
+string as_string(int i)
+{
+ static char buf[INT_DIGITS + 2];
+ sprintf(buf, "%d", i);
+ return string(buf);
+}
+
diff --git a/gnu/usr.bin/groff/libgroff/strsave.cc b/gnu/usr.bin/groff/libgroff/strsave.cc
new file mode 100644
index 000000000000..ab09644ec8b9
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/strsave.cc
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern "C" {
+#include <string.h>
+}
+
+char *strsave(const char *s)
+{
+ if (s == 0)
+ return 0;
+ char *p = new char[strlen(s) + 1];
+ strcpy(p, s);
+ return p;
+}
+
diff --git a/gnu/usr.bin/groff/libgroff/strtol.c b/gnu/usr.bin/groff/libgroff/strtol.c
new file mode 100644
index 000000000000..4a1830f685cb
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/strtol.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+
+#ifndef LONG_MIN
+#define LONG_MIN (-LONG_MAX-1)
+#endif
+
+long strtol(str, ptr, base)
+ char *str, **ptr;
+ int base;
+{
+ char *start = str;
+ int neg = 0;
+ long val;
+ char *p;
+ static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+ while (isascii(*str) && isspace(*str))
+ str++;
+
+ if (*str == '-') {
+ neg = 1;
+ str++;
+ }
+ if (base == 0) {
+ if (*str == '0') {
+ if (str[1] == 'x' || str[1] == 'X') {
+ str += 2;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+ if (base < 2 || base > 36)
+ base = 10;
+ else if (base == 16 && *str == '0' && (str[1] == 'x' || str[1] == 'X'))
+ str += 2;
+
+ p = strchr(digits, isascii(*str) && isupper(*str) ? tolower(*str) : *str);
+ if (p == 0 || (val = (p - digits)) >= base) {
+ if (base == 16 && str > start && (str[-1] == 'x' || str[-1] == 'X')) {
+ if (ptr)
+ *ptr = str - 1;
+ }
+ else {
+ if (ptr)
+ *ptr = start;
+ errno = ERANGE;
+ }
+ return 0;
+ }
+ if (neg)
+ val = -val;
+
+ while (*++str != '\0') {
+ int n;
+
+ p = strchr(digits, isascii(*str) && isupper(*str) ? tolower(*str) : *str);
+ if (p == 0)
+ break;
+ n = p - digits;
+ if (n >= base)
+ break;
+ if (neg) {
+ if (-(unsigned long)val > (-(unsigned long)LONG_MIN - n)/base) {
+ val = LONG_MIN;
+ errno = ERANGE;
+ }
+ else
+ val = val*base - n;
+ }
+ else {
+ if (val > (LONG_MAX - n)/base) {
+ val = LONG_MAX;
+ errno = ERANGE;
+ }
+ else
+ val = val*base + n;
+ }
+ }
+
+ if (ptr)
+ *ptr = str;
+
+ return val;
+}
diff --git a/gnu/usr.bin/groff/libgroff/tmpfile.cc b/gnu/usr.bin/groff/libgroff/tmpfile.cc
new file mode 100644
index 000000000000..bd6f8ad69ab6
--- /dev/null
+++ b/gnu/usr.bin/groff/libgroff/tmpfile.cc
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+
+extern "C" {
+ // Sun's stdlib.h fails to declare this.
+ char *mktemp(char *);
+ int mkstemp(char *);
+}
+
+// If this is set, create temporary files there
+#define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR"
+// otherwise if this is set, create temporary files there
+#define TMPDIR_ENVVAR "TMPDIR"
+// otherwise create temporary files here.
+#define DEFAULT_TMPDIR "/tmp"
+// Use this as the prefix for temporary filenames.
+#define TMPFILE_PREFIX "groff"
+
+// Open a temporary file with fatal error on failure.
+
+FILE *xtmpfile()
+{
+ const char *dir = getenv(GROFF_TMPDIR_ENVVAR);
+ if (!dir) {
+ dir = getenv(TMPDIR_ENVVAR);
+ if (!dir)
+ dir = DEFAULT_TMPDIR;
+ }
+
+ const char *p = strrchr(dir, '/');
+ int needs_slash = (!p || p[1]);
+ char *templ = new char[strlen(dir) + needs_slash
+ + sizeof(TMPFILE_PREFIX) - 1 + 6 + 1];
+ strcpy(templ, dir);
+ if (needs_slash)
+ strcat(templ, "/");
+ strcat(templ, TMPFILE_PREFIX);
+ strcat(templ, "XXXXXX");
+
+#ifdef HAVE_MKSTEMP
+ errno = 0;
+ int fd = mkstemp(templ);
+ if (fd < 0)
+ fatal("cannot create temporary file: %1", strerror(errno));
+ errno = 0;
+ FILE *fp = fdopen(fd, "w+");
+ if (!fp)
+ fatal("fdopen: %1", strerror(errno));
+#else /* not HAVE_MKSTEMP */
+ if (!mktemp(templ) || !templ[0])
+ fatal("cannot create file name for temporary file");
+ errno = 0;
+ FILE *fp = fopen(templ, "w+");
+ if (!fp)
+ fatal("cannot open `%1': %2", templ, strerror(errno));
+#endif /* not HAVE_MKSTEMP */
+ if (unlink(templ) < 0)
+ error("cannot unlink `%1': %2", templ, strerror(errno));
+ a_delete templ;
+ return fp;
+}
+
+#if 0
+// If you're not running Unix, the following will do:
+FILE *xtmpfile()
+{
+ FILE *fp = tmpfile();
+ if (!fp)
+ fatal("couldn't create temporary file");
+ return fp;
+}
+#endif
diff --git a/gnu/usr.bin/groff/lkbib/Makefile b/gnu/usr.bin/groff/lkbib/Makefile
new file mode 100644
index 000000000000..5650a35e5254
--- /dev/null
+++ b/gnu/usr.bin/groff/lkbib/Makefile
@@ -0,0 +1,12 @@
+# Makefile for lkbib
+
+PROG= lkbib
+SRCS= lkbib.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBBIB) $(LIBGROFF) -lm
+DPADD+= $(LIBBIB) $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/lkbib/lkbib.1 b/gnu/usr.bin/groff/lkbib/lkbib.1
new file mode 100644
index 000000000000..efbc9aaa18ed
--- /dev/null
+++ b/gnu/usr.bin/groff/lkbib/lkbib.1
@@ -0,0 +1,90 @@
+.\" -*- nroff -*-
+.ds g \" empty
+.ds G \" empty
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH LKBIB 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+lkbib \- search bibliographic databases
+.SH SYNOPSIS
+.B lkbib
+[
+.B \-v
+]
+[
+.BI \-i fields
+]
+[
+.BI \-p filename
+]
+[
+.BI \-t n
+]
+.IR key \|.\|.\|.
+.SH DESCRIPTION
+.B lkbib
+searches bibliographic databases for references that contain the keys
+.IR key \|.\|.\|.
+and prints any references found on the standard output.
+.B lkbib
+will search any databases given by
+.B \-p
+options, and then a default database.
+The default database is taken from the
+.SB REFER
+environment variable if it is set,
+otherwise it is
+.BR /usr/share/dict/papers/Ind .
+For each database
+.I filename
+to be searched,
+if an index
+.IB filename .i
+created by
+.BR indxbib (1)
+exists, then it will be searched instead;
+each index can cover multiple databases.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-p filename
+Search
+.IR filename .
+Multiple
+.B \-p
+options can be used.
+.TP
+.BI \-i string
+When searching files for which no index exists,
+ignore the contents of fields whose names are in
+.IR string .
+.TP
+.BI \-t n
+Only require the first
+.I n
+characters of keys to be given.
+Initially
+.I n
+is 6.
+.SH ENVIRONMENT
+.TP \w'\fBREFER'u+2n
+.SB REFER
+Default database.
+.SH FILES
+.Tp \w'\fB/usr/share/dict/papers/Ind'u+2n
+.B /usr/share/dict/papers/Ind
+Default database to be used if the
+.SB REFER
+environment variable is not set.
+.IB filename .i
+Index files.
+.SH "SEE ALSO"
+.BR refer (1),
+.BR lookbib (1),
+.BR indxbib (1)
diff --git a/gnu/usr.bin/groff/lkbib/lkbib.cc b/gnu/usr.bin/groff/lkbib/lkbib.cc
new file mode 100644
index 000000000000..a6d3e8fee52c
--- /dev/null
+++ b/gnu/usr.bin/groff/lkbib/lkbib.cc
@@ -0,0 +1,122 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+
+#include "defs.h"
+#include "refid.h"
+#include "search.h"
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-nv] [-p database] [-i XYZ] [-t N] keys ...\n",
+ program_name);
+ exit(1);
+}
+
+main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int search_default = 1;
+ search_list list;
+ int opt;
+ while ((opt = getopt(argc, argv, "nvVi:t:p:")) != EOF)
+ switch (opt) {
+ case 'V':
+ verify_flag = 1;
+ break;
+ case 'n':
+ search_default = 0;
+ break;
+ case 'i':
+ linear_ignore_fields = optarg;
+ break;
+ case 't':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 10);
+ if (n == 0 && ptr == optarg) {
+ error("bad integer `%1' in `t' option", optarg);
+ break;
+ }
+ if (n < 1)
+ n = 1;
+ linear_truncate_len = int(n);
+ break;
+ }
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU lkbib version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'p':
+ list.add_file(optarg);
+ break;
+ case '?':
+ usage();
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ usage();
+ char *filename = getenv("REFER");
+ if (filename)
+ list.add_file(filename);
+ else if (search_default)
+ list.add_file(DEFAULT_INDEX, 1);
+ if (list.nfiles() == 0)
+ fatal("no databases");
+ int total_len = 0;
+ for (int i = optind; i < argc; i++)
+ total_len += strlen(argv[i]);
+ total_len += argc - optind - 1 + 1; // for spaces and '\0'
+ char *buffer = new char[total_len];
+ char *ptr = buffer;
+ for (i = optind; i < argc; i++) {
+ if (i > optind)
+ *ptr++ = ' ';
+ strcpy(ptr, argv[i]);
+ ptr = strchr(ptr, '\0');
+ }
+ search_list_iterator iter(&list, buffer);
+ const char *start;
+ int len;
+ for (int count = 0; iter.next(&start, &len); count++) {
+ if (fwrite(start, 1, len, stdout) != len)
+ fatal("write error on stdout: %1", strerror(errno));
+ // Can happen for last reference in file.
+ if (start[len - 1] != '\n')
+ putchar('\n');
+ putchar('\n');
+ }
+ exit(!count);
+}
diff --git a/gnu/usr.bin/groff/lookbib/Makefile b/gnu/usr.bin/groff/lookbib/Makefile
new file mode 100644
index 000000000000..f0bdd17575a3
--- /dev/null
+++ b/gnu/usr.bin/groff/lookbib/Makefile
@@ -0,0 +1,12 @@
+# Makefile for lookbib
+
+PROG= lookbib
+SRCS= lookbib.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBBIB) $(LIBGROFF) -lm
+DPADD+= $(LIBBIB) $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/lookbib/lookbib.1 b/gnu/usr.bin/groff/lookbib/lookbib.1
new file mode 100644
index 000000000000..e0708ce3f02f
--- /dev/null
+++ b/gnu/usr.bin/groff/lookbib/lookbib.1
@@ -0,0 +1,58 @@
+.\" -*- nroff -*-
+.TH LOOKBIB 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+lookbib \- search bibliographic databases
+.SH SYNOPSIS
+.B lookbib
+[
+.B \-v
+]
+[
+.BI \-i string
+]
+[
+.BI \-t n
+]
+.IR filename \|.\|.\|.
+.SH DESCRIPTION
+lookbib prints a prompt on the standard error (unless the standard input is not a terminal),
+reads from the standard input a line containing a set of keywords,
+searches the bibliographic databases
+.IR filename \|.\|.\|.
+for references containing those keywords,
+prints any references found on the standard output,
+and repeats this process until the end of input.
+For each database
+.I filename
+to be searched,
+if an index
+.IB filename .i
+created by
+.BR indxbib (1)
+exists, then it will be searched instead;
+each index can cover multiple databases.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-i string
+When searching files for which no index exists,
+ignore the contents of fields whose names are in
+.IR string .
+.TP
+.BI \-t n
+Only require the first
+.I n
+characters of keys to be given.
+Initially
+.I n
+is 6.
+.SH FILES
+.TP \w'\fIfilename\fB.i'u+2n
+.IB filename .i
+Index files.
+.SH "SEE ALSO"
+.BR refer (1),
+.BR lkbib (1),
+.BR indxbib (1)
diff --git a/gnu/usr.bin/groff/lookbib/lookbib.cc b/gnu/usr.bin/groff/lookbib/lookbib.cc
new file mode 100644
index 000000000000..fcb3277353bc
--- /dev/null
+++ b/gnu/usr.bin/groff/lookbib/lookbib.cc
@@ -0,0 +1,127 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+#include "cset.h"
+
+#include "refid.h"
+#include "search.h"
+
+extern "C" {
+ int isatty(int);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-v] [-i XYZ] [-t N] database ...\n",
+ program_name);
+ exit(1);
+}
+
+main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ while ((opt = getopt(argc, argv, "vVi:t:")) != EOF)
+ switch (opt) {
+ case 'V':
+ verify_flag = 1;
+ break;
+ case 'i':
+ linear_ignore_fields = optarg;
+ break;
+ case 't':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 10);
+ if (n == 0 && ptr == optarg) {
+ error("bad integer `%1' in `t' option", optarg);
+ break;
+ }
+ if (n < 1)
+ n = 1;
+ linear_truncate_len = int(n);
+ break;
+ }
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU lookbib version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ usage();
+ search_list list;
+ for (int i = optind; i < argc; i++)
+ list.add_file(argv[i]);
+ if (list.nfiles() == 0)
+ fatal("no databases");
+ char line[1024];
+ int interactive = isatty(fileno(stdin));
+ for (;;) {
+ if (interactive) {
+ fputs("> ", stderr);
+ fflush(stderr);
+ }
+ if (!fgets(line, sizeof(line), stdin))
+ break;
+ char *ptr = line;
+ while (csspace(*ptr))
+ ptr++;
+ if (*ptr == '\0')
+ continue;
+ search_list_iterator iter(&list, line);
+ const char *start;
+ int len;
+ for (int count = 0; iter.next(&start, &len); count++) {
+ if (fwrite(start, 1, len, stdout) != len)
+ fatal("write error on stdout: %1", strerror(errno));
+ // Can happen for last reference in file.
+ if (start[len - 1] != '\n')
+ putchar('\n');
+ putchar('\n');
+ }
+ fflush(stdout);
+ if (interactive) {
+ fprintf(stderr, "%d found\n", count);
+ fflush(stderr);
+ }
+ }
+ if (interactive)
+ putc('\n', stderr);
+ return 0;
+}
+
diff --git a/gnu/usr.bin/groff/man/Makefile b/gnu/usr.bin/groff/man/Makefile
new file mode 100644
index 000000000000..66dbd20bdfe0
--- /dev/null
+++ b/gnu/usr.bin/groff/man/Makefile
@@ -0,0 +1,7 @@
+# Makefile for manpages
+
+MAN5= groff_font.5 groff_out.5
+MAN7= groff_char.7
+
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/man/groff_char.7 b/gnu/usr.bin/groff/man/groff_char.7
new file mode 100644
index 000000000000..ac023e8b3b2c
--- /dev/null
+++ b/gnu/usr.bin/groff/man/groff_char.7
@@ -0,0 +1,545 @@
+.\" -*- nroff -*-
+.\" For best results, print this with groff.
+.TH GROFF_CHAR 7 "31 May 1993" "Groff Version 1.08"
+.ds aq \(aq
+.ie !\n(.g .if '\(aq'' .ds aq \'
+.el \{\
+. tr \(aq\(aq
+. if !c\(aq .ds aq \'
+.\}
+.if !\n(.g .ig
+.\" .Ac accented-char accent char
+.de Ac
+.char \\$1 \\$3\
+\k[acc]\
+\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\
+\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\
+\\$2\
+\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\
+\h'|\\\\n[acc]u'
+.hcode \\$1\\$3
+..
+.Ac \(vc \(ah c
+.Ac \(vC \(ah C
+.SH NAME
+groff_char \- groff character names
+.SH DESCRIPTION
+This manual page lists the standard
+.B groff
+input characters.
+Only the characters that are available for the device that
+is being used to print this manual page will be displayed.
+The
+.I "Input code"
+column applies to characters which can be
+input with a single character, and gives the ISO Latin-1 code
+of that input character.
+The
+.I "PostScript name\"
+column gives the usual PostScript name of the output character.
+.LP
+The ISO Latin-1 no-break space (code 0240 octal) is equivalent to
+.BR \e (space).
+All other ISO Latin-1 characters print as themselves with the following
+exceptions:
+.B \`
+prints as `,
+.B \*(aq
+prints as ';
+the corresponding ISO Latin-1 characters can be obtained with
+.B \e`
+and
+.BR \e(aq .
+The ISO Latin-1 `Hyphen, Minus Sign' (code 45) prints as a hyphen;
+a minus sign can be obtained with
+.BR \e- .
+The ISO Latin-1 `Tilde' (code 126) prints as ~;
+the larger glyph can be obtained with
+.BR \e(ti .
+The ISO Latin-1 `Circumflex Accent' (code 94) prints as ^;
+a larger glyph can be obtained with
+.BR \e(ha .
+.sp
+'nf
+.nr Sp 3n
+.ta \w'\fIOutput'u+\n(Spu +\w'\fIInput'u+\n(Spu +\w'\fIInput'u+\n(Spu \
++\w'periodcentered'u+\n(Spu
+.de C0
+.C \\$1 "" \\$1 \\$2 "\\$3"
+..
+.de C1
+.C \e\\$1 "" \\\\\\$1 \\$2 "\\$3"
+..
+.de C2
+.C \e(\\$1 "" \\(\\$1 \\$2 "\\$3"
+..
+.if !\n(.g .ig
+.de CD
+.C \[char\\$1] \\$1 \[char\\$1] \\$2 "\\$3"
+..
+.do fspecial CR R
+.\" input-name decimal-code output-name ps-name description
+.if !\n(.g .ig
+.de C
+.if c\\$3 \{\
+.ft CR
+.tr `\`'\*(aq
+.in 0
+.di CH
+\&\\$1
+.br
+.di
+.in
+.ft
+.ds CH \\*(CH\
+.tr ``''
+\&\\$3\t\\*(CH\t\\$2\t\\$4\t\\$5
+.\}
+..
+.if \n(.g .ig
+.de C
+.if !'\\$3'' \{\
+.ft B
+.tr `\`'\*(aq
+.in 0
+.di CH
+\&\\$1
+.br
+.di
+.in
+.ft
+.ds CH \\*(CH\
+.tr ``''
+\&\\$3\t\\*(CH\t\\$2\t\\$4\t\\$5
+.\}
+..
+.wh \n(nlu+\n(.tu-\n(.Vu Fo
+.de Fo
+'bp
+.He
+..
+.de He
+.ft I
+Output Input Input PostScript Notes
+ name code name
+.ft
+.LP
+'nf
+..
+.He
+.CD 33 exclam
+.CD 34 quotedbl
+.CD 35 numbersign
+.CD 36 dollar
+.CD 37 percent
+.CD 38 ampersand
+.CD 39 quoteright
+.CD 40 parenleft
+.CD 41 parenright
+.CD 42 asterisk
+.CD 43 plus
+.CD 44 comma
+.CD 45 hyphen
+.CD 46 period
+.CD 47 slash
+.CD 58 colon
+.CD 59 semicolon
+.CD 60 less
+.CD 61 equal
+.CD 62 greater
+.CD 63 question
+.CD 64 at
+.CD 91 bracketleft
+.CD 92 backslash
+.CD 93 bracketright
+.CD 94 circumflex "circumflex accent"
+.CD 95 underscore
+.CD 96 quoteleft
+.CD 123 braceleft
+.CD 124 bar
+.CD 125 braceright
+.CD 126 tilde "tilde accent"
+.CD 161 exclamdown
+.CD 162 cent
+.CD 163 sterling
+.CD 164 currency
+.CD 165 yen
+.CD 166 brokenbar
+.CD 167 section
+.CD 168 dieresis
+.CD 169 copyright
+.CD 170 ordfeminine
+.CD 171 guillemotleft
+.CD 172 logicalnot
+.CD 173 hyphen
+.CD 174 registered
+.CD 175 macron
+.CD 176 degree
+.CD 177 plusminus
+.CD 178 twosuperior
+.CD 179 threesuperior
+.CD 180 acute "acute accent"
+.CD 181 mu
+.CD 182 paragraph
+.CD 183 periodcentered
+.CD 184 cedilla
+.CD 185 onesuperior
+.CD 186 ordmasculine
+.CD 187 guillemotright
+.CD 188 onequarter
+.CD 189 onehalf
+.CD 190 threequarters
+.CD 191 questiondown
+.CD 192 Agrave
+.CD 193 Aacute
+.CD 194 Acircumflex
+.CD 195 Atilde
+.CD 196 Adieresis
+.CD 197 Aring
+.CD 198 AE
+.CD 199 Ccedilla
+.CD 200 Egrave
+.CD 201 Eacute
+.CD 202 Ecircumflex
+.CD 203 Edieresis
+.CD 204 Igrave
+.CD 205 Iacute
+.CD 206 Icircumflex
+.CD 207 Idieresis
+.CD 208 Eth
+.CD 209 Ntilde
+.CD 210 Ograve
+.CD 211 Oacute
+.CD 212 Ocircumflex
+.CD 213 Otilde
+.CD 214 Odieresis
+.CD 215 multiply
+.CD 216 Oslash
+.CD 217 Ugrave
+.CD 218 Uacute
+.CD 219 Ucircumflex
+.CD 220 Udieresis
+.CD 221 Yacute
+.CD 222 Thorn
+.CD 223 germandbls
+.CD 224 agrave
+.CD 225 aacute
+.CD 226 acircumflex
+.CD 227 atilde
+.CD 228 adieresis
+.CD 229 aring
+.CD 230 ae
+.CD 231 ccedilla
+.CD 232 egrave
+.CD 233 eacute
+.CD 234 ecircumflex
+.CD 235 edieresis
+.CD 236 igrave
+.CD 237 iacute
+.CD 238 icircumflex
+.CD 239 idieresis
+.CD 240 eth
+.CD 241 ntilde
+.CD 242 ograve
+.CD 243 oacute
+.CD 244 ocircumflex
+.CD 245 otilde
+.CD 246 odieresis
+.CD 247 divide
+.CD 248 oslash
+.CD 249 ugrave
+.CD 250 uacute
+.CD 251 ucircumflex
+.CD 252 udieresis
+.CD 253 yacute
+.CD 254 thorn
+.CD 255 ydieresis
+.C2 -D Eth "Icelandic uppercase eth"
+.C2 Sd eth "Icelandic lowercase eth"
+.C2 TP Thorn "Icelandic uppercase thorn"
+.C2 Tp thorn "Icelandic lowercase thorn"
+.C2 AE AE
+.C2 ae ae
+.C2 OE OE
+.C2 oe oe
+.C2 IJ IJ "Dutch IJ ligature"
+.C2 ij ij "Dutch ij ligature"
+.C2 ss germandbls
+.C2 'A Aacute
+.C2 'C Cacute
+.C2 'E Eacute
+.C2 'I Iacute
+.C2 'O Oacute
+.C2 'U Uacute
+.C2 'a aacute
+.C2 'c cacute
+.C2 'e eacute
+.C2 'i iacute
+.C2 'o oacute
+.C2 'u uacute
+.C2 :A Adieresis
+.C2 :E Edieresis
+.C2 :I Idieresis
+.C2 :O Odieresis
+.C2 :U Udieresis
+.C2 :Y Ydieresis
+.C2 :a adieresis
+.C2 :e edieresis
+.C2 :i idieresis
+.C2 :o odieresis
+.C2 :u udieresis
+.C2 :y ydieresis
+.C2 ^A Acircumflex
+.C2 ^E Ecircumflex
+.C2 ^I Icircumflex
+.C2 ^O Ocircumflex
+.C2 ^U Ucircumflex
+.C2 ^a acircumflex
+.C2 ^e ecircumflex
+.C2 ^i icircumflex
+.C2 ^o ocircumflex
+.C2 ^u ucircumflex
+.C2 `A Agrave
+.C2 `E Egrave
+.C2 `I Igrave
+.C2 `O Ograve
+.C2 `U Ugrave
+.C2 `a agrave
+.C2 `e egrave
+.C2 `i igrave
+.C2 `o ograve
+.C2 `u ugrave
+.C2 ~A Atilde
+.C2 ~N Ntilde
+.C2 ~O Otilde
+.C2 ~a atilde
+.C2 ~n ntilde
+.C2 ~o otilde
+.C2 vS Scaron
+.C2 vs scaron
+.C2 vZ Zcaron
+.C2 vz zcaron
+.C2 ,C Ccedilla
+.C2 ,c ccedilla
+.C2 /L Lslash "Polish L with a slash"
+.C2 /l lslash "Polish l with a slash"
+.C2 /O Oslash
+.C2 /o oslash
+.C2 oA Aring
+.C2 oa aring
+.C2 a" hungarumlaut "Hungarian umlaut"
+.C2 a- macron "macron or bar accent"
+.C2 a. dotaccent "dot accent"
+.C2 a^ circumflex "circumflex accent"
+.C2 aa acute "acute accent"
+.C2 ga grave "grave accent"
+.C2 ab breve "breve accent"
+.C2 ac cedilla "cedilla accent"
+.C2 ad dieresis "umlaut or dieresis"
+.C2 ah caron "h\('a\(vcek accent"
+.C2 ao ring "ring or circle accent"
+.C2 a~ tilde "tilde accent"
+.C2 ho ogonek "hook or ogonek accent"
+.C2 .i dotlessi "i without a dot"
+.C2 .j dotlessj "j without a dot"
+.C2 Cs currency "Scandinavian currency sign"
+.C2 Do dollar
+.C2 Po sterling
+.C2 Ye yen
+.C2 Fn florin
+.C2 ct cent
+.C2 Fo guillemotleft
+.C2 Fc guillemotright
+.C2 fo guilsinglleft
+.C2 fc guilsinglright
+.C2 r! exclamdown
+.C2 r? questiondown
+.C2 ff ff "ff ligature"
+.C2 fi fi "fi ligature"
+.C2 fl fl "fl ligature"
+.C2 Fi ffi "ffi ligature"
+.C2 Fl ffl "ffl ligature"
+.C2 OK \& "check mark, tick"
+.C2 Of ordfeminine
+.C2 Om ordmasculine
+.C2 S1 onesuperior
+.C2 S2 twosuperior
+.C2 S3 threesuperior
+.C2 <- arrowleft
+.C2 -> arrowright
+.C2 <> arrowboth "horizontal double-headed arrow"
+.C2 da arrowdown
+.C2 ua arrowup
+.C2 va \& "vertical double-headed arrow"
+.C2 lA arrowdblleft
+.C2 rA arrowdblright
+.C2 hA arrowdblboth "horizontal double-headed double arrow"
+.C2 dA arrowdbldown
+.C2 uA arrowdblup
+.C2 vA \& "vertical double-headed double arrow"
+.C2 ba bar
+.C2 bb brokenbar
+.C2 br br "box rule with traditional troff metrics"
+.C2 ru ru "baseline rule"
+.C2 ul ul "underline with traditional troff metrics"
+.C2 bv bv "bold vertical"
+.C2 bs bell
+.C2 ci circle
+.C2 bu bullet
+.C2 co copyright
+.C2 rg registered
+.C2 tm trademark
+.C2 dd daggerdbl "double dagger sign"
+.C2 dg dagger
+.C2 ps paragraph
+.C2 sc section
+.C2 de degree
+.C2 em emdash "em dash"
+.C2 en endash "en dash"
+.C2 %0 perthousand "per thousand, per mille sign"
+.C2 12 onehalf
+.C2 14 onequarter
+.C2 34 threequarters
+.C2 f/ fraction "bar for fractions"
+.C2 fm minute "footmark, prime"
+.C2 sd second
+.C2 ha asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+.C2 ti asciitilde "\s-2ASCII\s0 tilde, large tilde"
+.C2 hy hyphen
+.C2 lB bracketleft
+.C2 rB bracketright
+.C2 lC braceleft
+.C2 rC braceright
+.C2 la angleleft "left angle bracket"
+.C2 ra angleright "right angle bracket"
+.C2 lh handleft
+.C2 rh handright
+.C2 Bq quotedblbase "low double comma quote"
+.C2 bq quotesinglbase "low single comma quote"
+.C2 lq quotedblleft
+.C2 rq quotedblright
+.C2 oq quoteleft "single open quote"
+.C2 aq quotesingle "apostrophe quote"
+.C2 or bar
+.C2 at at
+.C1 - minus "minus sign from current font"
+.C2 sh numbersign
+.C2 sl slash
+.C2 rs backslash
+.C2 sq square
+.C2 3d therefore
+.C2 tf therefore
+.C2 *A Alpha
+.C2 *B Beta
+.C2 *C Xi
+.C2 *D Delta
+.C2 *E Epsilon
+.C2 *F Phi
+.C2 *G Gamma
+.C2 *H Theta
+.C2 *I Iota
+.C2 *K Kappa
+.C2 *L Lambda
+.C2 *M Mu
+.C2 *N Nu
+.C2 *O Omicron
+.C2 *P Pi
+.C2 *Q Psi
+.C2 *R Rho
+.C2 *S Sigma
+.C2 *T Tau
+.C2 *U Upsilon
+.C2 *W Omega
+.C2 *X Chi
+.C2 *Y Eta
+.C2 *Z Zeta
+.C2 *a alpha
+.C2 *b beta
+.C2 *c xi
+.C2 *d delta
+.C2 *e epsilon
+.C2 *f phi
+.C2 +f phi1 "variant phi"
+.C2 *g gamma
+.C2 *h theta
+.C2 +h theta1 "variant theta"
+.C2 *i iota
+.C2 *k kappa
+.C2 *l lambda
+.C2 *m mu
+.C2 *n nu
+.C2 *o omicron
+.C2 *p pi
+.C2 +p omega1 "variant pi, looking like omega"
+.C2 *q psi
+.C2 *r rho
+.C2 *s sigma
+.C2 *t tau
+.C2 *u upsilon
+.C2 *w omega
+.C2 *x chi
+.C2 *y eta
+.C2 *z zeta
+.C2 ts sigma1 "terminal sigma"
+.C2 ~~ approxequal
+.C2 ~= approxequal
+.C2 != notequal
+.C2 ** asteriskmath
+.C2 -+ minusplus
+.C2 +- plusminus
+.C2 <= lessequal
+.C2 == equivalence
+.C2 =~ congruent
+.C2 >= greaterequal
+.C2 AN logicaland
+.C2 OR logicalor
+.C2 no logicalnot
+.C2 te existential "there exists, existential quantifier"
+.C2 fa universal "for all, universal quantifier"
+.C2 Ah aleph
+.C2 Im Ifraktur "Fraktur I, imaginary"
+.C2 Re Rfraktur "Fraktur R, real"
+.C2 if infinity
+.C2 md dotmath
+.C2 mo element
+.C2 mu multiply
+.C2 nc notpropersuperset
+.C2 ne notequivalence
+.C2 nm notelement
+.C2 pl plusmath "plus sign in special font"
+.C2 eq equalmath "equals sign in special font"
+.C2 pt proportional
+.C2 pp perpendicular
+.C2 sb propersubset
+.C2 sp propersuperset
+.C2 ib reflexsubset
+.C2 ip reflexsuperset
+.C2 ap similar
+.C2 pd partialdiff "partial differentiation sign"
+.C2 c* circlemultiply "multiply sign in a circle"
+.C2 c+ circleplus "plus sign in a circle"
+.C2 ca intersection "intersection, cap"
+.C2 cu union "union, cup"
+.C2 di divide "division sign"
+.C2 -h hbar
+.C2 gr gradient
+.C2 es emptyset
+.C2 CL club "club suit"
+.C2 SP spade "spade suit"
+.C2 HE heart "heart suit"
+.C2 DI diamond "diamond suit"
+.C2 CR carriagereturn "carriage return symbol"
+.C2 st suchthat
+.C2 /_ angle
+.C2 << "" "much less"
+.C2 >> "" "much greater"
+.C2 wp weierstrass "Weierstrass p"
+.C2 lz lozenge
+.C2 an arrowhorizex "horizontal arrow extension"
+.ch Fo
+.SH "SEE ALSO"
+.BR groff (1)
+.br
+.IR "An extension to the troff character set for Europe" ,
+E.G. Keizer, K.J. Simonsen, J. Akkerhuis,
+EUUG Newsletter, Volume 9, No. 2, Summer 1989
diff --git a/gnu/usr.bin/groff/man/groff_font.5 b/gnu/usr.bin/groff/man/groff_font.5
new file mode 100644
index 000000000000..78afa2e2c7cc
--- /dev/null
+++ b/gnu/usr.bin/groff/man/groff_font.5
@@ -0,0 +1,351 @@
+.\" -*- nroff -*-
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROFF_FONT 5 "24 September 1992" "Groff Version 1.08"
+.SH NAME
+groff_font \- format of groff device and font description files
+.SH DESCRIPTION
+The groff font format is roughly a superset of the ditroff
+font format.
+Unlike the ditroff font format, there is no associated binary
+format.
+The font files for device
+.I name
+are stored in a directory
+.BI dev name.
+There are two types of file: a
+device description file called
+.B DESC
+and for each font
+.I F
+a font file called
+.IR F .
+These are text files;
+there is no associated binary format.
+.SS DESC file format
+The DESC file can contain the following types of line:
+.TP
+.BI res\ n
+There are
+.I n
+machine units per inch.
+.TP
+.BI hor\ n
+The horizontal resolution is
+.I n
+machine units.
+.TP
+.BI vert\ n
+The vertical resolution is
+.I n
+machine units.
+.TP
+.BI sizescale\ n
+The scale factor for pointsizes.
+By default this has a value of 1.
+One
+.I
+scaled point
+is equal to
+one
+.RI point/ n .
+The arguments to the
+.B unitwidth
+and
+.B sizes
+commands are given in scaled points.
+.TP
+.BI unitwidth\ n
+Quantities in the font files are given in machine units
+for fonts whose point size is
+.I n
+scaled points.
+.TP
+.B tcommand
+This means that the postprocessor can handle the
+.B t
+and
+.B u
+output commands.
+.TP
+.BI sizes\ s1\ s2\|.\|.\|.\|sn\ 0
+This means that the device has fonts at
+.IR s1 ,
+.IR s2 ,\|.\|.\|.\| sn
+scaled points.
+The list of sizes must be terminated by a
+.BR 0 .
+Each
+.BI s i
+can also be a range of sizes
+.IR m \- n .
+The list can extend over more than one line.
+.TP
+.BI styles\ S1\ S2\|.\|.\|.\|Sm
+The first
+.I m
+font positions will be associated with styles
+.IR S1\|.\|.\|.\|Sm .
+.TP
+.BI fonts\ n\ F1\ F2\ F3\|.\|.\|.\|Fn
+Fonts
+.I F1\|.\|.\|.\|Fn
+will be mounted in the font positions
+.IR m +1,\|.\|.\|., m + n
+where
+.I m
+is the number of styles.
+This command may extend over more than one line.
+A font name of
+.B 0
+will cause no font to be mounted on the corresponding font position.
+.TP
+.BI family\ fam
+The default font family is
+.IR fam .
+.TP
+.B charset
+This line and everything following in the file are ignored.
+It is allowed for the sake of backwards compatibility.
+.LP
+The res, unitwidth, fonts and sizes lines are compulsory.
+Other commands are ignored by
+.B troff
+but may be used by postprocessors to store arbitrary information
+about the device in the DESC file.
+.SS Font file format
+A font file has two sections. The first section is a sequence
+of lines each containing a sequence of blank delimited
+words; the first word in the line is a key, and subsequent
+words give a value for that key.
+.TP
+.BI name\ F
+The name of the font is
+.IR F .
+.TP
+.BI spacewidth\ n
+The normal width of a space is
+.IR n .
+.TP
+.BI slant\ n
+The characters of the font have a slant of
+.I n
+degrees. (Positive means forward.)
+.TP
+.BI ligatures\ lig1\ lig2\|.\|.\|.\|lign\ \fR[ 0 \fR]
+Characters
+.IR lig1 ,
+.IR lig2 ,\|.\|.\|., lign
+are ligatures; possible ligatures are
+.BR ff ,
+.BR fi ,
+.BR fl
+and
+.BR ffl .
+For backwards compatibiliy, the list of ligatures may be terminated
+with a
+.BR 0.
+The list of ligatures may not extend over more than one line.
+.TP
+.B special
+The font is
+.IR special ;
+this means that when a character is requested that is not present in
+the current font, it will be searched for in any special fonts that
+are mounted.
+.LP
+Other commands are ignored by
+.B troff
+but may be used by postprocessors to store arbitrary information
+about the font in the font file.
+.LP
+The first section can contain comments which start with the
+.B #
+character and extend to the end of a line.
+.LP
+The second section contains one or two subsections.
+It must contain a
+.I charset
+subsection
+and it may also contain a
+.I kernpairs
+subsection.
+These subsections can appear in any order.
+Each subsection starts with a word on a line by itself.
+.LP
+The word
+.B charset
+starts the charset subsection.
+The
+.B charset
+line is followed by a sequence of lines.
+Each line gives information for one character.
+A line comprises a number of fields separated
+by blanks or tabs. The format is
+.IP
+.I
+name metrics type code comment
+.LP
+.I name
+identifies the character:
+if
+.I name
+is a single character
+.I c
+then it corresponds to the groff input character
+.IR c ;
+if it is of the form
+.BI \e c
+where c is a single character, then it
+corresponds to the groff input character
+.BI \e c\fR;
+otherwise it corresponds to the groff input character
+.BI \e[ name ]
+(if it is exactly two characters
+.I xx
+it can be entered as
+.BI \e( xx\fR.)
+Groff supports eight bit characters; however some utilities
+has difficulties with eight bit characters.
+For this reason, there is a convention that the name
+.BI char n
+is equivalent to the single character whose code is
+.I n .
+For example,
+.B char163
+would be equivalent to the character with code 163
+which is the pounds sterling sign in ISO Latin-1.
+The name
+.B \-\-\-
+is special and indicates that the character is unnamed;
+such characters can only be used by means of the
+.B \eN
+escape sequence in
+.BR troff .
+.LP
+The
+.I type
+field gives the character type:
+.TP
+1
+means the character has an descender, for example, p;
+.TP
+2
+means the character has an ascender, for example, b;
+.TP
+3
+means the character has both an ascender and a descender, for example,
+(.
+.LP
+The
+.I code
+field gives the code which the postprocessor uses to print the character.
+The character can also be input to groff using this code by means of the
+.B \eN
+escape sequence.
+The code can be any integer.
+If it starts with a
+.B 0
+it will be interpreted as octal;
+if it starts with
+.B 0x
+or
+.B 0X
+it will be intepreted as hexdecimal.
+.LP
+Anything on the line after the code field will be ignored.
+.LP
+The
+.I metrics
+field has the form:
+.IP
+.IR width [\fB, height [\fB, depth [\fB, italic_correction [\fB, \
+left_italic_correction [\fB, subscript_correction ]]]]]
+.LP
+There must not be any spaces between these subfields.
+Missing subfields are assumed to be 0.
+The subfields are all decimal integers.
+Since there is no associated binary format, these
+values are not required to fit into a variable of type
+.B char
+as they are in ditroff.
+The
+.I width
+subfields gives the width of the character.
+The
+.I height
+subfield gives the height of the character (upwards is positive);
+if a character does not extend above the baseline, it should be
+given a zero height, rather than a negative height.
+The
+.I depth
+subfield gives the depth of the character, that is, the distance
+below the lowest point below the baseline to which the
+character extends (downwards is positive);
+if a character does not extend below above the baseline, it should be
+given a zero depth, rather than a negative depth.
+The
+.I italic_correction
+subfield gives the amount of space that should be added after the
+character when it is immediately to be followed by a character
+from a roman font.
+The
+.I left_italic_correction
+subfield gives the amount of space that should be added before the
+character when it is immediately to be preceded by a character
+from a roman font.
+The
+.I subscript_correction
+gives the amount of space that should be added after a character
+before adding a subscript.
+This should be less than the italic correction.
+.LP
+A line in the charset section can also have the format
+.IP
+.I
+name \fB"
+.LP
+This indicates that
+.I name
+is just another name for the character mentioned in the
+preceding line.
+.LP
+The word
+.B kernpairs
+starts the kernpairs section.
+This contains a sequence of lines of the form:
+.IP
+.I
+c1 c2 n
+.LP
+This means that when character
+.I c1
+appears next to character
+.I c2
+the space between them should be increased by
+.IR n .
+Most entries in kernpairs section will have a negative value for
+.IR n .
+.SH FILES
+.Tp \w'/usr/share/groff_font/devname/DESC'u+3n
+.BI /usr/share/groff_font/dev name /DESC
+Device description file for device
+.IR name .
+.TP
+.BI /usr/share/groff_font/dev name / F
+Font file for font
+.I F
+of device
+.IR name .
+.SH "SEE ALSO"
+.BR groff_out (5),
+.BR troff (1).
diff --git a/gnu/usr.bin/groff/man/groff_out.5 b/gnu/usr.bin/groff/man/groff_out.5
new file mode 100644
index 000000000000..1d9303cad0f5
--- /dev/null
+++ b/gnu/usr.bin/groff/man/groff_out.5
@@ -0,0 +1,215 @@
+'\" e
+.\" -*- nroff -*-
+.\" This man page must be preprocessed with eqn.
+.ie \n(.g .ds ic \/
+.el .ds ic \^
+.TH GROFF_OUT 5 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+groff_out \- groff intermediate output format
+.SH DESCRIPTION
+This manual page describes the format output by GNU troff.
+The output format used by GNU troff is very similar to that used
+by Unix device-independent troff. Only the differences are documented
+here.
+.LP
+The argument to the
+.B s
+command is in scaled points (units of
+.IR points/ n ,
+where
+.I n
+is the argument to the
+.B sizescale
+command in the DESC file.)
+The argument to the
+.B x\ Height
+command is also in scaled points.
+.LP
+The first three output commands are guaranteed to be:
+.IP
+.BI x\ T\ device
+.br
+.BI x\ res\ n\ h\ v
+.br
+.B x init
+.LP
+If the
+.B tcommand
+line is present in the DESC file, troff will use the following
+two commands
+.TP
+.BI t xxx
+.I xxx
+is any sequence of characters terminated by a space or a newline;
+the first character should be printed at the current position,
+the the current horizontal position should be increased by
+the width of the first character, and so on for each character.
+The width of the character is that given in the font file,
+appropriately scaled for the current point size, and rounded
+so that it is a multiple of the horizontal resolution.
+Special characters cannot be printed using this command.
+.TP
+.BI u n\ xxx
+This is same as the
+.B t
+command except that after printing each character, the current horizontal
+position is increased by the sum of the width of that character
+and
+.IR n .
+.LP
+Note that single characters can have the eighth bit set, as can the
+names of fonts and special characters.
+.LP
+The names of characters and fonts an be of arbitrary length; drivers
+should not assume that they will be only two characters long.
+.LP
+When a character is to be printed, that character will always be
+in the current font.
+Unlike device-independent troff, it is not necessary
+for drivers to search special fonts to find a character.
+.LP
+The
+.B D
+drawing command has been extended.
+These extensions will only be used by GNU pic if the
+.B \-x
+option is given.
+.TP
+\fBDf \fIn\fR\*(ic\en
+Set the shade of gray to be used for filling solid objects to
+.IR n ;
+.I n
+must be an integer between 0 and 1000, where 0 corresponds solid white
+and 1000 to solid black, and values in between correspond to
+intermediate shades of gray.
+This applies only to solid circles, solid ellipses and solid
+polygons.
+By default, a level of 1000 will be used.
+Whatever color a solid object has, it should completely obscure
+everything beneath it.
+A value greater than 1000 or less than 0 can also be used:
+this means fill with the shade of gray that is currently being used
+for lines and text.
+Normally this will be black, but some drivers may provide
+a way of changing this.
+.TP
+\fBDC \fId\fR\*(ic\en
+Draw a solid circle with a diameter of
+.I d
+with the leftmost point at the current position.
+.TP
+\fBDE \fIdx dy\fR\*(ic\en
+Draw a solid ellipse with a horizontal diameter of
+.I dx
+and a vertical diameter of
+.I dy
+with the leftmost point at the current position.
+.EQ
+delim $$
+.EN
+.TP
+\fBDp\fR $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub n$\en
+Draw a polygon with,
+for $i = 1 ,..., n+1$, the
+.IR i -th
+vertex at the current position
+$+ sum from j=1 to i-1 ( dx sub j , dy sub j )$.
+At the moment,
+GNU pic only uses this command to generate triangles and rectangles.
+.TP
+\fBDP\fR $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub n$\en
+Like
+.B Dp
+but draw a solid rather than outlined polygon.
+.TP
+\fBDt \fIn\fR\*(ic\en
+Set the current line thickness to
+.I n
+machine units.
+Traditionally Unix troff drivers use a line thickness proportional to the current
+point size; drivers should continue to do this if no
+.B Dt
+command has been given, or if a
+.B Dt
+command has been given with a negative value of
+.IR n .
+A zero value of
+.I n
+selects the smallest available line thickness.
+.LP
+A difficulty arises in how the current position should be changed after
+the execution of these commands.
+This is not of great importance since the code generated by GNU pic
+does not depend on this.
+Given a drawing command of the form
+.IP
+\fB\eD\(fm\fIc\fR $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$\(fm
+.LP
+where
+.I c
+is not one of
+.BR c ,
+.BR e ,
+.BR l ,
+.B a
+or
+.BR ~ ,
+Unix troff will treat each of the $x sub i$ as a horizontal quantity,
+and each of the $y sub i$ as a vertical quantity and will assume that
+the width of the drawn object is $sum from i=1 to n x sub i$,
+and that the height is $sum from i=1 to n y sub i$.
+(The assumption about the height can be seen by examining the
+.B st
+and
+.B sb
+registers after using such a
+.B D
+command in a \ew escape sequence.)
+This rule also holds for all the original drawing commands
+with the exception of
+.BR De .
+For the sake of compatibility GNU troff also follows this rule,
+even though it produces an ugly result in the case of the
+.BR Df ,
+.BR Dt ,
+and, to a lesser extent,
+.B DE
+commands.
+Thus after executing a
+.B D
+command of the form
+.IP
+\fBD\fIc\fR $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$\en
+.LP
+the current position should be increased by
+$( sum from i=1 to n x sub i , sum from i=1 to n y sub i )$.
+.LP
+There is a continuation convention which permits the argument to the
+.B x\ X
+command to contain newlines:
+when outputting the argument to the
+.B x\ X
+command, GNU troff
+will follow each newline in the argument with a
+.B +
+character
+(as usual, it will terminate the entire argument with a newline);
+thus if the line after the line containing the
+.B x\ X
+command starts with
+.BR + ,
+then the newline ending the line containing the
+.B x\ X
+command should be treated as part of the argument to the
+.B x\ X
+command,
+the
+.B +
+should be ignored,
+and the part of the line following the
+.B +
+should be treated like the part of the line following the
+.B x\ X
+command.
+.SH "SEE ALSO"
+.BR groff_font (5)
diff --git a/gnu/usr.bin/groff/mm/ChangeLog b/gnu/usr.bin/groff/mm/ChangeLog
new file mode 100644
index 000000000000..389777fa85a9
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/ChangeLog
@@ -0,0 +1,252 @@
+Mon Mar 29 10:53:13 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.16
+ * MUL* now use the previus font and family.
+ * extra blank page at end-of-text eliminated.
+
+Mon Mar 8 10:27:47 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.15
+ * Didn't restore pointsize to current size in .H.
+ * B1/B2 did not work with indent. (MULE and friends)
+ * fixed old problem with trailing empty pages.
+
+Fri Mar 5 15:20:49 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.14
+ * Sigh. Amazing what a missing \} can do. If the string
+ HP was set, then all text disappeared...
+
+Fri Mar 5 14:12:43 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.13
+ * Fixed bug with handling ps/vs in .H. (again, sigh... )
+
+Wed Mar 3 09:21:20 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.12
+ * Line-break added to PGFORM.
+ * added more features to VERBON
+ * .S is not used anymore in H, it caused confusion with
+ normal text, but it will still set .vs.
+ * SK was broken, will now produce the requested number of
+ empty pages.
+ * dotted lines added to LIST OF FIGURES adn friends.
+ Also better linespacing.
+
+Mon Feb 22 12:41:06 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.11
+ * missing left-parenthesis gave ") .sp" when N=4.
+ * N=4 removed user-specified header also.
+ * MOVE made linelength pageoffset wider than wanted.
+ * fixed (again) parenthesis in RP.
+
+Thu Jan 21 12:10:39 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.10
+ * changed PROG_PREFIX to g in the manual-pages.
+ * Better check if new page is needed in .H, when Ej>0.
+ * Usage of variable Lsp now more complete.
+ * Space added in TOC when mark is equal to size.
+ * Usermacro HY moved after font-calulations.
+ * .S used instead of .ps, which will use .vs correct.
+ * Now possible to set Hps1/2 inside HX.
+ * .FD "" 1 is now fixed.
+ * section-page numbering bug fixed.
+ * several bugs in VERBON/OFF fixed.
+
+Tue Dec 8 16:43:15 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.09
+ * N==4 gives no default header
+
+Sat Nov 21 14:28:20 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.08
+ * Escape-character disabled between
+ VERBON/VERBOFF (turned on by an argument).
+ Pointsize and fontchange also added as arguments.
+ * MULB, MULN and MULE added to get multicolumn output
+ with different width.
+ * Number register N can now use 1-5.
+ * Register Sectp and Sectf added.
+ * Register P is now updated correctly for "section-page" numbering.
+
+Thu Nov 19 11:19:33 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.07
+ * .OP fixed to eject a blank page if not odd.
+
+Fri Nov 13 09:46:09 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.06
+ * Macro TL rewritten. TL depends now on a following .AU.
+ * NOTES updated.
+ * .lt is now used more frequent when linelength is changed.
+ * macro AST added.
+ * removed PH/EH/OH not needed in ?.MT.
+
+Wed Oct 28 14:35:43 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.05
+ * .VM implemented.
+ * Possible bug in page heading fixed. Changed .sp to 'sp in HEADER.
+
+Thu Aug 20 13:56:31 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.04
+ * page-break in .EQ moved.
+ * changed unit for footer-size and header-size from units to lines.
+ Fixes problems with .S and page-breaks.
+ * \n[%] is now treated as a string, wich makes it possible
+ to assign new formats to it. Unfortunately, it was necessary
+ to change the page-number-variable in GETPN to a string.
+ * Makefile.sub included. (Thank you, James)
+
+Thu May 7 16:14:10 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.03
+ * Typo and centering in DS/DE fixed.
+ Even and odd pageheaders were reversed.
+ * LI: pad and mark-indent was lost in some earlier versions. Now fixed.
+ * fixed bug in reference to .FG, .TB, ...
+ * APP did not clear headercounters.
+ * Pointsize in titles is now only set at the beginning and
+ when PH, PF, OH, OF, EH and EF are used.
+
+Thu May 6 16:01:35 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.02
+ * OP fixed.
+
+Fri Mar 6 09:36:09 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.01
+ * two .LI without text between should not be printed
+ on the same row. Now fixed.
+ * figure titles and friends fixed, now possible with many .FG
+ in a DS/DE. Didn't always position correctly in previous version,
+ but is now always printed as it should.
+ * Makefile fixed for Ultrix.
+ * DS/DF could not handle empty arguments correct
+ * Missing .br i EQ added.
+
+Sat Jan 25 15:47:21 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.00
+ * No betaversion anymore!
+ * Fixed headernumbers within appendixes.
+ * DS did not keep the same font as before DS.
+ * mmse did a line break.
+
+Fri Jan 24 14:38:16 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.16
+ * bug in TC, multiple line headers did not wrap correctly.
+ * added support for mm/locale and mm/language_locale.
+ * cov*default-firm in locale sets name of firm in the MT covers.
+ * cov*location-xxxx in locale sets location xxxx to the contents
+ of cov*location-xxxx. Used in the MT covers.
+ * hanging indent in lists fixed.
+ * use larger empty lines if .nroff is defined.
+ * macros, like .P, can now be used inside abstracts.
+ * .S do not reset indentation anymore.
+ * .RS aA now sets a string, not an integer.
+ * appendix with .APP or .APPSK added.
+
+Thu Nov 28 22:00:59 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.15
+ * Fixed .AU in MT 0-3, added support for variable Au.
+ * Bug in the positioning of the foot-notes.
+ * lists not indented properly.
+ * Hps1 and Hps2 added.
+ * COVER had to have an argument.
+ * table of contents can now have multiline header.
+ * .HU now increments headingvariable H?
+ * added the inclusion of a locale file.
+
+Sat Nov 23 14:40:17 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.14
+ * bug when using -rO fixed.
+ * MT 1-4 added.
+ * default is now MT 1
+ * .EQ/.EN can be used outside of .DS/.DE without complaints. But
+ I don't recommend it. Neither does the DWB books.
+ * LI don't break lines now if arg too big.
+ * PGFORM did not reset indent.
+ * Added the numbervariable Hps.
+ * Rewritten and added MT 0-5 + "string".
+ * Added TM.
+ * Indent to AS added
+
+Wed Nov 6 15:18:40 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.13
+ * ds*format nod defined if PS/PE is used without DS/DE.
+ * GETST added, fourth argument to EX, FG, TB and EC added.
+
+Mon Nov 4 13:38:01 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.12
+ * Fixed C,D,P,+-size in .S
+
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * Next version will have ChangeLog entries...
+ * Bug in INITR fixed.
+ * VERBON/VERBOFF added to include programlistings
+ * Bug in .DE fixed, addition overflow
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * spelling error in month-names.
+ * WC should work now (no warranty :-)
+ * FD almost finished, some details missing.
+ * incorrect calculation of foot-notes fixed.
+ * DS/DE did not break page when the size was smaller than the paper
+ * Forward/backward referencesystem added. Se .INITR in README.
+ * mgmsw changed name to mgmse.
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * embarrassing bug in .P fixed
+ * .H did always eject page, now fixed.
+ * lost floating displays now found.
+ * accents added (from mgs)
+ * empty line in .EQ/.EN removed
+ * indentation in .TC corrected.
+ * indentation of DS/DE in lists fixed.
+ * .TB and friends now work inside DS/DE and outside.
+ * .WC partially implemented (WF and WD). Still working on it.
+ * .mso used if version>=1.02
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * register P was not working.
+ * support for register Fg, Tb, Ec and Ex.
+ * list items was left on the previous page at a page break.
+ * tlevel in .TC now defaults to 2.
+ * string DT, EM and Tm supported.
+ * new macro: PGNH, see comments.
+ * bug in MOVE fixed.
+ * pagenumber in .TC fixed.
+ * a blank page was ejected if Ej==1, now fixed
+ * bug in floating display fixed (did break and SP wrong)
+ * bug in .SP fixed, no lines is now printed at top of page
+ * There are still problems with footnotes and displays in two column mode.
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * register P added (same as %)
+ * bug in floating displays fixed
+ * MOVE added
+ * MT added, see comment below
+ * COVER/COVEND added
+ * fixed bug in figure titles
+ * extended S, se comment below
+ * MT 0 added
+ * ms-cover added (COVER ms)
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * bugs in RD and comb. fonts fixed
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * HC added
+ * Combined fonts (IB,BI...)
+ * HM added
+ * RD added
+ * OP added
+ * TP&PX supported
+ * warnings for unimplemented macros
diff --git a/gnu/usr.bin/groff/mm/Makefile b/gnu/usr.bin/groff/mm/Makefile
new file mode 100644
index 000000000000..99d4f0a703b7
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/Makefile
@@ -0,0 +1,34 @@
+TMACOWN?= bin
+TMACGRP?= bin
+TMACMODE?= 444
+TMACDIR?= /usr/share/tmac
+
+FILES= 0.MT 5.MT 4.MT ms.cov se_ms.cov
+LOCALE= locale se_locale
+
+MAN7= groff_mm.7 groff_mmse.7
+MLINKS= groff_mm.7 mm.7 groff_mmse.7 mmse.7
+
+afterinstall:
+ install -c -o $(TMACOWN) -g $(TMACGRP) -m $(TMACMODE) \
+ $(.CURDIR)/tmac.m $(DESTDIR)$(TMACDIR)/tmac.m
+ install -c -o $(TMACOWN) -g $(TMACGRP) -m $(TMACMODE) \
+ $(.CURDIR)/tmac.m $(DESTDIR)$(TMACDIR)/tmac.mse
+
+ test -d $(DESTDIR)$(TMACDIR)/mm || mkdir $(DESTDIR)$(TMACDIR)/mm
+ chown $(TMACOWN).$(TMACGRP) $(DESTDIR)$(TMACDIR)/mm
+ chmod 755 $(DESTDIR)$(TMACDIR)/mm
+
+ for f in $(FILES); do \
+ rm -f $(TMACDIR)/mm/$$f; \
+ install -c -o $(TMACOWN) -g $(TMACGRP) -m $(TMACMODE) \
+ $(.CURDIR)/mm/$$f $(DESTDIR)$(TMACDIR)/mm/$$f; \
+ done
+ for f in $(LOCALE); do \
+ test -f $(DESTDIR)$(TMACDIR)/mm/$$f || touch $(DESTDIR)$(TMACDIR)/mm/$$f; \
+ chown $(TMACOWN).$(TMACGRP) $(DESTDIR)$(TMACDIR)/mm/$$f; \
+ chmod $(TMACMODE) $(DESTDIR)$(TMACDIR)/mm/$$f; \
+ done
+
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/mm/NOTES b/gnu/usr.bin/groff/mm/NOTES
new file mode 100644
index 000000000000..ee258d349ef9
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/NOTES
@@ -0,0 +1,101 @@
+######################################################################
+
+Implementation notes. (Or how to make your own national mm)
+
+Different commands:
+
+COVER [arg]
+MT [arg [addressee]]
+The arg is part of a filename in mm/*.MT or mm/*.cov.
+This file is read when the macro is executed. Therefore it must be
+put before any text output.
+In each file there are definitions of all extra macros needed for the
+cover sheet. MT files is only for compatibility reasons, and has several
+limits due to that it don't know when the cover starts, and cannot
+change sizes. Use COVER for new coversheet macros.
+
+But with MT it is possible to write all of the AT&T covers.
+An example can be found in mm/0.MT.
+
+When writing a new cover using COVER, have in mind that the cover
+should print the page with the COVEND macro. This macro
+should be defined by the new macrofile.
+
+Here is a part of ms.cov:
+> .\"-----------------
+> .de COVEND
+> .sp |4.2c
+> .cov@print-title
+> .cov@print-authors
+> .cov@print-firm
+> .cov@print-abstract
+> .cov@print-date
+This is important, since COVER disables the page header.
+> .pg@enable-top-trap
+Should begin with page one (normally).
+> .bp 1
+And enable the trap at the page footer.
+> .pg@enable-trap
+> ..
+
+#########################
+
+Variables for covers:
+I = integer
+S = string
+D = diversion
+M = macro
+
+Name Type Desc.
+cov*au I The number of authors.
+
+cov*title M Title collected with .TL.
+
+cov*au!x!y S Author(s) given to .AU
+cov*at!x!y S Author(s) title given to .AT
+ x is the author-index [1-cov*au],
+ y is the argument-index [1-9].
+ Look at the table with indexes.
+
+cov*firm I Author(s) firm.
+
+cov*abs-arg I Argument to abstract.
+
+cov*abs-ind I Indent for abstract.
+
+cov*abs-name S The string 'ABSTRACT', changed with .AST
+
+cov*abstract M The abstract.
+
+cov*new-date S The date (todays date if ND is not used)
+
+cov*mt-type S MT type
+cov*mt-addresse S MT addressee
+
+
+##########################
+Argument-index for cov*au:
+
+Index Desc.
+1 name
+2 initials
+3 location
+4 department
+5 extension
+6 room
+7 arg 7
+8 arg 8
+9 arg 9
+
+The location is set to the contents of string cov*location-xxxx
+if location is equal to xxxx and cov*location-xxxx is defined
+in the file locale.
+
+
+Argument-index for cov*at:
+
+Index Desc.
+1 title 1
+. .
+. .
+9 title 9
diff --git a/gnu/usr.bin/groff/mm/README b/gnu/usr.bin/groff/mm/README
new file mode 100644
index 000000000000..54b32d211c46
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/README
@@ -0,0 +1,26 @@
+This is mgm, a macro package for groff.
+
+It is supposed to be compatible with the DWB mm macros,
+and has several extensions.
+
+Send bug reports to jh@efd.lth.se with a description of the problem
+and a sample of text which reproduces the error.
+
+Don't forget to mention the version of mgm (look in the beginning
+of tmac.m) and the version of groff.
+
+Any new ideas or improvements are welcome.
+
+Newest version is available with anonymous FTP
+at ftp.efd.lth.se [130.235.48.11], as pub/groff/mm<something>.Z
+
+You can install mgm as a separate package without the configure in groff
+with the following command:
+
+make -f Makefile.sim install
+
+This README should be bigger :-)
+
+Jörgen.
+
+Thanks to everyone who have send me bug-reports and fixes.
diff --git a/gnu/usr.bin/groff/mm/groff_mm.7 b/gnu/usr.bin/groff/mm/groff_mm.7
new file mode 100644
index 000000000000..7918252baf01
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/groff_mm.7
@@ -0,0 +1,738 @@
+.TH GROFF_MM 7 "4 March 1993" "Groff Version 1.08"
+.SH NAME
+groff_mm \- groff mm macros
+.SH SYNOPSIS
+.B groff
+.B \-mm
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.SH DESCRIPTION
+The groff mm macros are intended to be compatible with the DWB mm macros
+with the following limitations:
+.TP
+.B \(bu
+no letter macros implemented (yet).
+.TP
+.B \(bu
+no Bell Labs localisms implemented.
+.TP
+.B \(bu
+the macros OK and PM is not implemented.
+.TP
+.B \(bu
+groff mm does not support cut marks
+.LP
+\fBmm\fP is intended to be international. Therefore it is
+possible to write short national macrofiles which change all
+english text to the preferred language. Use \fBmmse\fP as an example.
+.LP
+Groff mm has several extensions:
+.TP
+.B "APP name text"
+Begin an appendix with name \fIname\fP. Automatic naming occurs if
+\fIname\fP is "". The appendixes starts with \fBA\fP if auto is used.
+An new page is ejected, and a header is also produced if the number
+variable \fBAph\fP is non-zero. This is the default.
+The appendix always appear in the 'List of contents' with correct
+pagenumber. The name \fIAPPENDIX\fP can be changed by setting
+the string \fBApp\fP to the desired text.
+.TP
+.B "APPSK name pages text"
+Same as \fB.APP\fP, but the pagenr is incremented with \fIpages\fP.
+This is used when diagrams or other non-formatted documents are
+included as appendixes.
+.TP
+.B B1
+Begin box (as the ms macro)
+Draws a box around the text.
+.TP
+.B B2
+End box. Finish the box.
+.TP
+.B BVL
+Start of
+broken variable-item list.
+As VL but text begins always at the next line
+.TP
+.B "COVER [arg]"
+\&\fBCOVER\fP begins a coversheet definition. It is important
+that \fB.COVER\fP appears before any normal text.
+\&\fB.COVER\fP uses \fIarg\fP to build the filename
+/usr/share/tmac/mm/\fIarg\fP.cov. Therefore it is possible to create unlimited
+types of coversheets.
+\fIms.cov\fP is supposed to look like the \fBms\fP coversheet.
+\&\fB.COVER\fP requires a \fB.COVEND\fP at the end of the coverdefinition.
+Always use this order of the covermacros:
+.nf
+\&.COVER
+\&.TL
+\&.AF
+\&.AU
+\&.AT
+\&.AS
+\&.AE
+\&.COVEND
+.fi
+However, only \fB.TL\fP and \fB.AU\fP are required.
+.TP
+.B COVEND
+This finish the cover description and prints the cover-page.
+It is defined in the cover file.
+.TP
+.B "GETHN refname [varname]"
+Includes the headernumber where the corresponding \fBSETR\fP \fIrefname\fP
+was placed. Will be X.X.X. in pass 1. See \fBINITR\fP.
+If varname is used, \fBGETHN\fP sets the stringvariable \fIvarname\fP to the
+headernumber.
+.TP
+.B "GETPN refname [varname]"
+Includes the pagenumber where the corresponding \fBSETR\fP \fIrefname\fP
+was placed. Will be 9999 in pass 1. See \fBINITR\fP.
+If varname is used, \fBGETPN\fP sets the stringvariable \fIvarname\fP
+to the pagenumber.
+.TP
+.B "GETR refname"
+Combines \fBGETHN\fP and \fBGETPN\fP with the text 'chapter' and ', page'.
+The string \fIQrf\fP contains the text for reference:
+.ti +.5i
+\&.ds Qrf See chapter \e\e*[Qrfh], page \e\e*[Qrfp].
+.br
+\fIQrf\fP may be changed to support other languages.
+Strings \fIQrfh\fP and \fIQrfp\fP are set by \fBGETR\fP
+and contains the page and headernumber.
+.TP
+.B "GETST refname [varname]"
+Includes the string saved with the second argument to \fB.SETR\fP.
+Will be dummystring in pass 1.
+If varname is used, \fBGETST\fP sets the stringvariable \fIvarname\fP to the
+saved string. See \fBINITR\fP.
+.TP
+.B "INITR filename"
+Initialize the refencemacros. References will be written to
+\fIfilename.tmp\fP and \fIfilename.qrf\fP. Requires two passes with groff.
+The first looks for references and the second includes them.
+\fBINITR\fP can be used several times, but it is only the first
+occurrence of \fBINITR\fP that is active.
+See also \fBSETR\fP, \fBGETPN\fP and \fBGETHN\fP.
+.TP
+.B "MC column-size [column-separation] "
+Begin multiple columns. Return to normal with 1C.
+.TP
+.B "MT [arg [addressee]]"
+Memorandom type.
+The \fIarg\fP is part of a filename in \fI/usr/share/tmac/mm/*.MT\fP.
+Memorandum type 0 thru 5 are supported, including \fI"string"\fP.
+\fIAddresse\fP just sets a variable, used in the AT&T macros.
+.TP
+.B "MOVE y-pos [x-pos [line-length]]"
+Move to a position, pageoffset set to \fIx-pos\fP.
+If \fIline-length\fP is not given, the difference between
+current and new pageoffset is used.
+Use \fBPGFORM\fP without arguments to return to normal.
+.TP
+.B "MULB cw1 space1 [cw2 space2 [cw3 ...]]"
+Begin a special multi-column mode. Every columns width must be specified.
+Also the space between the columns must be specified. The last column
+does not need any space-definition. MULB starts a diversion and MULE
+ends the diversion and prints the columns.
+The unit for width and space is 'n', but MULB accepts all
+normal unitspecifications like 'c' and 'i'.
+MULB operates in a separate environment.
+.TP
+.B "MULN"
+Begin the next column. This is the only way to switch column.
+.TP
+.B "MULE"
+End the multi-column mode and print the columns.
+.TP
+.B "PGFORM [linelength [pagelength [pageoffset]]]"
+Sets linelength, pagelength and/or pageoffset.
+This macro can be used for special formatting, like letterheads
+and other.
+\fBPGFORM\fP can be used without arguments
+to reset everything after a \fBMOVE\fP.
+.TP
+.B PGNH
+No header is printed on the next page. Used to get rid off
+the header in letters or other special texts
+This macro must be used before any text to inhibit the pageheader
+on the first page.
+.TP
+.B "SETR refname [string]"
+Remember the current header and page-number as refname.
+Saves \fIstring\fP if \fIstring\fP is defined. \fIstring\fP is retrieved
+with \fB.GETST\fP.
+See \fBINITR\fP.
+.TP
+.B TAB
+reset tabs to every 5n. Normally used to reset any previous tabpositions.
+.TP
+.B VERBON [flag [pointsize [font]]]
+Begin verbatim output using courier font.
+Usually for printing programs.
+All character has equal width.
+The pointsize can be changed with
+the second argument. By specifying the font-argument
+it is possible to use another font instead of courier.
+\fIflag\fP control several special features.
+It contains the sum of all wanted features.
+.in +.5i
+.ti -.5i
+Value
+.sp -1
+Description
+.ti -.5i
+1
+.sp -1
+Enable the escape-character (\e). This is normally turned off during
+verbose output.
+.ti -.5i
+2
+.sp -1
+Add en empty line before the verbose text.
+.ti -.5i
+4
+.sp -1
+Add en empty line after the verbose text.
+.ti -.5i
+8
+.sp -1
+Print the verbose text with numbered lines. This adds four digitsized
+spaces in the beginning of each line. Finer control is available with
+the string-variable \fBVerbnm\fP. It contains all arguments to the
+\fBtroff\fP-command \fB.nm\fP, normally '1'.
+.ti -.5i
+16
+.sp -1
+Indent the verbose text with five 'n':s. This is controlled by the
+number-variable \fBVerbin\fP (in units).
+.in
+.TP
+.B VERBOFF
+End verbatim output.
+.sp
+.LP
+.\"########################################################################
+New variables in mm:
+.TP
+.B App
+A string containing the word "APPENDIX".
+.TP
+.B Aph
+Print an appendix-page for every new appendix
+if this numbervariable is non-zero.
+No output will occur if \fBAph\fP is zero, but there will always
+be an appendix-entry in the 'List of contents'.
+.TP
+.B Hps
+Numbervariable with the heading pre-space level. If the heading-level
+is less than or equal to \fBHps\fP, then two lines will precede the
+section heading instead of one. Default is first level only.
+The real amount of lines is controlled by the variables \fBHps1\fP and
+\fBHps2\fP.
+.TP
+.B Hps1
+This is the number of lines preceding \fB.H\fP when the heading-level
+is greater than \fBHps\fP. Value is in units, normally 0.5v.
+.TP
+.B Hps2
+This is the number of lines preceding \fB.H\fP when the heading-level
+is less than or equal to \fBHps\fP. Value is in units, normally 1v.
+.TP
+.B Lifg
+String containing \fIFigure\fP.
+.TP
+.B Litb
+String containing \fITABLE\fP.
+.TP
+.B Liex
+String containing \fIExhibit\fP.
+.TP
+.B Liec
+String containing \fIEquation\fP.
+.TP
+.B Licon
+String containing \fICONTENTS\fP.
+.TP
+.B Lsp
+.TP
+The size of an empty line. Normally 0.5v, but it is 1v
+if \fBn\fP is set (\fB.nroff\fP).
+.B "MO1 - MO12"
+Strings containing \fIJanuary\fI to \fIDecember\fP.
+.TP
+.B Qrf
+String containing "See chapter \e\e*[Qrfh], page \e\en[Qrfp].".
+.TP
+.B Sectf
+Flag controlling "section-figures". A non-zero value enables this.
+Se also register N.
+.TP
+.B Sectp
+Flag controlling "section-page-numbers". A non-zero value enables this.
+Se also register N.
+.TP
+.B .mgm
+Always 1.
+.\"########################################################################
+.LP
+A file called \fBlocale\fP or \fIlang\fP\fB_locale\fP is read
+after the initiation of the global variables. It is therefore
+possible to localize the macros with companyname and so on.
+.sp 3
+.LP
+The following standard macros are implemented:
+.TP
+.B 1C
+Begin one column processing
+.TP
+.B 2C
+Begin two column processing
+.TP
+.B AE
+Abstract end
+.TP
+.B "AF [name of firm]"
+Authors firm
+.TP
+.B "AL [type [text-indent [1]]]]"
+Start autoincrement list
+.TP
+.B "AS [arg [indent]]"
+Abstract start. Indent is specified in 'ens', but scaling is allowed.
+.TP
+.B "AST [title]"
+Abstract title. Default is 'ABSTRACT'.
+.TP
+.B "AT title1 [title2 ...]"
+Authors title
+.TP
+.B "AU name [initials [loc [dept [ext [room [arg [arg [arg]]]]]]]]"
+Author information
+.TP
+.B "B [bold-text [prev-font-tex [...]]]"
+Begin boldface
+No limit on the number of arguments.
+.TP
+.B BE
+End bottom block
+.TP
+.B "BI [bold-text [italic-text [bold-text [...]]]"
+Bold-italic.
+No limit on the number of arguments.
+.TP
+.B "BL [text-indent [1]]"
+Start bullet list
+.TP
+.B "BR [bold-text [roman-text [bold-text [...]]]"
+Bold-roman.
+No limit on the number of arguments.
+.TP
+.B BS
+Bottom block start
+.TP
+.B DE
+Display end
+.TP
+.B "DF [format [fill [rindent]]]"
+Begin floating display (no nesting allowed)
+.TP
+.B "DL [text-indent [1]]"
+Dash list start
+.TP
+.B "DS [format [fill [rindent]]]"
+Static display start.
+Can now have unlimited nesting. Also
+right adjusted text and block may be used (R or RB as \fIformat\fP).
+.TP
+.B "EC [title [override [flag [refname]]]]"
+Equation title.
+If \fIrefname\fP is used, then the equationnumber is saved with
+\&\fB.SETR\fP, and can be retrieved with \fB.GETST\fP \fIrefname\fP.
+.TP
+.B "EF [arg]"
+Even-page footer.
+.TP
+.B "EH [arg]"
+Even-page header.
+.TP
+.B EN
+Equation end.
+.TP
+.B "EQ [label]"
+Equation start.
+.TP
+.B "EX [title [override [flag [refname]]]]"
+Exhibit title.
+If \fIrefname\fP is used, then the exhibitnumber is saved with
+\&\fB.SETR\fP, and can be retrieved with \fB.GETST\fP \fIrefname\fP.
+.TP
+.B "FD [arg [1]]"
+Footnote default format.
+.TP
+.B FE
+Footnote end.
+.TP
+.B "FG [title [override [flag [refname]]]]"
+Figure title.
+If \fIrefname\fP is used, then the figurenumber is saved with
+\&\fB.SETR\fP, and can be retrieved with \fB.GETST\fP \fIrefname\fP.
+.TP
+.B FS
+Footnote start.
+Footnotes in displays is now possible.
+.TP
+.B "H level [heading-text [heading-suffix]]"
+Numbered heading.
+.TP
+.B "HC [hypenation-character]"
+Set hypenation character.
+.TP
+.B "HM [arg1 [arg2 [... [arg7]]]]"
+Heading mark style.
+.TP
+.B "HU heading-text"
+Unnumbered header.
+.TP
+.B "HX dlevel rlevel heading-text"
+Userdefined heading exit.
+Called just before printing the header.
+.TP
+.B "HY dlevel rlevel heading-text"
+Userdefined heading exit.
+Called just before printing the header.
+.TP
+.B "HZ dlevel rlevel heading-text"
+Userdefined heading exit.
+Called just after printing the header.
+.TP
+.B "I [italic-text [prev-font-text [italic-text [...]]]"
+Italic.
+.TP
+.B "IB [italic-text [bold-text [italic-text [...]]]"
+Italic-bold
+.TP
+.B "IR [italic-text [roman-text [italic-text [...]]]"
+Italic-roman
+.TP
+.B "LB text-indent mark-indent pad type [mark [LI-space [LB-space]]]"
+List begin macro.
+.TP
+.B "LC [list level]"
+List-status clear
+.TP
+.B LE
+List end.
+.TP
+.B "LI [mark [1]]"
+List item
+.TP
+.B "ML mark [text-indent]"
+Marked list start
+.TP
+.B "MT [arg [addressee]]"
+Memorandom type. See above note about MT.
+.TP
+.B "ND new-date"
+New date.
+.TP
+.B "OF [arg]"
+Odd-page footer
+.TP
+.B "OH [arg]"
+Odd-page header
+.TP
+.B OP
+Skip to odd page.
+.TP
+.B "P [type]"
+Begin new paragraph.
+.TP
+.B PE
+Picture end.
+.TP
+.B "PF [arg]"
+Page footer
+.TP
+.B "PH [arg]"
+Page header
+.TP
+.B PS
+Picture start (from pic)
+.TP
+.B PX
+Page-header user-defined exit.
+.TP
+.B R
+Roman.
+.TP
+.B "RB [roman-text [bold-text [roman-text [...]]]"
+Roman-bold.
+.TP
+.B "RD [prompt [diversion [string]]]"
+Read to diversion and/or string.
+.TP
+.B RF
+Reference end
+.TP
+.B "RI [roman-text [italic-text [roman-text [...]]]"
+Roman-italic.
+.TP
+.B "RL [text-indent [1]]"
+Reference list start
+.TP
+.B "RP [arg [arg]]"
+Produce reference page.
+.TP
+.B "RS [string-name]"
+Reference start.
+.TP
+.B "S [size [spacing]]"
+Set point size and vertical spacing. If any argument is equal 'P', then
+the previous value is used. A 'C' means current value, and 'D' default value.
+If '+' or '-' is used before the value, then increment or decrement of
+the current value will be done.
+.TP
+.B "SA [arg]"
+Set adjustment.
+.TP
+.B "SK [pages]"
+Skip pages.
+.TP
+.B "SM string1 [string2 [string3]]"
+Make a string smaller.
+.TP
+.B "SP [lines]"
+Space vertically. \fIlines\fP can have any scalingfactor, like \fI3i\fP or
+\fI8v\fP.
+.TP
+.B "TB [title [override [flag [refname]]]]"
+Table title.
+If \fIrefname\fP is used, then the tablenumber is saved with
+\&\fB.SETR\fP, and can be retrieved with \fB.GETST\fP \fIrefname\fP.
+.TP
+.B "TC [slevel [spacing [tlevel [tab [h1 [h2 [h3 [h4 [h5]]]]]]]]]"
+Table of contents.
+All texts can be redefined, new stringvariables
+\fILifg\fP, \fILitb\fP, \fILiex\fP, \fILiec\fP and \fILicon\fP contains
+"Figure", "TABLE", "Exhibit", "Equation" and "CONTENTS".
+These can be redefined to other languages.
+.TP
+.B TE
+Table end.
+.TP
+.B "TH [N]"
+Table header.
+.TP
+.B TL
+Begin title of memorandom.
+.TP
+.B TM [num1 [num2 [...]]]
+Technical memorandumnumbers used in \fB.MT\fP. Unlimited number
+of arguments may be given.
+.TP
+.B TP
+Top of page user-defined macro.
+.TP
+.B "TS [H]"
+Table start
+.TP
+.B TX
+Userdefined table of contents exit.
+.TP
+.B TY
+Userdefined tbale of contents exit (no "CONTENTS").
+.TP
+.B "VL [text-indent [mark-indent [1]]]"
+Variable-item list start
+.TP
+.B "VM [top [bottom]]"
+Vertical margin.
+.TP
+.B "WC [format]"
+Footnote and display width control.
+.sp 3
+.LP
+Strings used in mm:
+.TP
+.B "EM"
+Em dash string
+.TP
+.B HF
+Fontlist for headings, normally "2 2 2 2 2 2 2".
+Nonnumeric fontnames may also be used.
+.TP
+.B HP
+Pointsize list for headings. Normally "0 0 0 0 0 0 0" which is the same as
+"10 10 10 10 10 10 10".
+.TP
+.B Lf
+Contains "LIST OF FIGURES".
+.TP
+.B Lt
+Contains "LIST OF TABLES".
+.TP
+.B Lx
+Contains "LIST OF EXHIBITS".
+.TP
+.B Le
+Contains "LIST OF EQUATIONS".
+.TP
+.B Rp
+Contains "REFERENCES".
+.TP
+.B Tm
+Contains \e(tm, trade mark.
+.\"-----------------------------------
+.LP
+Number variables used in mm:
+.TP
+.B Cl=2
+Contents level [0:7], contents saved if heading level <= Cl
+.TP
+.B Cp=0
+Eject page between LIST OF XXXX if Cp == 0
+.TP
+.B D=0
+Debugflag, values >0 produces varying degree of debug. A value of 1
+gives information about the progress of formatting.
+.TP
+.B De=0
+Eject after floating display is output [0:1]
+.TP
+.B Df=5
+Floating keep output [0:5]
+.TP
+.B Ds=1
+space before and after display if == 1 [0:1]
+.TP
+.B Ej=0
+Eject page
+.TP
+.B Eq=0
+Eqation lable adjust 0=left, 1=right
+.TP
+.B Fs=1
+Footnote spacing
+.TP
+.B "H1-H7"
+Heading counters
+.TP
+.B Hb=2
+Heading break level [0:7]
+.TP
+.B Hc=0
+Heading centering level, [0:7]
+.TP
+.B Hi=1
+Heading temporary indent [0:2]
+0 -> 0 indent, left margin
+.br
+1 -> indent to right , like .P 1
+.br
+2 -> indent to line up with text part of preceding heading
+.TP
+.B Hs=2
+Heading space level [0:7]
+.TP
+.B Ht=0
+Heading numbering type
+0 -> multiple (1.1.1 ...)
+.br
+1 -> single
+.TP
+.B Hu=2
+Unnumbered heading level
+.TP
+.B Hy=1
+Hyphenation in body
+0 -> no hyphenation
+.br
+1 -> hyphenation 14 on
+.TP
+.B "Lf=1, Lt=1, Lx=1, Le=0"
+Enables (1) or disables (0) the printing of List of figures,
+List of tables, List of exhibits and List of equations.
+.TP
+.B Li=6
+List indent, used by .AL
+.TP
+.B Ls=99
+List space, if current listlevel > Ls then no spacing will occur around lists.
+.TP
+.B N=0
+Numbering style [0:5]
+0 == (default) normal header for all pages.
+.br
+1 == header replaces footer on first page, header is empty.
+.br
+2 == page header is removed on the first page.
+.br
+3 == "section-page" numbering enabled.
+.br
+4 == page header is removed on the first page.
+.br
+5 == "section-page" and "section-figure" numbering enabled.
+Se also the number-register Sectf and Sectp.
+.TP
+.B Np=0
+Numbered paragraphs.
+.br
+0 == not numbered
+.br
+1 == numbered in first level headings.
+.TP
+.B Of=0
+Format of figure,table,exhibit,equation titles.
+.br
+0= ". "
+.br
+1= " - "
+.TP
+.B P
+Current page-number, normally the same as % unless "section-page" numbering
+is enabled.
+.TP
+.B Pi=5
+paragraph indent
+.TP
+.B Ps=1
+paragraph spacing
+.TP
+.B Pt=0
+Paragraph type.
+.br
+0 == left-justified
+.br
+1 == indented .P
+.br
+2 == indented .P except after .H, .DE or .LE.
+.TP
+.B Si=5
+Display indent.
+.LP
+.\".SH BUGS
+.SH AUTHOR
+Jörgen Hägg, Lund Institute of Technology, Sweden <jh@efd.lth.se>
+.SH FILES
+.TP
+.B /usr/share/tmac/tmac.m
+.TP
+.B /usr/share/tmac/mm/*.cov
+.TP
+.B /usr/share/tmac/mm/*.MT
+.TP
+.B /usr/share/tmac/mm/locale
+.SH "SEE ALSO"
+.BR groff (1),
+.BR troff (1),
+.BR tbl (1),
+.BR pic (1),
+.BR eqn (1)
+.br
+.BR mm (7)
+.BR mmse (7)
diff --git a/gnu/usr.bin/groff/mm/groff_mmse.7 b/gnu/usr.bin/groff/mm/groff_mmse.7
new file mode 100644
index 000000000000..eabdbda91483
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/groff_mmse.7
@@ -0,0 +1,36 @@
+.\"
+.\" Skrivet av Jörgen Hägg, Lund, Sverige
+.\"
+.TH GROFF_MMSE 7 "21 February 1993" "Groff Version 1.08"
+.SH NAMN
+groff_mmse \- svenska mm makro för groff
+.SH SYNTAX
+.B groff
+.B \-mmse
+[
+.IR flaggor .\|.\|.
+]
+[
+.IR filer .\|.\|.
+]
+.SH BESKRIVNING
+\fBmmse\fP är en svensk variant av \fBmm\fP. Alla texter
+är översatta. En A4 sida får text som är 13 cm bred, 3.5 cm indragning
+samt är 28.5 cm hög.
+.LP
+\fBCOVER\fP kan använda \fIse_ms\fP som argument. Detta ger ett
+svenskt försättsblad.
+Se \fBgroff_mm(7)\fP för övriga detaljer.
+.SH "SKRIVET AV"
+Jörgen Hägg, Lunds Tekniska Högskola <jh@efd.lth.se>
+.SH FILER
+.B /usr/share/tmac/tmac.mse
+.B /usr/share/tmac/mm/se_*.cov
+.SH "SE OCKSÅ"
+.BR groff (1),
+.BR troff (1),
+.BR tbl (1),
+.BR pic (1),
+.BR eqn (1)
+.br
+.BR mm (7)
diff --git a/gnu/usr.bin/groff/mm/mm/0.MT b/gnu/usr.bin/groff/mm/mm/0.MT
new file mode 100644
index 000000000000..1ac48598449e
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/mm/0.MT
@@ -0,0 +1,143 @@
+.\"------------
+.\" Cover sheet. Memorandum type 0-3 and "string".
+.\"------------
+.if !r Au .nr Au 1
+.nr cov*mt0-ind 1.1c
+.de cov@print-title
+.MOVE 4.8c 1.5c
+.S 8
+subject:
+.sp -1.1
+.S
+.PGFORM
+.B
+.ll 9c
+.fi
+.cov*title
+.R
+.ll
+.nf
+.if d cov*title-charge-case \fBCharge Case \\*[cov*title-charge-case]\fP
+.if d cov*title-file-case \fBFile Case \\*[cov*title-file-case]\fP
+.fi
+..
+.\"------------
+.de cov@print-authors
+.MOVE 5.7c 13.3c
+.nf
+.S 8
+\\$1:
+.br
+.S
+.sp -1
+.in 0.8c
+.B
+.nr cov*i 0 1
+.while \\n+[cov*i]<=\\n[cov*au] \{\
+. cov@print-au1 \\n[cov*i] 1
+. if \\n[Au] \{\
+. cov@print-au2 \\n[cov*i] 3 4
+. cov@print-au2 \\n[cov*i] 6 5
+. cov@print-au1 \\n[cov*i] 7
+. cov@print-au1 \\n[cov*i] 8
+. cov@print-au1 \\n[cov*i] 9
+. \}
+. if \\n[cov*i]<\\n[cov*au] .SP 1
+.\}
+.R
+.if r cov*mt-tm-max \{\
+. SP 1
+. nr cov*i 0 1
+. B
+TM
+. in 1.5c
+. sp -1
+. while \\n+[cov*i]<\\n[cov*mt-tm-max] \\*[cov*mt-tm!\\n[cov*i]]
+. in
+. R
+.\}
+.fi
+.PGFORM
+..
+.\"------------
+.\" index arg1
+.de cov@print-au1
+.if d cov*au!\\$1!\\$2 \\*[cov*au!\\$1!\\$2]
+..
+.\"------------
+.de cov@print-au2
+.\" index arg1 arg2
+.if d cov*au!\\$1!\\$2 \\*[cov*au!\\$1!\\$2] \c
+.if \\$3=5 .if d cov*au!\\$1!\\$3 x\c
+.if d cov*au!\\$1!\\$3 \\*[cov*au!\\$1!\\$3]\c
+.br
+..
+.\"------------
+.de cov@print-date
+.MOVE 4.8c 13.3c
+.S 8
+\\$1:
+.br
+.S
+.sp -1
+.in 0.8c
+.B "\\*[cov*new-date]"
+.br
+.PGFORM
+..
+.\"------------
+.de cov@print-firm
+.if d cov*firm \{\
+. MOVE 2.8c 0 17.7c
+. S 18
+. rj 1
+\fB\\*[cov*firm]\fP
+. S
+. PGFORM
+.\}
+..
+.\"------------
+.de cov@print-abstract
+.SP 3
+.if d cov*abstract \{\
+. misc@ev-keep cov*ev
+. if \\n[cov*abs-ind]>0 \{\
+. in +\\n[cov*abs-ind]u
+. ll -\\n[cov*abs-ind]u
+. \}
+. ce
+\fI\\$1\fP
+. SP 1.5
+. fi
+. cov*abstract
+. br
+. ev
+.\}
+..
+.\"-----------------
+.ds cov*mt0-txt!1 MEMORANDUM FOR FILE
+.ds cov*mt0-txt!2 PROGRAMMER'S NOTES
+.ds cov*mt0-txt!3 ENGINEER'S NOTES
+.if d cov*default-firm .if !d cov*firm .ds cov*firm \\*[cov*default-firm]
+.\"
+.if !d cov*mt-printed \{\
+. cov@print-firm
+. cov@print-title subject
+. cov@print-date date
+. cov@print-authors from
+. cov@print-abstract \\*[cov*abs-name]
+. SP 3
+. if (\*[cov*mt-type]>=1)&(\*[cov*mt-type]<=3) \{\
+. ce
+\fI\*[cov*mt0-txt!\*[cov*mt-type]]\fP
+. SP 1.5
+. \}
+. if \*[cov*mt-type]=6 \{\
+. ce
+\fI\*[cov*mt-type-text]\fP
+. SP 1.5
+. \}
+. pg@enable-top-trap
+. pg@enable-trap
+. ds cov*mt-printed
+.\}
diff --git a/gnu/usr.bin/groff/mm/mm/4.MT b/gnu/usr.bin/groff/mm/mm/4.MT
new file mode 100644
index 000000000000..e36113247a7a
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/mm/4.MT
@@ -0,0 +1,65 @@
+.\"------------
+.\" Cover sheet. Memorandum type 4
+.\"------------
+.de cov@print-title
+.MOVE 2.4c
+.S 12
+.ad c
+.fi
+.B
+.cov*title
+.br
+.S
+.R
+.ad b
+.PGFORM
+..
+.\"------------
+.de cov@print-authors
+.SP 0.5
+.I
+.nr cov*i 0 1
+.while \\n+[cov*i]<=\\n[cov*au] \{\
+.ce
+\\*[cov*au!\\n[cov*i]!1]
+.br
+.\}
+.R
+.PGFORM
+..
+.\"------------
+.de cov@print-firm
+.SP 0.5
+.ce
+\\*[cov*firm]
+..
+.\"------------
+.de cov@print-abstract
+.SP 2
+.if d cov*abstract \{\
+. misc@ev-keep cov*ev
+. if \\n[cov*abs-ind]>0 \{\
+. in +\\n[cov*abs-ind]u
+. ll -\\n[cov*abs-ind]u
+. \}
+. ce
+\fI\\*[cov*abs-name]\fP
+. SP 2
+. fi
+. cov*abstract
+. br
+. ev
+.\}
+..
+.\"-----------------
+.if d cov*default-firm .if !d cov*firm .ds cov*firm \\*[cov*default-firm]
+.if !d cov*mt-printed \{\
+. cov@print-title
+. cov@print-authors
+. cov@print-firm
+. cov@print-abstract
+. SP 3
+. ds cov*mt-printed
+. pg@enable-top-trap
+. pg@enable-trap
+.\}
diff --git a/gnu/usr.bin/groff/mm/mm/5.MT b/gnu/usr.bin/groff/mm/mm/5.MT
new file mode 100644
index 000000000000..654fc95f225a
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/mm/5.MT
@@ -0,0 +1,33 @@
+.\"------------
+.\" Cover sheet. Memorandum type 5
+.\"------------
+.nr cov*mt0-ind 1.1c
+.de cov@print-title
+.B
+.ll 9c
+.fi
+.cov*title
+.R
+.ll
+.nf
+.if d cov*title-charge-case \fBCharge Case \\*[cov*title-charge-case]\fP
+.if d cov*title-file-case \fBFile Case \\*[cov*title-file-case]\fP
+.fi
+..
+.\"------------
+.de cov@print-date
+.rj 1
+.B "\\*[cov*new-date]"
+.br
+..
+.\"------------
+.if !d cov*mt-printed \{\
+. SP 1.9c
+. cov@print-title
+. SP 1.2c
+. cov@print-date
+. SP 3
+. pg@enable-top-trap
+. pg@enable-trap
+. ds cov*mt-printed
+.\}
diff --git a/gnu/usr.bin/groff/mm/mm/ms.cov b/gnu/usr.bin/groff/mm/mm/ms.cov
new file mode 100644
index 000000000000..ee7511392899
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/mm/ms.cov
@@ -0,0 +1,82 @@
+.\"------------
+.\" Cover sheet. Mostly like ms cover.
+.\"------------
+.de cov@print-title
+.in 0
+.misc@ev-keep cov*ev
+.init@reset
+.ad c
+.hy 0
+.fi
+.B
+.cov*title
+.br
+.ad b
+.R
+.ev
+..
+.\"------------
+.de cov@print-authors
+.SP
+.nr cov*i 0 1
+.while \\n+[cov*i]<=\\n[cov*au] \{\
+. ce
+\fI\\*[cov*au!\\n[cov*i]!1]\fP
+. nr cov*j 0 1
+. while \\n+[cov*j]<=9 \{\
+. if d cov*at!\\n[cov*i]!\\n[cov*j] \{\
+. if \w'\\*[cov*at!\\n[cov*i]!\\n[cov*j]]' \{\
+. ce
+\s-1\\*[cov*at!\\n[cov*i]!\\n[cov*j]]\s0
+. .\}
+. \}
+. \}
+.\}
+..
+.\"------------
+.de cov@print-firm
+.SP .5
+.ce
+\\*[cov*firm]
+..
+.\"------------
+.de cov@print-abstract
+.SP 2
+.if d cov*abstract \{\
+. misc@ev-keep cov*ev
+. init@reset
+. if \\n[cov*abs-ind]>0 \{\
+. in +\\n[cov*abs-ind]u
+. ll -\\n[cov*abs-ind]u
+. \}
+. ce
+\fI\\$1\fP
+. SP 1.5
+. fi
+. cov*abstract
+. br
+. ev
+.\}
+..
+.\"------------
+.de cov@print-date
+.SP 2
+\\*[cov*new-date]
+..
+.\"-----------------
+.de COVEND
+.if d cov*default-firm .if !d cov*firm .ds cov*firm \\*[cov*default-firm]
+.sp |4.2c
+.cov@print-title
+.cov@print-authors
+.cov@print-firm
+.cov@print-abstract \\*[cov*abs-name]
+.cov@print-date
+.pg@enable-top-trap
+.bp 1
+.pg@enable-trap
+.if d cov*abs-arg .if \\n[cov*abs-arg] \{\
+. cov@print-abstract ABSTRACT
+. SP 2
+.\}
+..
diff --git a/gnu/usr.bin/groff/mm/mm/se_ms.cov b/gnu/usr.bin/groff/mm/mm/se_ms.cov
new file mode 100644
index 000000000000..e6431f25e99b
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/mm/se_ms.cov
@@ -0,0 +1,2 @@
+.mso mm/ms.cov
+.nr cur*abstract-ll 11c
diff --git a/gnu/usr.bin/groff/mm/tmac.m b/gnu/usr.bin/groff/mm/tmac.m
new file mode 100644
index 000000000000..d37bdac0a56e
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/tmac.m
@@ -0,0 +1,2582 @@
+.\" Version:
+.ds RE 1.16
+.ig
+
+Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+mgm is written by Jörgen Hägg (jh@efd.lth.se)
+
+mgm is free software; you can redistribute 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.
+
+mgm is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Almost complete. The letter format is not included.
+Maybe as a separate package.
+Should be better as time goes.
+
+Please send bugreports with examples to jh@efd.lth.se.
+
+Naming convention stolen from mgs.
+Local names module*name
+Extern names module@name
+Env.var environ:name
+Index array!index
+..
+.warn
+.\" ####### init ######
+.\" Contents level [0:7], contents saved if heading level <= Cl
+.nr Cl 2
+.\" Eject page between LIST OF XXXX if Cp == 0
+.nr Cp 0
+.\" Debugflag
+.if !r D .nr D 0
+.\" Eject after floating display is output [0:1]
+.nr De 0
+.\" Floating keep output [0;5]
+.nr Df 5
+.\" space before and after display if == 1 [0:1]
+.nr Ds 1
+.\" Eject page
+.nr Ej 0
+.\" Eqation lable adjust 0=left, 1=right
+.nr Eq 0
+.\" Em dash string
+.ds EM \-
+.\" Footnote spacing
+.nr Fs 1
+.\" H1-H7 heading counters
+.nr H1 0 1
+.nr H2 0 1
+.nr H3 0 1
+.nr H4 0 1
+.nr H5 0 1
+.nr H6 0 1
+.nr H7 0 1
+.\" Heading break level [0:7]
+.nr Hb 2
+.\" heading centering level, [0:7]
+.nr Hc 0
+.\" header format
+.ds HF 2 2 2 2 2 2 2
+.\" heading temp. indent [0:2]
+.\" 0 -> 0 indent, left margin
+.\" 1 -> indent to right , like .P 1
+.\" 2 -> indent to line up with text part of preceding heading
+.nr Hi 1
+.\" header pointsize
+.ds HP 0 0 0 0 0 0 0
+.\" heading space level [0:7]
+.nr Hs 2
+.\" heading numbering type
+.\" 0 -> multiple (1.1.1 ...)
+.\" 1 -> single
+.nr Ht 0
+.\" Unnumbered heading level
+.nr Hu 2
+.\" hyphenation in body
+.\" 0 -> no hyphenation
+.\" 1 -> hyphenation 14 on
+.nr Hy 1
+.\" text for toc, selfexplanatory. Look in the new variable section
+.ds Lf LIST OF FIGURES
+.nr Lf 1
+.ds Lt LIST OF TABLES
+.nr Lt 1
+.ds Lx LIST OF EXHIBITS
+.nr Lx 1
+.ds Le LIST OF EQUATIONS
+.nr Le 0
+.\" List indent, used by .AL
+.nr Li 6
+.\" List space, if listlevel > Ls then no spacing will occur around lists.
+.nr Ls 99
+.\" Numbering style [0:5]
+.if !r N .nr N 0
+.\" numbered paragraphs
+.\" 0 == not numbered
+.\" 1 == numbered in first level headings.
+.nr Np 0
+.\" Format of figure,table,exhibit,equation titles.
+.\" 0= ". ", 1=" - "
+.nr Of 0
+.\" Page-number, normally same as %.
+.nr P 0
+.\" paragraph indent
+.nr Pi 5
+.\" paragraph spacing
+.nr Ps 1
+.\" paragraph type
+.\" 0 == left-justified
+.\" 1 == indented .P
+.\" 2 == indented .P except after .H, .DE or .LE.
+.nr Pt 0
+.\" Reference title
+.ds Rp REFERENCES
+.\" Display indent
+.nr Si 5
+.\"
+.ds Tm \(tm
+.\"
+.\"---------------------------------------------
+.\" Internal global variables
+.\"
+.\" These two are for cover macro .MT
+.\" Change @langage in the national file.
+.ds @cur-lib /usr/local/lib/groff/tmac
+.\" .ds @language
+.\"
+.\" Current pointsize and vertical space, always in points.
+.nr @ps 10
+.nr @vs 12
+.\" Page length
+.ie r L .nr @pl \n[L]
+.el .nr @pl 11i
+.\" page width
+.ie r W .nr @ll \n[W]
+.el .nr @ll 6i
+.\" page offset
+.ie r O .nr @po \n[O]
+.el .nr @po 1i
+.\"
+.\" cheating...
+.pl \n[@pl]u
+.ll \n[@ll]u
+.lt \n[@ll]u
+.po \n[@po]u
+.nr @cur-ll \n[@ll]
+.\"
+.\" non-zero if escape mechanism is turned off. Used by VERBON/OFF
+.nr @verbose-flag 0
+.\"---------------------------------------------
+.\" New variables
+.\"
+.\" Appendix name
+.ds App APPENDIX
+.\" print appendixheader, 0 == don't
+.nr Aph 1
+.\"
+.\" header prespace level. If level <= Hps, then two lines will be printed
+.\" before the header instead of one.
+.nr Hps 1
+.\"
+.\" These variables controls the number of lines preceding .H.
+.\" Hps1 is the number of lines when level > Hps
+.nr Hps1 0.5v
+.if n .nr Hps1 1v
+.\"
+.\" Hps2 is the number of lines when level >= Hps
+.nr Hps2 1v
+.if n .nr Hps2 2v
+.\"
+.\" flag for mkindex
+.if !r Idxf .nr Idxf 0
+.\" Change these in the national configuration file
+.ds Lifg Figure
+.ds Litb TABLE
+.ds Liex Exhibit
+.ds Liec Equation
+.ds Licon CONTENTS
+.\"
+.\" Lsp controls the height of an empty line. Normally 0.5v
+.\" Normally used for nroff compatibility.
+.nr Lsp 0.5v
+.if n .nr Lsp 1v
+.ds MO1 January
+.ds MO2 February
+.ds MO3 March
+.ds MO4 April
+.ds MO5 May
+.ds MO6 June
+.ds MO7 July
+.ds MO8 August
+.ds MO9 September
+.ds MO10 October
+.ds MO11 November
+.ds MO12 December
+.\" for GETR
+.ds Qrf See chapter \\*[Qrfh], page \\*[Qrfp].
+.\" test for mgm macro. This can be used if the text must test
+.\" what macros is used.
+.\"
+.\" section-page if Sectp > 0
+.nr Sectp 0
+.if (\n[N]=3):(\n[N]=5) \{\
+. nr Sectp 1
+. nr Ej 1
+.\}
+.\" section-figure if Sectf > 0
+.nr Sectf 0
+.if \n[N]=5 .nr Sectf 1
+.\"
+.\" argument to .nm in .VERBON.
+.ds Verbnm "1
+.\" indent for VERBON
+.nr Verbin 5n
+.\"
+.nr .mgm 1
+.\"
+.\"---------------------------------------------
+.\" set local variables.
+.ie d @language .mso mm/\\*[@language]_locale
+.el .mso mm/locale
+.\"---------------------------------------------
+.if \n[D] .tm Groff mm, version \*[RE].
+.\" ####### module init ######
+.\" reset all things
+.de init@reset
+.ie \\n[misc@adjust] 'ad
+.el 'na
+.ie \\n[Hy] 'hy 14
+.el 'nh
+'in 0
+'ti 0
+'ps \\n[@ps]
+'vs \\n[@vs]
+..
+.de @error
+.tm ******************
+.tm ERROR:(\\n[.F]) input line \\n[.c]:\\$*
+.if \\n[D] .backtrace
+.tm ******************
+.ab
+..
+.\" ####### module debug #################################
+.de debug
+.tm \\$1:\\n[.F]:\\n[c.] ll=\\n[.l] vs=\\n[.v] ps=\\n[.s],\\n[.ps] \
+in=\\n[.i] fi=\\n[.u] .d=\\n[.d] nl=\\n[nl] pg=\\n[%]
+..
+.de debug-all
+.nr debug*n 1n
+.nr debug*m 1m
+.tm \\$1:\\n[.F]:\\n[c.] ll=\\n[.l] vs=\\n[.v] ps=\\n[.s] in=\\n[.i]\
+ ad=\\n[.j] fi=\\n[.u] pl=\\n[.p] page=\\n[%] .o=\\n[.o]
+.tm _______ .d=\\n[.d] .f=\\n[.f] .h=\\n[.h] .k=\\n[.k] .n=\\n[.n]\
+ .p=\\n[.p] .t=\\n[.t] .z=\\n[.z] nl=\\n[nl] dn=\\n[dn] n=\\n[debug*n]
+..
+.\" ####### module par #################################
+.nr par@ind-flag 1 \" indent on following P if Pt=2
+.nr hd*last-pos -1
+.nr hd*last-hpos -1
+.nr par*number 0 1
+.af par*number 01
+.nr par*num-count 0 1
+.af par*num-count 01
+.\" reset numbered paragraphs, arg1 = headerlevel
+.de par@reset-num
+.if \\$1<3 .nr par*num-count 0
+.if (\\$1=1)&(\\n[Np]=1) .nr par*number 0
+..
+.\"------------
+.\" paragraph
+.de P
+.\" skip P if previous heading
+.ie !((\\n[nl]=\\n[hd*last-pos]):(\\n[nl]=(\\n[hd*last-pos]-.5v))) \{\
+. if \\n[D]>2 .tm Paragraph
+. par@doit \\$*
+.\}
+.el .if !(\\n[hd*last-hpos]=\\n[.k]) \{\
+. if \\n[D]>2 .tm Paragraph
+. par@doit \\$*
+.\}
+.nr par@ind-flag 1
+..
+.de par@doit
+.SP (u;\\n[Ps]*\\n[Lsp])
+.ie \\n[.$] \{\
+. if \\$1=1 .ti +\\n[Pi]n
+.\}
+.el \{\
+. if \\n[Pt]=1 .ti +\\n[Pi]n
+. if (\\n[Pt]=2)&\\n[par@ind-flag] .ti +\\n[Pi]n
+.\}
+.if \\n[Np] \{\
+\\n[H1].\\n+[par*number]\ \ \c
+.\" $$$ 'br
+.\}
+..
+.\" ####### module line #######################################
+.de SP
+.br
+.if !r line*lp\\n[.z] .nr line*lp\\n[.z] 0
+.if !r line*ac\\n[.z] .nr line*ac\\n[.z] 0
+.ie \\n[.$] .nr line*temp (v;\\$1)
+.el .nr line*temp 1v
+.\"
+.ie \\n[line*lp\\n[.z]]=\\n[.d] \{\
+. \" go here if no output since the last .SP
+. nr line*output \\n[line*temp]-\\n[line*ac\\n[.z]]
+. if \\n[line*output]<0 .nr line*output 0
+. nr line*ac\\n[.z] +\\n[line*output]
+.\}
+.el \{\
+. nr line*ac\\n[.z] \\n[line*temp]
+. nr line*output \\n[line*temp]
+. \" no extra space in the beginning of a page
+. if (\\n[.d]<0):(\\n[pg*head-mark]=\\n[.d]) .nr line*output 0
+.\}
+.if \\n[line*output] .sp \\n[line*output]u
+.nr line*lp\\n[.z] \\n[.d]
+..
+.\" ######## module misc ###############
+.nr misc@adjust 14
+.de SA
+.if \\n[.$] \{\
+. if \\$1-1 .@error "SA: bad arg: \\$1"
+. nr misc@adjust 0\\$1
+.\}
+.ie \\n[misc@adjust] 'ad
+.el 'na
+..
+.\"-------------
+.\" switch environment, keep all important settings.
+.de misc@ev-keep
+.nr misc*ll \\n[.l]
+.ev \\$1
+.ll \\n[misc*ll]u
+.lt \\n[misc*ll]u
+..
+.\"-------------
+.\" .misc@push stackname value
+.de misc@push
+.ie d misc*st-\\$1 .ds misc*st-\\$1 \\$2 \\*[misc*st-\\$1]
+.el .ds misc*st-\\$1 \\$2
+..
+.\"-------------
+.\" .misc@pop stackname
+.\" value returned in the string misc*pop
+.de misc@pop
+.misc@pop-set misc*st-\\$1 \\*[misc*st-\\$1]
+..
+.\"-------------
+.de misc@pop-set
+.ds misc*st-name \\$1
+.shift
+.if \\n[.$]<1 .@error "stack \\*[misc*st-name] empty"
+.ds misc*pop \\$1
+.shift
+.ds \\*[misc*st-name] \\$*
+..
+.\"-------------
+.\" .misc@pop-nr stackname varname
+.de misc@pop-nr
+.misc@pop \\$1
+.nr \\$2 \\*[misc*pop]
+..
+.\"-------------
+.\" .misc@pop-ds stackname varname
+.de misc@pop-ds
+.misc@pop \\$1
+.ds \\$2 \\*[misc*pop]
+..
+.\"-----------
+.\" reset tabs
+.de TAB
+.ta T 5n
+..
+.\"-------------
+.\" .PGFORM linelength [ pagelength [ pageoffset ] ]
+.de PGFORM
+.\" Break here to avoid problems with new linesetting of the previous line.
+.\" Hope this doesn't break anything else :-)
+.br
+.if !''\\$1' .nr @ll \\$1
+.if !''\\$2' .nr @pl \\$2
+.if !''\\$3' .nr @po \\$3
+.ll \\n[@ll]u
+.lt \\n[@ll]u
+.po \\n[@po]u
+.pl \\n[@pl]u
+.nr @cur-ll \\n[@ll]
+.in 0
+.pg@move-trap
+..
+.\"-------------
+.\" .MOVE y [[x] linelength]
+.\" move to line y, indent to x
+.de MOVE
+.if !\\n[.$] .@error "MOVE y [x]: no arguments"
+.if \\n[nl]<0 \c
+.\" move to Y-pos
+.sp |(v;\\$1)
+.\" calc linelength
+.ie \\n[.$]>2 .nr pg*i (n;\\$3)
+.el \{\
+. ie \\n[.$]>1 .nr pg*i (n;\\n[@ll]u-\\$2)
+. el .nr pg*i \\n[@ll]u
+.\}
+.\" move to X-pos, if any
+.if !''\\$2' .po \\$2
+.\" set linelength
+.ll \\n[pg*i]u
+..
+.\"-------------
+.de SM
+.if !\\n[.$] .@error "SM: no arguments"
+.if \\n[.$]=1 \s-1\\$1\s0
+.if \\n[.$]=2 \s-1\\$1\s0\\$2
+.if \\n[.$]=3 \\$1\s-1\\$2\s0\\$3
+..
+.\"-------------
+.nr misc*S-ps \n[@ps]
+.nr misc*S-vs \n[@vs]
+.nr misc*S-ps1 \n[@ps]
+.nr misc*S-vs1 \n[@vs]
+.ds misc*a
+.ds misc*b
+.de S
+.ie !\\n[.$] \{\
+. ds misc*a P
+. ds misc*b P
+.\}
+.el \{\
+. ie \\n[.$]=1 .ds misc*b D
+. el \{\
+. ie \w@\\$2@=0 .ds misc*b C
+. el .ds misc*b \\$2
+. \}
+. ie \w@\\$1@=0 .ds misc*a C
+. el .ds misc*a \\$1
+.\}
+.\"
+.\" set point size
+.if !'\\*[misc*a]'C' \{\
+. ie '\\*[misc*a]'P' .nr @ps \\n[misc*S-ps]
+. el \{\
+. ie '\\*[misc*a]'D' .nr @ps 10
+. el .nr @ps \\*[misc*a]
+. \}
+.\}
+.\"
+.\" set vertical spacing
+.if !'\\*[misc*b]'C' \{\
+. ie '\\*[misc*b]'P' .nr @vs \\n[misc*S-vs]
+. el \{\
+. ie '\\*[misc*b]'D' .nr @vs \\n[@ps]+2
+. el .nr @vs \\*[misc*b]
+. \}
+.\}
+'ps \\n[@ps]
+'vs \\n[@vs]
+.if \\n[D]>1 .tm point-size \\n[@ps] (\\n[.s]), vertical spacing \\n[@vs] (\\n[.v])
+.nr misc*S-ps \\n[misc*S-ps1]
+.nr misc*S-vs \\n[misc*S-vs1]
+.nr misc*S-ps1 \\n[@ps]
+.nr misc*S-vs1 \\n[@vs]
+..
+.\"------------
+.de HC
+.ev 0
+.hc \\$1
+.ev
+.ev 1
+.hc \\$1
+.ev
+.ev 2
+.hc \\$1
+.ev
+..
+.\"------------
+.de RD
+.di misc*rd
+'fl
+.rd \\$1
+.br
+.di
+.ie !''\\$3' \{\
+. di misc*rd2
+. ds \\$3 "\\*[misc*rd]
+. br
+. di
+.\}
+.if !''\\$2' .rn misc*rd \\$2
+.rm misc*rd misc*rd2
+..
+.\"------------
+.\" VERBON [flag [pointsize [font]]]
+.\" flag
+.\" bit function
+.\" 0 escape on
+.\" 1 add an empty line before verbose text
+.\" 2 add an empty line after verbose text
+.\" 4 numbered lines (controlled by the string Verbnm)
+.\" 8 indent text by the numbervariable Verbin.
+.de VERBON
+.nr misc*verb 0\\$1
+.if (0\\n[misc*verb]%4)/2 .SP \\n[Lsp]u
+.br
+.misc@ev-keep misc*verb-ev
+.nf
+.if (0\\n[misc*verb]%16)/8 .nm \\*[Verbnm]
+.ie !'\\$3'' .ft \\$3
+.el .ft CR
+.ss 12
+.ta T 8u*\w@n@u
+.if 0\\$2 \{\
+. ps \\$2
+. vs \\$2
+.\}
+.if (0\\n[misc*verb]%32)/16 .in +\\n[Verbin]u
+.if !(0\\n[misc*verb]%2) \{\
+. eo
+. nr @verbose-flag 1 \" tell pageheader to set ec/eo
+.\}
+..
+.de VERBOFF
+.ec
+.if (0\\n[misc*verb]%8)/4 .SP \\n[Lsp]u
+.if (0\\n[misc*verb]%16)/8 .nm
+.if (0\\n[misc*verb]%32)/16 .in
+.ev
+.nr @verbose-flag 0
+..
+.\" ######## module acc #################
+.\"-----------
+.\" accents. These are copied from mgs, written by James Clark.
+.de acc@over-def
+.ds \\$1 \Z'\v'(u;\w'x'*0+\En[rst]-\En[.cht])'\
+\h'(u;-\En[skw]+(-\En[.w]-\w'\\$2'/2)+\En[.csk])'\\$2'
+..
+.de acc@under-def
+.ds \\$1 \Z'\v'\En[.cdp]u'\h'(u;-\En[.w]-\w'\\$2'/2)'\\$2'
+..
+.acc@over-def ` \`
+.acc@over-def ' \'
+.acc@over-def ^ ^
+.acc@over-def ~ ~
+.acc@over-def : \(ad
+.acc@over-def ; \(ad
+.acc@under-def , \(ac
+.\" ######## module uni #################
+.\" unimplemented macros
+.de OK
+.tm "OK: not implemented"
+..
+.de PM
+.tm "PM: not implemented"
+..
+.\" ######## module hd #################
+.\" support for usermacro
+.nr hd*h1-page 1 \" last page-number for level 1 header.
+.nr hd*htype 0
+.ds hd*sect-pg
+.ds hd*mark
+.ds hd*suf-space
+.nr hd*need 0
+.aln ;0 hd*htype
+.als }0 hd*mark
+.als }2 hd*suf-space
+.aln ;3 hd*need
+.\"-------------
+.\" .hd@split varable index name val1 val2 ...
+.de hd@split
+.if \\$2>(\\n[.$]-3) .@error "\\$3 must have at least \\$2 values (\\*[\\$3]).
+.nr hd*sp-tmp \\$2+3
+.ds \\$1 \\$[\\n[hd*sp-tmp]]
+..
+.de HU
+.H 0 "\\$1"
+..
+.\"-------------
+.de H
+.if !r hd*cur-bline .nr hd*cur-bline \\n[nl]
+.br
+.ds@print-float 2\" $$$ could be wrong...
+.\" terminate all lists
+.LC 0
+.init@reset
+.nr hd*level 0\\$1
+.nr hd*arg1 0\\$1
+.if !\\n[hd*level] .nr hd*level \\n[Hu]
+.\"
+.\" clear lower counters
+.nr hd*i 1 1
+.while \\n+[hd*i]<8 .if \\n[hd*level]<\\n[hd*i] .nr H\\n[hd*i] 0 1
+.\"
+.\" Check if it's time for new page. Only if text has
+.\" appeared before.
+.if \\n[Ej]&(\\n[Ej]>=\\n[hd*level])&(\\n[nl]>\\n[hd*cur-bline]) .pg@next-page
+.\"
+.\" increment current counter
+.nr H\\n[hd*level] +1
+.\"
+.\" if level==1 -> prepare for new section.
+.if \\n[hd*level]=1 .rr hd*h1-page
+.\"
+.\"
+.\" hd*mark is the text written to the left of the header.
+.ds hd*mark \\n[H1].
+.\"
+.if \\n[hd*level]>1 .as hd*mark \\n[H2]
+.\"
+.nr hd*i 2 1
+.while \\n+[hd*i]<8 .if \\n[hd*level]>(\\n[hd*i]-1) .as hd*mark .\\n[H\\n[hd*i]]
+.if \\n[Ht] .ds hd*mark \\n[H\\n[hd*level]].
+.\"
+.\" toc-mark is sent to the table of contents
+.ds hd*toc-mark \\*[hd*mark]
+.as hd*mark \ \ \" add spaces between mark and heading
+.if !\\n[hd*arg1] \{\
+. ds hd*mark\" no mark for unnumbered
+. ds hd*toc-mark
+.\}
+.\"
+.if \\n[D]>1 .tm At header \\*[hd*toc-mark] "\\$2"
+.nr hd*htype 0 \" hd*htype = check break and space
+. \" 0 = run-in, 1 = break only, 2 = space
+.if \\n[hd*level]<=\\n[Hb] .nr hd*htype 1
+.if \\n[hd*level]<=\\n[Hs] .nr hd*htype 2
+. \" two spaces if hd*htype == 0
+.ie (\\n[hd*htype]=0)&(\w@\\$2@) .ds hd*suf-space " \"
+.el .ds hd*suf-space
+.nr hd*need 2v \" hd*need = header need space
+.if \\n[hd*htype]<2 .nr hd*need +\\n[Lsp]u \" add some extra space
+.\"---------- user macro HX ------------
+.\" User exit macro to override numbering.
+.\" May change hd*mark (}0), hd*suf-space (}2) and hd*need (;3)
+.\" Can also change Hps1/2.
+.if d HX .HX \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
+.\"--------------------------------------
+.\" pre-space
+.ie \\n[hd*level]<=\\n[Hps] .SP \\n[Hps2]u
+.el .SP \\n[Hps1]u
+.\"
+.par@reset-num \\n[hd*level]\" reset numbered paragraph
+.\" start diversion to measure size of header
+.di hd*div
+\\*[hd*mark]\\$2\\$3\\*[hd*suf-space]
+.br
+.di
+.rm hd*div
+.ne \\n[hd*need]u+\\n[dn]u+.5p \" this is the needed space for a header
+.if \\n[hd*htype] .na \" no adjust if run-in
+.\"
+.\" size and font calculations
+.hd@split hd*font \\n[hd*level] HF \\*[HF]\" get font for this level
+.ft \\*[hd*font]\" set new font
+.hd@split hd*new-ps \\n[hd*level] HP \\*[HP]\" get point size
+.ie (\\*[hd*new-ps]=0):(\w@\\*[hd*new-ps]@=0) \{\
+. if \\n[hd*htype] \{\
+. if '\\*[hd*font]'3' \{\
+. ps -1
+. vs -1
+. \}
+. if '\\*[hd*font]'B' \{\
+. ps -1
+. vs -1
+. \}
+. \}
+.\}
+.el \{\
+. ps \\*[hd*new-ps]
+. vs \\*[hd*new-ps]+2
+.\}
+.\"
+.\"---------- user macro HY -------------
+.\" user macro to reset indents
+.if d HY .HY \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
+.\"--------------------------------------
+.nr hd*mark-size \w@\\*[hd*mark]@
+.if (\\n[hd*level]<=\\n[Hc])&\\n[hd*htype] .ce\" center if level<=Hc
+.\"
+.\" finally, output the header
+\\*[hd*mark]\&\c
+.\" and the rest of the header
+.ie \\n[hd*htype] \{\
+\\$2\\$3
+. br
+.\}
+.el \\$2\\$3\\*[hd*suf-space]\&\c
+.ft 1
+.\" restore pointsize and vertical size.
+.ps \\n[@ps]
+.vs \\n[@vs]
+.\"
+.\" table of contents
+.if (\\n[hd*level]<=\\n[Cl])&\w@\\$2@ \{\
+. ie \\n[Sectp] \{\
+. toc@save \\n[hd*level] "\\*[hd*toc-mark]" "\\$2" \\*[hd*sect-pg]
+. \}
+. el .toc@save \\n[hd*level] "\\*[hd*toc-mark]" "\\$2" \\n[%]
+.\}
+.\" set adjust to previous value
+.SA
+.\" do break or space
+.if \\n[hd*htype] .br
+.if \\n[hd*htype]>1 .SP \\n[Lsp]u
+.if \\n[hd*htype] \{\
+. \" indent if Hi=1 and Pt=1
+. if (\\n[Hi]=1)&(\\n[Pt]=1) .ti +\\n[Pi]n
+. \" indent size of mark if Hi=2
+. if \\n[hd*htype]&(\\n[Hi]>1) .ti +\\n[hd*mark-size]u
+.\}
+.nr par@ind-flag 0 \" no indent on .P if Pt=2
+.\"
+.\" check if it is time to reset footnotes
+.if (\\n[hd*level]=1)&\\n[ft*clear-at-header] .nr ft*nr 0 1
+.\"
+.\" check if it is time to reset indexes
+.if (\\n[hd*level]=1)&\\n[Sectf] \{\
+. nr lix*fg-nr 0 1
+. nr lix*tb-nr 0 1
+. nr lix*ec-nr 0 1
+. nr lix*ex-nr 0 1
+.\}
+.\"---------- user macro HZ ----------
+.if d HZ .HZ \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
+.nr hd*last-pos \\n[nl]
+.nr hd*last-hpos \\n[.k]
+.nr par@ind-flag 0
+..
+.\"--------
+.de HM
+.nr hd*i 0 1
+.while \\n+[hd*i]<8 .af H\\n[hd*i] \\$[\\n[hd*i]] 1
+..
+.\"----------------------
+.\" set page-nr, called from header
+.\"
+.de hd@set-page
+.if !r hd*h1-page .nr hd*h1-page \\n[%]
+.\"
+.ie \\n[Sectp] .nr P \\n[%]-\\n[hd*h1-page]+1
+.el .nr P \\n[%]
+.\"
+.\" Set section-page-string
+.ds hd*sect-pg \\n[H1]-\\n[P]
+..
+.\"########### module pg ####################
+.\" set end of text trap
+.wh 0 pg@header
+.em pg@end-of-text
+.\"
+.ie \n[N]=4 .ds pg*header ''''
+.el .ds pg*header ''- % -''
+.ds pg*even-footer
+.ds pg*odd-footer
+.ds pg*even-header
+.ds pg*odd-header
+.ds pg*footer
+.\"
+.nr pg*top-margin 0
+.nr pg*foot-margin 0
+.nr pg*block-size 0
+.nr pg*footer-size 5\" 1v+footer+even/odd footer+2v
+.nr pg*header-size 7\" 3v+header+even/odd header+2v
+.nr pg*extra-footer-size 0
+.nr pg*extra-header-size 0
+.nr ft*note-size 0
+.nr pg*cur-column 0
+.nr pg*cols-per-page 1
+.nr pg*cur-po \n[@po]
+.nr pg*head-mark 0
+.\"
+.nr pg*ps \n[@ps]
+.nr pg*vs \n[@vs]
+.\"-------------------------
+.\" footer traps: set, enable and disable
+.de pg@set-new-trap
+.nr pg*foot-trap \\n[@pl]u-(\\n[pg*block-size]u+\\n[ft*note-size]u+\\n[pg*foot-margin]u+\\n[pg*footer-size]v+\\n[pg*extra-footer-size]u)
+.if \\n[D]>2 .tm pg*foot-trap \\n[@pl]u-(\\n[pg*block-size]u+\\n[ft*note-size]u+\\n[pg*foot-margin]u+\\n[pg*footer-size]v) = \\n[pg*foot-trap]
+.\" last-pos points to the position of the footer and bottom
+.\" block below foot-notes.
+.nr pg*last-pos \\n[@pl]u-(\\n[pg*block-size]u+\\n[pg*foot-margin]u+\\n[pg*footer-size]v)
+..
+.de pg@enable-trap
+.wh \\n[pg*foot-trap]u pg@footer
+.if \\n[D]>2 .tm pg@enable-trap .t=\\n[.t] nl=\\n[nl]
+..
+.de pg@disable-trap
+.ch pg@footer
+..
+.\" move to new trap (if changed).
+.de pg@move-trap
+.pg@disable-trap
+.pg@set-new-trap
+.pg@enable-trap
+..
+.de pg@enable-top-trap
+.\" set trap for pageheader.
+.nr pg*top-enabled 1
+..
+.de pg@disable-top-trap
+.\" remove trap for pageheader.
+.nr pg*top-enabled 0
+..
+.\" no header on the next page
+.de PGNH
+.nr pg*top-enabled -1
+..
+.\" set first trap for pagefooter
+.pg@enable-top-trap
+.pg@set-new-trap
+.pg@enable-trap
+.\"-------------------------
+.\" stop output and begin on next page. Fix footnotes and all that.
+.de pg@next-page
+.\".debug next-page
+.ne 999i \" activate trap
+.\" .pg@footer
+..
+.\"-------------------------
+.\" support for PX and TP
+.als }t pg*header
+.als }e pg*even-header
+.als }o pg*odd-header
+.\"------------------------------------------------------------
+.\" HEADER
+.de pg@header
+.if \\n[D]>1 .tm Page# \\n[%] (\\n[.F]:\\n[c.])
+.if \\n[Idxf] \{\
+.tl '<pagenr\ \\n[%]>'''
+.\}
+.\" assign current page-number to P
+.hd@set-page
+.\"
+.\" suppress pageheader if pagenumber == 1 and N == [124]
+.if \\n[pg*top-enabled] \{\
+. if \\n[pg*extra-header-size] 'sp \\n[pg*extra-header-size]u
+. if \\n[pg*top-margin] 'sp \\n[pg*top-margin]u
+. ev pg*tl-ev
+. pg@set-env
+. ie !d TP \{\
+' sp 3
+. lt \\n[@ll]u
+. ie ((\\n[%]=1)&(\\n[N]=1):(\\n[N]=2)) .sp
+. el .tl \\*[pg*header]
+. ie o .tl \\*[pg*odd-header]
+. el .tl \\*[pg*even-header]
+' sp 2
+. \}
+. el .TP
+. ev
+. \" why no-space??
+. if d PX \{\
+. ns
+. PX
+. rs
+. \}
+. \" check for pending footnotes
+. ft@check-old
+. \"
+. \" back to normal text processing
+. \" .pg@enable-trap
+. \" mark for multicolumn
+. nr pg*head-mark \\n[nl]u
+. \" set multicolumn
+. \"
+. pg@set-po
+. \" print floating displays
+. ds@print-float 4
+. tbl@top-hook
+. ns
+.\}
+.if \\n[pg*top-enabled]<0 .nr pg*top-enabled 1
+.nr hd*cur-bline \\n[nl] \" .H needs to know if output has occured
+..
+.\"---------------------------------------------------------
+.\" FOOTER
+.de pg@footer
+.ec
+.if \\n[D]>2 .tm Footer# \\n[%] (\\n[.F]:\\n[c.])
+.pg@disable-trap
+.\".debug footer
+.tbl@bottom-hook
+.\" increment pageoffset for MC
+.\" move to the exact start of footer.
+'sp |\\n[pg*foot-trap]u+1v
+.\"
+.if \\n[D]>3 .tm FOOTER after .sp
+.\" print footnotes
+.if d ft*div .ft@print
+.\"
+.pg@inc-po
+.if !\\n[pg*cur-column] .pg@print-footer
+.\" next column
+.pg@set-po
+.pg@enable-trap
+.if \\n[@verbose-flag] .eo \" to help VERBON/VERBOFF
+..
+.\"-------------------------
+.de pg@print-footer
+.\" jump to the position just below the foot-notes.
+'sp |\\n[pg*last-pos]u+1v
+.\" check if there are any bottom block
+.if d pg*block-div .pg@block
+.\"
+.\" print the footer and eject new page
+.ev pg*tl-ev
+.pg@set-env
+.lt \\n[@ll]u
+.ie o .tl \\*[pg*odd-footer]
+.el .tl \\*[pg*even-footer]
+.ie (\\n[%]=1)&(\\n[N]=1) .tl \\*[pg*header]
+.el .tl \\*[pg*footer]
+.ev
+.ie (\\n[ds*fnr]>=\\n[ds*o-fnr]):\\n[ft*exist] \{\
+. ev ne
+' bp
+. ev
+.\}
+.el 'bp
+..
+.\"-------------------------
+.\"
+.\" Initialize the title environment
+.de pg@set-env
+'na
+'nh
+'in 0
+'ti 0
+'ps \\n[pg*ps]
+'vs \\n[pg*vs]
+..
+.\"-------------------------
+.de PH
+.ds pg*header "\\$1
+.pg@set-new-size
+..
+.de PF
+.ds pg*footer "\\$1
+.pg@set-new-size
+..
+.de OH
+.ds pg*odd-header "\\$1
+.pg@set-new-size
+..
+.de EH
+.ds pg*even-header "\\$1
+.pg@set-new-size
+..
+.de OF
+.ds pg*odd-footer "\\$1
+.pg@set-new-size
+..
+.de EF
+.ds pg*even-footer "\\$1
+.pg@set-new-size
+..
+.de pg@clear-hd
+.ds pg*even-header
+.ds pg*odd-header
+.ds pg*header
+..
+.de pg@clear-ft
+.ds pg*even-footer
+.ds pg*odd-footer
+.ds pg*footer
+..
+.de pg@set-new-size
+.nr pg*ps \\n[@ps]
+.nr pg*vs \\n[@vs]
+.pg@move-trap
+..
+.\"-------------------------
+.\" end of page processing
+.de pg@footnotes
+.\".debug footnotes
+.\" output footnotes. set trap for block
+.\"
+..
+.\"-------------------------
+.\" print bottom block
+.de pg@block
+.ev pg*block-ev
+'nf
+'in 0
+.ll 100i
+.pg*block-div
+.br
+.ev
+..
+.\"-------------------------
+.\" define bottom block
+.de BS
+.misc@ev-keep pg*block-ev
+.init@reset
+.br
+.di pg*block-div
+..
+.\"-------------------------
+.de BE
+.br
+.di
+.nr pg*block-size \\n[dn]u
+.ev
+.pg@move-trap
+..
+.\"-------------------------
+.\" print out all pending text
+.de pg@end-of-text
+.if \\n[D]>2 .tm ---------- End of text processing ----------------
+.ds@eot-print
+.ref@eot-print
+..
+.\"-------------------------
+.\" set top and bottom margins
+.de VM
+.if \\n[.$]=0 \{\
+. nr pg*extra-footer-size 0
+. nr pg*extra-header-size 0
+.\}
+.if \\n[.$]>0 .nr pg*extra-header-size (v;\\$1)
+.if \\n[.$]>1 .nr pg*extra-footer-size (v;\\$2)
+.if \\n[D]>2 \{\
+. tm extra top \\n[pg*extra-footer-size]
+. tm extra bottom \\n[pg*extra-header-size]
+.\}
+.pg@move-trap
+..
+.\"---------------------
+.\" multicolumn output.
+.de pg@set-po
+.if \\n[pg*cols-per-page]>1 \{\
+. ll \\n[pg*column-size]u
+.\}
+..
+.de pg@inc-po
+.if \\n[pg*cols-per-page]>1 \{\
+. ie \\n+[pg*cur-column]>=\\n[pg*cols-per-page] \{\
+. nr pg*cur-column 0 1
+. nr pg*cur-po \\n[@po]u
+. po \\n[@po]u
+. ll \\n[@ll]u
+. \}
+. el \{\
+. nr pg*cur-po +(\\n[pg*column-size]u+\\n[pg*column-sep]u)
+. po \\n[pg*cur-po]u
+' sp |\\n[pg*head-mark]u
+. tbl@top-hook
+. \}
+.\}
+..
+.de 1C
+.br
+.if \\n[pg*cols-per-page]<=1 .@error "1C: multicolumn mode not active"
+.nr pg*cols-per-page 1
+.nr pg*column-sep 0
+.nr pg*column-size \\n[@ll]
+.nr pg*cur-column 0 1
+.nr pg*cur-po \\n[@po]u
+.PGFORM
+.\".pg@next-page
+.SK
+..
+.de 2C
+.br
+.nr pg*head-mark \\n[nl]u
+.if \\n[pg*cols-per-page]>1 .@error "2C: multicolumn mode already active"
+.nr pg*cols-per-page 2
+.nr pg*column-sep \\n[@ll]/15
+.nr pg*column-size (\\n[@ll]u*7)/15
+.nr pg*cur-column 0 1
+.nr pg*cur-po \\n[@po]u
+.ll \\n[pg*column-size]u
+.lt \\n[pg*column-size]u
+..
+.\" MC column-size [ column-separation ]
+.de MC
+.br
+.nr pg*head-mark \\n[nl]u
+.if \\n[pg*cols-per-page]>1 .@error "MC: multicolumn mode already active"
+.ie ''\\$1' .nr pg*column-size \\n[.l]
+.el .nr pg*column-size (n;\\$1)
+.ie ''\\$2' .nr pg*column-sep \\n[pg*column-size]/15
+.el .nr pg*column-sep (n;\\$2)
+.\"
+.nr pg*cols-per-page (u;\\n[.l]/(\\n[pg*column-size]+\\n[pg*column-sep]+1))
+.nr pg*cur-column 0 1
+.nr pg*cur-po \\n[@po]u
+.ll \\n[pg*column-size]u
+.lt \\n[pg*column-size]u
+..
+.\" begin a new column
+.de NCOL
+.br
+.pg@footer
+..
+.\" skip pages
+.de SK
+.br
+.bp
+.nr pg*i 0 1
+.\" force new page by writing something invisible.
+.while \\n+[pg*i]<=(0\\$1) \{\
+\&
+. bp
+.\}
+..
+.\"-------------------------------
+.\" MULB width1 space1 width2 space2 width3 space3 ...
+.de MULB
+.br
+.nr pg*i 0 1
+.nr pg*mul-x 0 1
+.nr pg*mul-ind 0
+.nr pg*mul-last 0
+.while \\n[.$] \{\
+. nr pg*mul!\\n+[pg*i] (n;0\\$1)
+. nr pg*muls!\\n[pg*i] (n;0\\$2)
+. shift 2
+.\}
+.nr pg*mul-max-col \\n[pg*i]
+.ds pg*mul-fam \\n[.fam]
+.nr pg*mul-font \\n[.f]
+.ev pg*mul-ev
+.fam \\*[pg*mul-fam]
+.ft \\n[pg*mul-font]
+.fi
+.hy 14
+.di pg*mul-div
+.MULN
+..
+.\"-----------
+.de MULN
+.if \\n[pg*mul-x]>=\\n[pg*mul-max-col] .@error "MULN: Undefined columnwidth"
+.br
+.if \\n[.d]>\\n[pg*mul-last] .nr pg*mul-last \\n[.d]
+.rt +0
+.in \\n[pg*mul-ind]u
+.ll (u;\\n[.i]+\\n[pg*mul!\\n+[pg*mul-x]])u
+.nr pg*mul-ind +(u;\\n[pg*mul!\\n[pg*mul-x]]+\\n[pg*muls!\\n[pg*mul-x]])
+..
+.\"-----------
+.\" MULE
+.de MULE
+.br
+.if \\n[.d]>\\n[pg*mul-last] .nr pg*mul-last \\n[.d]
+.di
+.ev
+.ne \\n[pg*mul-last]u
+.nf
+.mk
+.pg*mul-div
+.rt
+.sp \\n[pg*mul-last]u
+.fi
+..
+.\"-----------
+.de OP
+.br
+.ie o .if !\\n[pg*head-mark]=\\n[nl] \{\
+. bp +1
+. bp +1
+.\}
+.el .bp
+..
+.\"########### module footnotes ###################
+.nr ft*note-size 0
+.nr ft*busy 0
+.nr ft*nr 0 1
+.nr ft*wide 0
+.nr ft*hyphen 0\" hyphenation value
+.nr ft*adjust 1\" >0 if adjust true
+.nr ft*indent 1\" >0 if text indent true (not imp. $$$)
+.nr ft*just 0\" 0=left justification, 1=right (not imp. $$$)
+.nr ft*exist 0\" not zero if there are any footnotes to be printed
+.nr ft*clear-at-header 0\" >0 if footnotes should be reset at first level head.
+.\"
+.ds F \v'-.4m'\s-3\\n+[ft*nr]\s0\v'.4m'
+.\"
+.\"-----------------
+.\" init footnote environment
+.de ft@init
+.\" indentcontrol not implemented $$$
+.\" label justification not implemented $$$
+'in 0
+'fi
+.ie \\n[ft*adjust] 'ad
+.el 'na
+.ie \\n[ft*hyphen] 'hy 14
+.el 'hy 0
+.ll \\n[@cur-ll]u
+.lt \\n[@cur-ll]u
+.ps (\\n[@ps]-2)
+.vs (\\n[@vs]-1)
+..
+.\"-----------------
+.\" set footnote format
+.\" no support for two column processing (yet). $$$
+.de FD
+.if \\n[.$]=0 .@error "FD: bad arg \\$1"
+.ie \\n[.$]=2 .nr ft*clear-at-header 1
+.el .nr ft*clear-at-header 0
+.\"
+.if !'\\$1'' \{\
+. ie \\$1>11 .nr ft*format 0
+. el .nr ft*format \\$1
+. \"
+. nr ft*hyphen (\\n[ft*format]%2)*14
+. nr ft*format \\n[ft*format]/2
+. \"
+. nr ft*adjust 1-(\\n[ft*format]%2)
+. nr ft*format \\n[ft*format]/2
+. \"
+. nr ft*indent 1-(\\n[ft*format]%2)
+. nr ft*format \\n[ft*format]/2
+. \"
+. nr ft*just \\n[ft*format]%2
+.\}
+..
+.\"---------------
+.\" Footnote and display width control $$$
+.de WC
+.nr ft*i 0 1
+.while \\n+[ft*i]<=\\n[.$] \{\
+. ds ft*x \\$[\\n[ft*i]]
+. if '\\*[ft*x]'N' \{\
+. nr ft*wide 0
+. nr ft*first-fn 0
+. nr ds*wide 0
+. nr ds*float-break 1
+. \}
+. if '\\*[ft*x]'-WF' .nr ft*wide 0
+. if '\\*[ft*x]'WF' .nr ft*wide 1
+. if '\\*[ft*x]'-FF' .nr ft*first-fn 0
+. if '\\*[ft*x]'FF' .nr ft*first-fn 1
+. if '\\*[ft*x]'-WD' .nr ds*wide 0
+. if '\\*[ft*x]'WD' .nr ds*wide 1
+. if '\\*[ft*x]'-FB' .nr ds*float-break 0
+. if '\\*[ft*x]'FB' .nr ds*float-break 1
+.\}
+..
+.\"-----------------
+.\" begin footnote
+.de FS
+.if \\n[ft*busy] .@error "FS: missing FE"
+.nr ft*busy 1
+.ev ft*ev
+.ft@init
+.if !\\n[ft*wide] .pg@set-po
+.if !d ft*div .ft@init-footnote
+.di ft*tmp-div
+.nr ft*space (u;\\n[Fs]*\\n[Lsp])
+.sp \\n[ft*space]u
+.\" print mark
+.ie \\n[.$] .ds ft*mark \\$1
+.el .ds ft*mark \\n[ft*nr].
+\\*[ft*mark]
+.in +.75c
+.sp -1
+.nr ft*exist 1
+..
+.\"-----------------
+.\" init footnote diversion
+.de ft@init-footnote
+.di ft*div
+\l'20n'
+.br
+.di
+.nr ft*note-size \\n[dn]
+..
+.\"-----------------
+.\" end footnote
+.de FE
+.nr ft*busy 0
+.br
+.di
+'in 0
+'nf
+.if \\n[@pl]u<\\n[dn]u .@error "FE: too big footnote"
+.ie (\\n[pg*foot-trap]u-\\n[.d]u)<\\n[dn]u \{\
+. da ft*next-div
+. ft*tmp-div
+. br
+. di
+.\}
+.el \{\
+. da ft*div
+. ft*tmp-div
+. di
+. nr ft*note-size +\\n[dn]
+.\}
+.rm ft*tmp-div
+.ev
+.pg@move-trap
+..
+.\"-----------------
+.\" print footnotes, see pg@footer
+.de ft@print
+.ev ft*print-ev
+'nf
+'in 0
+.ll 100i
+.ft*div
+.br
+.ev
+.rm ft*div
+.nr ft*note-size 0
+.pg@move-trap
+..
+.\"-----------------
+.\" check if any pending footnotes, see pg@header
+.de ft@check-old
+.if d ft*next-div \{\
+. ev ft*ev
+. ft@init
+. ft@init-footnote
+. nf
+. in 0
+. da ft*div
+. ft*next-div
+. di
+. nr ft*note-size +\\n[dn]
+. rm ft*next-div
+. ev
+. nr ft*exist 0
+. pg@move-trap
+.\}
+..
+.\"########### module display ###################
+.nr ds*wide 0\" >0 if wide displays wanted
+.nr ds*fnr 0 1\" floating display counter
+.nr ds*o-fnr 1\" floating display counter, already printed
+.nr ds*snr 0 1\" static display counter
+.nr ds*lvl 0 1\" display level
+.nr ds*float-busy 0\" >0 if printing float
+.nr ds*ffloat 0\" >0 if DF, 0 if DS
+.\" static display start
+.\" nested DS/DE is allowed. No limit on depth.
+.de DS
+.br
+.ds@start 0 DS \\$@
+..
+.\" floating display start
+.\" nested DF/DE is not allowed.
+.de DF
+.if \\n[ds*lvl] .@error "DF:nested floating is not allowed. Use DS."
+.ds@start 1 DF \\$@
+..
+.\"---------------
+.nr ds*format 0\" dummy value for .En/.EQ
+.nr ds*format! 0\" no indent
+.nr ds*format!0 0\" no indent
+.nr ds*format!L 0\" no indent
+.nr ds*format!I 1\" indent
+.nr ds*format!1 1\" indent
+.nr ds*format!C 2\" center each line
+.nr ds*format!2 2\" center each line
+.nr ds*format!CB 3\" center as block
+.nr ds*format!3 3\" center as block
+.nr ds*format!R 4\" right justify each line
+.nr ds*format!4 4\" right justify each line
+.nr ds*format!RB 5\" right justify as block
+.nr ds*format!5 5\" right justify as block
+.\"---------------
+.nr ds*fill! 0\" no fill
+.nr ds*fill!N 0\" no fill
+.nr ds*fill!0 0\" no fill
+.nr ds*fill!F 1\" fill on
+.nr ds*fill!1 1\" fill on
+.\"---------------
+.de ds@start
+.nr ds*ffloat \\$1
+.ds ds*type \\$2
+.shift 2
+.nr ds*lvl +1
+.\" get format of the display
+.ie \\n[.$] \{\
+. ie r ds*format!\\$1 .nr ds*format \\n[ds*format!\\$1]
+. el .@error "\\*[ds*type]:wrong format:\\$1"
+.\}
+.el .nr ds*format 0
+.\" fill or not to fill, that is the...
+.nr ds*fill 0
+.ie \\n[.$]>1 \{\
+. ie r ds*fill!\\$2 .nr ds*fill \\n[ds*fill!\\$2]
+. el .@error "\\*[ds*type]:wrong fill:\\$2"
+.\}
+.nr ds*rindent 0
+.if \\n[.$]>2 .nr ds*rindent \\$3
+.\"
+.\"---------------
+.nr ds*old-ll \\n[.l]
+.misc@push ds-ll \\n[.l]
+.misc@push ds-form \\n[ds*format]
+.misc@push ds-ffloat \\n[ds*ffloat]
+.nr ds*i \\n[.i]
+.nr ds*ftmp \\n[.f]
+.misc@ev-keep ds*ev!\\n+[ds*snr]
+.ft \\n[ds*ftmp]
+.\"
+.init@reset
+'in \\n[ds*i]u
+.di ds*div!\\n[ds*snr]
+.\"
+.ll \\n[ds*old-ll]u
+.lt \\n[ds*old-ll]u
+.if \\n[ds*rindent] \{\
+. ll -\\n[ds*rindent]n
+. lt -\\n[ds*rindent]n
+.\}
+.if \\n[ds*wide] \{\
+. ll \\n[@ll]u
+. lt \\n[@ll]u
+.\}
+.\"
+.ie \\n[ds*fill] 'fi
+.el 'nf
+.\"
+.if \\n[ds*format]=1 \{\
+. ll -\\n[Si]n
+. lt -\\n[Si]n
+' in +\\n[Si]n
+.\}
+.if (\\n[ds*format]=3):(\\n[ds*format]=5) 'in 0
+..
+.\"---------------
+.de DE
+.if \\n-[ds*lvl]<0 .@error "DE: no corresponding DS or DF"
+.br
+.if \\n[ds*ffloat] .SP \\n[Lsp]u
+.di
+.nr ds*width \\n[dl]
+.nr ds*height \\n[dn]
+.misc@pop-nr ds-ll ds*old-ll
+.misc@pop-nr ds-form ds*format
+.misc@pop-nr ds-ffloat ds*ffloat
+.if (\\n[ds*format]>=2)&(\\n[ds*width]>\\n[ds*old-ll]) \{\
+. @error "DE: display too wide for current line-length"
+.\}
+.\" prepare copy to floating display
+.if \\n[ds*ffloat] .di ds*fdiv!\\n+[ds*fnr]
+.\"
+'in 0
+'nf
+.if \\n[ds*format]=2 'ce 9999
+.if \\n[ds*format]=3 'in (u;(\\n[ds*old-ll]-\\n[ds*width])/2)
+.if \\n[ds*format]=4 'rj 9999
+.if \\n[ds*format]=5 'in (u;\\n[ds*old-ll]-\\n[ds*width])
+.\"
+.ie !\\n[ds*ffloat] \{\
+. \"
+. \" Print static display
+. \" Eject page if display will fit one page and
+. \" there are less than half of the page left.
+. nr ds*i \\n[pg*foot-trap]-\\n[pg*header-size]v-\\n[pg*extra-header-size]v
+. if (\\n[ds*height]>\\n[ds*i])&(\\n[.t]<(\\n[ds*i]/2)) \{\
+. ne \\n[.t]u+1v
+. \}
+. if (\\n[ds*height]<\\n[ds*i])&(\\n[.t]<(\\n[ds*height])) \{\
+. ne \\n[.t]u+1v
+. \}
+. if \\n[Ds] .SP \\n[Lsp]u
+.\}
+.el .SP \\n[Lsp]u
+.ds*div!\\n[ds*snr]
+.ie !\\n[ds*ffloat] .if \\n[Ds] .SP \\n[Lsp]u
+.el \{\
+. SP \\n[Lsp]u
+. di
+.\}
+.if \\n[ds*format]=2 'ce 0
+.if \\n[ds*format]=4 'rj 0
+.rm ds*div!\\n[ds*snr]
+.nr ds*snr -1
+.nr par@ind-flag 0
+.\" move div to the floating display list
+.ev
+.if \\n[ds*ffloat] \{\
+. nr ds*fsize!\\n[ds*fnr] \\n[dn]
+. \" print float if queue is empty and the display fits into
+. \" the current page
+. if (\\n[ds*fnr]>\\n[ds*o-fnr])&(\\n[ds*height]<\\n[.t]) \{\
+. ds@print-float 1
+. \}
+.\}
+..
+.\"-------------
+.\" called by end-of-text
+.de ds@eot-print
+.if \\n[ds*o-fnr]<=\\n[ds*fnr] \{\
+. if \\n[D]>2 .tm Print remaining displays.
+.\" still some floats left, make non-empty environment
+. misc@ev-keep ne
+. init@reset
+\c
+. ds@print-float 3
+. ev
+.\}
+..
+.\"---------------
+.\" print according to Df and De.
+.\" .ds@print-float type
+.\" type called from
+.\" 1 .DE
+.\" 2 end of section
+.\" 3 end of document
+.\" 4 beginning of new page
+.\"
+.de ds@print-float
+.if \\n[Df]>5 .@error "Df=\\n[Df], max value is 5"
+.if !\\n[ds*float-busy] \{\
+. nr ds*float-busy 1
+.\" at .DE
+. if (\\$1=1)&((\\n[Df]%2)=1) \{\
+. if \\n[.t]>\\n[ds*fsize!\\n[ds*fnr]] \{\
+. \" Df = 1,3 or 5
+. ds@print-one-float
+. \}
+. \}
+.\" print all if Df<2 and end of section
+. if (\\$1=2)&(\\n[Df]<2) .ds@print-all-floats
+.\" print all if end of document. Where should they go instead?
+. if \\$1=3 .ds@print-all-floats
+.\" new page
+. if (\\$1=4)&(\\n[Df]>1) \{\
+. if \\n[Df]=2 .ds@print-one-float
+. if \\n[Df]=3 .ds@print-one-float
+. if \\n[Df]>3 \{\
+. ie \\n[De] .ds@print-all-floats
+. el .ds@print-this-page
+. \}
+. \}
+. nr ds*float-busy 0
+.\}
+..
+.\"---------------
+.\" print a floating diversion
+.de ds@output-div
+.ev ds*fev
+.in 0
+.nf
+.ds*fdiv!\\n[ds*o-fnr]
+.ev
+.rm ds*fdiv!\\n[ds*o-fnr]
+.rm ds*fsize!\\n[ds*o-fnr]
+.rm ds*fformat!\\n[ds*o-fnr]
+.nr ds*o-fnr +1
+..
+.\"---------------
+.\" print one floating display if there is one.
+.de ds@print-one-float
+.if \\n[ds*o-fnr]<=\\n[ds*fnr] \{\
+. if \\n[.t]<\\n[ds*fsize!\\n[ds*o-fnr]] .pg@next-page
+. ds@output-div
+. if \\n[De] .pg@next-page
+.\}
+..
+.\"---------------
+.\" print all queued floats.
+.\" if De>0 do a page eject between the floats.
+.de ds@print-all-floats
+.while \\n[ds*o-fnr]<=\\n[ds*fnr] \{\
+. if \\n[.t]<\\n[ds*fsize!\\n[ds*o-fnr]] .pg@next-page
+. ds@output-div
+. if \\n[De] .pg@next-page
+.\}
+..
+.\"---------------
+.\" print as many floats as will fit on the current page
+.de ds@print-this-page
+.while \\n[ds*o-fnr]<=\\n[ds*fnr] \{\
+. if \\n[.t]<\\n[ds*fsize!\\n[ds*o-fnr]] .break
+. ds@output-div
+.\}
+..
+.\"########### module list ###################
+.\" .LI text-indent mark-indent pad type [mark [LI-space [LB-space] ] ]
+.\"
+.nr li*tind 0
+.nr li*mind 0
+.nr li*pad 0
+.nr li*type 0
+.ds li*mark 0
+.nr li*li-spc 0
+.nr li*lvl 0 1
+.nr li*cur-vpos 0
+.\"--------------------------
+.\" the major list-begin macro.
+.\" If type == -1 a 'break' will occur.
+.de LB
+.if \\n[.$]<4 .@error "LB: not enough arguments, min 4"
+.misc@push cind \\n[.i]
+.misc@push tind \\n[li*tind]
+.misc@push mind \\n[li*mind]
+.misc@push pad \\n[li*pad]
+.misc@push type \\n[li*type]
+.misc@push li-spc \\n[li*li-spc]
+.ds li*mark-list!\\n[li*lvl] \\*[li*mark]
+.nr li*lvl +1
+.\"
+.nr li*tind (n;0\\$1)\" text-indent
+.nr li*mind (n;0\\$2)\" mark-indent
+.nr li*pad (n;0\\$3)\" pad
+.nr li*type 0\\$4\" type
+.ds li*mark \\$5\" mark
+.ie !'\\$6'' .nr li*li-spc \\$6\" LI-space
+.el .nr li*li-spc 1
+.ie !'\\$7'' .nr li*lb-spc \\$6\" LB-space
+.el .nr li*lb-spc 0
+.\" init listcounter
+.nr li*cnt!\\n[li*lvl] 0 1
+.\" assign format
+.af li*cnt!\\n[li*lvl] 1
+.if \\n[li*type] .if !'\\*[li*mark]'' .af li*cnt!\\n[li*lvl] \\*[li*mark]
+.\"
+.if \\n[li*lb-spc] .SP (u;\\n[li*lb-spc]*\\n[Lsp])
+.in +\\n[li*tind]u
+..
+.\"---------------
+.de LI
+.if \\n[li*lvl]<1 .@error "LI:no lists active"
+.if \\n[li*li-spc]&(\\n[Ls]>=\\n[li*lvl]) .SP (u;\\n[li*li-spc]*\\n[Lsp])
+.ne 2v
+.\"
+.ds li*c-mark \\*[li*mark]
+.nr li*cnt!\\n[li*lvl] +1
+.if \\n[li*type]=1 .ds li*c-mark \\n[li*cnt!\\n[li*lvl]].
+.if \\n[li*type]=2 .ds li*c-mark \\n[li*cnt!\\n[li*lvl]])
+.if \\n[li*type]=3 .ds li*c-mark (\\n[li*cnt!\\n[li*lvl]])
+.if \\n[li*type]=4 .ds li*c-mark [\\n[li*cnt!\\n[li*lvl]]]
+.if \\n[li*type]=5 .ds li*c-mark <\\n[li*cnt!\\n[li*lvl]]>
+.if \\n[li*type]=6 .ds li*c-mark {\\n[li*cnt!\\n[li*lvl]]}
+.if \\n[.$]=1 .ds li*c-mark \\$1
+.if \\n[.$]=2 .ds li*c-mark \\$1\ \\*[li*c-mark]
+.if '\\*[li*c-mark]'\ ' .ds li*c-mark
+.\"
+.\" determine where the text begins
+.nr li*text-begin \\n[li*tind]>?\w@\\*[li*c-mark]\ @
+.\"
+.\" determine where the mark begin
+.ie !\\n[li*pad] .nr li*in \\n[li*mind]
+.el .nr li*in \\n[li*text-begin]-\\n[li*pad]-\w@\\*[li*c-mark]@
+.if !\\n[li*in] .nr li*in 0
+.\"
+.ti -\\n[li*tind]u
+.\" no indentation if hanging indent
+.if (\w@\\*[li*c-mark]@=0)&((\\n[.$]=0):(\w@\\$1@=0)) .nr li*text-begin 0
+\Z'\&\h'\\n[li*in]u'\\*[li*c-mark]'\h'\\n[li*text-begin]u'\&\c
+.if \\n[li*type]=-1 .br
+..
+.\"
+.\"-------------
+.de li@pop
+.nr li*lvl -1
+.misc@pop-nr cind li*tmp
+.in \\n[li*tmp]u
+.misc@pop-nr tind li*tind
+.misc@pop-nr mind li*mind
+.misc@pop-nr pad li*pad
+.misc@pop-nr type li*type
+.misc@pop-nr li-spc li*li-spc
+.ds li*mark \\*[li*mark-list!\\n[li*lvl]]
+..
+.de LE
+.if \\n[li*lvl]<1 .@error "LE:mismatched"
+.li@pop
+.if '\\$1'1' .SP \\n[Lsp]u
+..
+.\"-------------
+.\" list status clear.
+.de LC
+.if !\\n[.$]=1 .@error "LC: no argument"
+.if \\$1>\\n[li*lvl] .@error "LC: incorrect argument: \\$1 (too big)"
+.while \\n[li*lvl]>\\$1 .li@pop
+.nr par@ind-flag 0
+..
+.\"-------------
+.de AL
+.if \\n[.$]>3 .@error "AL: too many arguments"
+.if \\n[D]>2 .tm AL $*
+.ie \\n[.$]<=1 .LB \\n[Li] 0 2 1 "\\$1"
+.el \{\
+. ie \\n[.$]=2 .LB 0\\$2 0 2 1 "\\$1"
+. el \{\
+. ie !'\\$2'' .LB \\$2 0 2 1 "\\$1" 0 1
+. el .LB \\n[Li] 0 2 1 "\\$1" 0 1
+. \}
+.\}
+..
+.de ML
+.if \\n[.$]>3 .@error "ML: too many arguments"
+.if \\n[D]>2 .tm ML $*
+.nr li*ml-width \w@\\$1@u+1n
+.if \\n[.$]<2 .LB \\n[li*ml-width]u 0 1 0 "\\$1"
+.if \\n[.$]=2 .LB 0\\$2 0 1 0 "\\$1"
+.if \\n[.$]=3 \{\
+. ie '\\$2'' .LB \\n[li*ml-width]u 0 1 0 "\\$1" 0 1
+. el .LB \\n[Li] 0 1 0 "\\$1" 0 1
+.\}
+..
+.de VL
+.if \\n[D]>2 .tm VL $*
+.if \\n[.$]>3 .@error "VL: too many arguments"
+.if \\n[.$]<1 .@error "VL: missing text-indent"
+.ie \\n[.$]<3 .LB 0\\$1 0\\$2 0 0
+.el .LB 0\\$1 0\\$2 0 0 \& 0 1
+..
+.\" Bullet (for .BL)
+.de BL
+.if \\n[D]>2 .tm BL $*
+.ds BU \s-2\(bu\s0
+.if \\n[.$]>2 .@error "BL: too many arguments"
+.if \\n[.$]<1 .LB \\n[Pi] 0 1 0 \\*[BU]
+.if \\n[.$]=1 .LB 0\\$1 0 1 0 \\*[BU]
+.if \\n[.$]=2 \{\
+. ie '\\$1'' .LB \\n[Pi] 0 1 0 \\*[BU] 0 1
+. el .LB 0\\$1 0 1 0 \\*[BU] 0 1
+.\}
+..
+.de DL
+.if \\n[D]>2 .tm DL $*
+.if \\n[.$]>2 .@error "DL: too many arguments"
+.if \\n[.$]<1 .LB \\n[Pi] 0 1 0 \(em
+.if \\n[.$]=1 .LB 0\\$1 0 1 0 \(em
+.if \\n[.$]=2 \{\
+. ie '\\$1'' .LB \\n[Pi] 0 1 0 \(em 0 1
+. el .LB 0\\$1 0 1 0 \(em 0 1
+.\}
+..
+.de RL
+.if \\n[D]>2 .tm RL $*
+.if \\n[.$]>2 .@error "RL: too many arguments"
+.if \\n[.$]<1 .LB 6 0 2 4
+.if \\n[.$]=1 .LB 0\\$1 0 2 4
+.if \\n[.$]=2 \{\
+. ie '\\$1'' .LB 6 0 2 4 1 0 1
+. el .LB 0\\$1 0 2 4 1 0 1
+.\}
+..
+.\" Broken Variable List. As .VL but text begin on the next line
+.de BVL
+.if \\n[D]>2 .tm BVL $*
+.if \\n[.$]>3 .@error "BVL: too many arguments"
+.if \\n[.$]<1 .@error "BVL: missing text-indent"
+.ie \\n[.$]<3 .LB 0\\$1 0\\$2 0 -1
+.el .LB 0\\$1 0\\$2 0 -1 \& 0 1
+..
+.\" ####### module tbl #######################################
+.\" This module is copied from groff_ms and modified for mgm.
+.\" Yes, it does not resemble the original anymore :-).
+.\" Don't know if I missed something important.
+.\" Groff_ms is written by James Clark.
+.nr tbl*have-header 0
+.nr tbl*header-written 0
+.de TS
+.br
+.if ''\\n[.z]' .SP
+.if '\\$1'H' .di tbl*header-div
+..
+.de tbl@top-hook
+.if \\n[tbl*have-header] \{\
+. ie \\n[.t]-\\n[tbl*header-ht]-1v .tbl@print-header
+. el .sp \\n[.t]u
+.\}
+..
+.de tbl@bottom-hook
+.if \\n[tbl*have-header] \{\
+. nr T. 1
+.\" draw bottom and side lines of boxed tables.
+. T#
+.\}
+.nr tbl*header-written 0
+..
+.de tbl@print-header
+.ev tbl*ev
+'nf
+.tbl*header-div
+.ev
+.mk #T
+.nr tbl*header-written 1
+..
+.de TH
+.ie '\\n[.z]'tbl*header-div' \{\
+. nr T. 0
+. T#
+. br
+. di
+. nr tbl*header-ht \\n[dn]
+. ne \\n[dn]u+1v
+. nr tbl*have-header 1
+. ie '\\$1'N' .if !\\n[tbl*header-written] .tbl@print-header
+. el .tbl@print-header
+.\}
+.el .@error ".TH without .TS H"
+..
+.de TE
+.ie '\\n(.z'tbl*header-div' .@error ".TS H but no .TH before .TE"
+.el \{\
+. nr tbl*have-header 0
+.\}
+.\" reset tabs
+.TAB
+..
+.de T&
+..
+.\" ####### module pic #######################################
+.de PS
+.nr pic*in 0
+.br
+.SP .5
+.ie \\n[.$]<2 .@error "PS: bad arguments. Probably not processed with pic."
+.el \{\
+. if !\\n[ds*lvl] .ne (u;\\$1)+1v
+.\" should be contained between .DS/.DE
+.if r ds*format \{\
+. if \\n[ds*lvl]&((\\n[ds*format]=2):(\\n[ds*format]=3)) \{\
+. nr pic*in \\n[.i]
+.\" . in +(u;\\n[.l]-\\n[.i]-\\$2/2)
+. \}
+. \}
+.\}
+..
+.de PE
+.init@reset
+.SP .5
+..
+.\" ####### module eq #######################################
+.\"
+.nr eq*number 0 1
+.de EQ
+.ds eq*lable "\\$1
+.di eq*div
+.misc@ev-keep eq*ev
+.in 0
+.nf
+..
+.de EN
+.br
+.di
+.ta
+.\" equation with lable.
+.if \\n[dl] \{\
+. br
+. chop eq*div
+. ie (\\n[Eq]%2) \{\
+. \" lable to the left
+. if \\n[ds*format]<2 \{\
+. ta (u;(\\n[.l]/7)+\\n[.i]) \\n[.l]u\" L
+\\*[eq*lable]\t\\*[eq*div]\t\&
+. \}
+. if (\\n[ds*format]=2):(\\n[ds*format]=3) \{\
+. ta (u;(\\n[.l]-\\n[.i])/2+\\n[.i])C \\n[.l]u\" C
+\\*[eq*lable]\t\\*[eq*div]\t\&
+. \}
+. if \\n[ds*format]>3 \{\
+. ta \\n[.l]uR\" R
+\\*[eq*lable]\t\\*[eq*div]
+. \}
+. \}
+. el \{\
+. \" lable to the right
+. if \\n[ds*format]<2 \{\
+. ta \\n[.l]uR\" L
+\\*[eq*div]\t\\*[eq*lable]
+. \}
+. if (\\n[ds*format]=2):(\\n[ds*format]=3) \{\
+. ta (u;(\\n[.l]-\\n[.i])/2+\\n[.i])C \\n[.l]uR\" C
+\t\\*[eq*div]\t\\*[eq*lable]
+. \}
+. if \\n[ds*format]>3 \{\
+. ta (\\n[.l]u-\w@\\*[eq*lable]@u-1m)R \\n[.l]uR\" R
+\t\\*[eq*div]\t\\*[eq*lable]
+. \}
+. \}
+.\}
+.TAB
+.ev
+..
+.\"########### module toc ###################
+.\" table of contents
+.nr toc*slevel 1
+.nr toc*spacing \n[Lsp]u
+.nr toc*tlevel 2
+.nr toc*tab 0
+.\"-----------
+.\" Table of contents with friends (module lix)
+.de TC
+.br
+.\" print any pending displays and references
+.ds@print-float 3
+.if \\n[ref*flag] .RP 0 1
+.\"
+.if \w@\\$1@>0 .nr toc*slevel \\$1
+.if \w@\\$2@>0 .nr toc*spacing (u;\\$2*\\n[Lsp])
+.if \w@\\$3@>0 .nr toc*tlevel \\$3
+.if \w@\\$4@>0 .nr toc*tab \\$4
+.if \\n[pg*cols-per-page]>1 .1C
+.pg@clear-hd
+.pg@next-page
+.pg@clear-ft
+.\"-------------
+.if d Ci .toc@read-Ci \\*[Ci]
+.nf
+.in 0
+.nr toc*pn 0 1
+.af toc*pn i
+.PF "''\\\\\\\\n+[toc*pn]''"
+.nr toc*i 4 1
+.while \\n+[toc*i]<10 \{\
+. if !'\\$\\n[toc*i]'' \{\
+. ce
+\\$\\n[toc*i]
+. br
+. \}
+.\}
+.if \\n[.$]<=4 .if d TX .TX
+.ie d TY .if \\n[.$]<=4 .TY
+.el \{\
+. ce
+\\*[Licon]
+. br
+. SP 3
+.\}
+.if d toc*list .toc*list
+.\" print LIST OF XXX
+.if d lix*dsfg .lix@print-ds fg "\\*[Lf]"
+.if d lix*dstb .lix@print-ds tb "\\*[Lt]"
+.if d lix*dsec .lix@print-ds ec "\\*[Le]"
+.if d lix*dsex .lix@print-ds ex "\\*[Lx]"
+..
+.\"-----------
+.\" .toc@read-Ci lev1 lev2 lev3 lev4 ... lev7
+.de toc@read-Ci
+.nr toc*i 0 1
+.while \\n+[toc*i]<8 \{\
+. nr toc*hl!\\n[toc*i] \\$\\n[toc*i]
+.\}
+..
+.\"-----------
+.de toc@save
+.\" collect maxsize of mark if string Ci don't exist.
+.if !d Ci \{\
+. if !r toc*hl!\\$1 .nr toc*hl!\\$1 0
+. if \\n[toc*hl!\\$1]<=\w@\\$2@ \{\
+. nr toc*hl!\\$1 \w@\\$2@u+1m
+. \}
+.\}
+.am toc*list
+.\" .toc@set level headernumber text pagenr
+.toc@set \\$1 "\\$2" "\\$3" \\$4
+\\..
+..
+.\"-----------
+.\" level mark text pagenumber
+.de toc@set
+.if \\$1<=\\n[toc*slevel] .SP \\n[toc*spacing]u
+.ne 2v
+.na
+.fi
+.nr toc*ind 0
+.nr toc*i 0 1
+.ie d Ci \{\
+. nr toc*ind +\\n[toc*hl!\\$1]u
+.\}
+.el \{\
+. while \\n+[toc*i]<\\$1 \{\
+. nr toc*ind +\\n[toc*hl!\\n[toc*i]]u
+. \}
+.\}
+.nr toc*text \\n[toc*ind]u+\\n[toc*hl!\\$1]u
+.in \\n[toc*text]u
+.ti -\\n[toc*hl!\\$1]u
+.\"
+.\" length of headernum space
+.nr toc*i \\n[toc*hl!\\$1]-\w@\\$2@
+.\"
+.ll \\n[@ll]u-\w@\\$4@u-2m
+.\" ragged right ---------------------------------
+.ie \\$1>\\n[toc*tlevel] \{\
+\\$2
+. sp -1
+\\$3\ \ \ \\$4
+. br
+.\}
+.el \{\
+. \" unnumbered heading --------------------
+. ie '\\$2'' \{\
+. in \\n[toc*ind]u
+\\$3\h'1m'
+. \}
+. \" normal heading ------------------------
+. el \{\
+\\$2
+. sp -1
+\\$3\h'1m'
+. \}
+. ll \\n[@ll]u
+. sp -1
+. nr toc*sep (u;\\n[.l]-\\n[.n]-\\n[.i]-\w@\\$4@)-1m
+\h'|\\n[.n]u'\l'\\n[toc*sep]u.'\h'1m'\\$4
+.\}
+.ll \\n[@ll]u
+..
+.\"########################### module lix ############################
+.\" LIST OF figures, tables, exhibits and equations
+.nr lix*fg-nr 0 1
+.nr lix*tb-nr 0 1
+.nr lix*ec-nr 0 1
+.nr lix*ex-nr 0 1
+.aln Fg lix*fg-nr
+.aln Tb lix*tb-nr
+.aln Ec lix*ec-nr
+.aln Ex lix*ex-nr
+.\"------------
+.de FG
+.lix@print-line fg Lf \\n+[lix*fg-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.de TB
+.lix@print-line tb Lt \\n+[lix*tb-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.de EC
+.lix@print-line ec Le \\n+[lix*ec-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.de EX
+.lix@print-line ex Lx \\n+[lix*ex-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.\"------------
+.\" print line with 'figure' in the text
+.\" type stringvar number text override flag refname
+.de lix@print-line
+.ds lix*text "\\$4
+.\"
+.ie \\n[Sectf] .ds lix*numb \\n[H1]-\\$3
+.el .ds lix*numb \\$3
+.\"
+.ie !\\n[Of] .ds lix*ds-form .\ \ \"
+.el .ds lix*ds-form "\ \(em\ \"
+.nr lix*in \\n[.i]
+.ds lix*lable \\*[Li\\$1]\ \\*[lix*numb]\\*[lix*ds-form]
+.if !'\\$5'' \{\
+. if !0\\$6 .ds lix*lable \\*[Li\\$1]\ \\$5\\*[lix*numb]\\*[lix*ds-form]
+. if 0\\$6=1 .ds lix*lable \\*[Li\\$1]\ \\*[lix*numb]\\$5\\*[lix*ds-form]
+. if 0\\$6=2 .ds lix*lable \\*[Li\\$1]\ \\$5\\*[lix*ds-form]
+.\}
+.ie \\n[Sectp] .ds lix*pgnr \\*[hd*sect-pg]
+.el .ds lix*pgnr \\n[%]
+.\" print line if not between DS/DE
+.ie \\n[ds*lvl]<1 .lix@print-text "\\*[lix*lable]" "\\*[lix*text]"
+.el .lix@embedded-text "\\*[lix*lable]" "\\*[lix*text]"
+.\"
+.\" save line for LIST OF XXX
+.if !r lix*wth\\$1 .nr lix*wth\\$1 0
+.if \w@\\*[lix*lable]@>\\n[lix*wth\\$1] .nr lix*wth\\$1 \w@\\*[lix*lable]@
+.if \\n[\\$2] .lix@ds-save \\$1 \\*[lix*pgnr] "\\$4" "\\*[lix*lable]"
+.if !'\\$7'' .SETR \\$7 \\*[lix*numb]
+..
+.\"-----------
+.de lix@print-text
+.SP \\n[Lsp]u
+.misc@ev-keep lix
+.init@reset
+.br
+.ie (\w@\\$1\\$2@)>(\\n[.l]-\\n[.i]) \{\
+. in +\w@\\$1@u
+. ti 0
+.\}
+.el .ce 1
+\fB\\$1\fP\\$2
+.br
+.ev
+..
+.\" hide printout until diversion is evaluated
+.de lix@embedded-text
+\!.SP \\n[Lsp]u
+\!.misc@ev-keep lix
+\!.init@reset
+\!.br
+\!.ie (\w@\\$1\\$2@)>(\\n[.l]-\\n[.i]) \{\
+\!. in +\w@\\$1@u
+\!. ti 0
+\!.\}
+\!.el .ce 1
+\!\fB\\$1\fP\\$2
+\!.br
+\!.ev
+..
+.\"------------
+.\" print complete list of XXXX
+.de lix@print-ds
+.\" arg: fg,tb,ec,ex text
+.if !\\n[Cp] .pg@next-page
+.\" print LIST OF XXXX
+.ce
+\\$2
+.SP 3
+.in \\n[lix*wth\\$1]u
+.fi
+.lix*ds\\$1
+..
+.\"------------
+.\" save line of list in macro
+.de lix@ds-save
+.\" type pagenumber text
+.am lix*ds\\$1
+.lix@dsln \\$1 \\$2 "\\$3" "\\$4" \\$5
+\\..
+..
+.\"------------
+.\" print appended macro
+.\" lix@dsln type pagenumber text headernr
+.de lix@dsln
+.nr lix*i \\n[lix*wth\\$1]-\w@\\$4@
+.ne 2v
+.nr lix*sep \\n[.l]-\\n[lix*i]-\w'\\$4\\$3\\$2'-1m-1n-\\n[.i]
+\h'\\n[lix*i]u'\\$4\\$3\h'1n'\l'\\n[lix*sep]u.'\h'1m'\\$2
+.SP \\n[toc*spacing]u
+..
+.\"########################### module fnt ############################
+.\" some font macros.
+.de R
+.ft R
+.ul 0
+..
+.\"-----------
+.de fnt@switch
+.ul 0
+.ds fnt*tmp
+.nr fnt*prev \\n[.f]
+.nr fnt*i 2 1
+.while \\n+[fnt*i]<=\\n[.$] \{\
+. if \\n[fnt*i]>3 .as fnt*tmp \,
+. ie (\\n[fnt*i]%2)=1 .as fnt*tmp \\$1\\$[\\n[fnt*i]]
+. el .as fnt*tmp \\$2\\$[\\n[fnt*i]]
+. if \\n[fnt*i]<\\n[.$] .as fnt*tmp \/
+.\}
+\&\\*[fnt*tmp]\f[\\n[fnt*prev]]
+..
+.\"-----------
+.de B
+.ie \\n[.$] .fnt@switch \fB \f[\\n[.f]] \\$@
+.el .ft B
+..
+.de I
+.ie \\n[.$] .fnt@switch \fI \f[\\n[.f]] \\$@
+.el .ft I
+..
+.de IB
+.if \\n[.$] .fnt@switch \fI \fB \\$@
+..
+.de BI
+.if \\n[.$] .fnt@switch \fB \fI \\$@
+..
+.de IR
+.if \\n[.$] .fnt@switch \fI \fR \\$@
+..
+.de RI
+.if \\n[.$] .fnt@switch \fR \fI \\$@
+..
+.de RB
+.if \\n[.$] .fnt@switch \fR \fB \\$@
+..
+.de BR
+.if \\n[.$] .fnt@switch \fB \fR \\$@
+..
+.\"########################### module box ############################
+.\" draw a box around some text. Text will be kept on the same page.
+.\"
+.nr box*ll 0
+.\" .B1 and .B2 works like .DS
+.de B1
+.if \\n[box*ll] .@error "B1: missing B2"
+.nr box*ll \\n[.l]
+.nr box*ind \\n[.i]
+.nr box*hyp \\n[.hy]
+.nr box*wid \\n[.l]-\\n[.i]
+.\"
+.\" jump to new environment.
+.ev box*ev
+.di box*div
+.in 1n
+.ll (u;\\n[box*wid]-1n)
+.hy \\n[.hy]
+..
+.de B2
+.if !\\n[box*ll] .@error "B2: missing B1"
+.br
+.di
+.nr box*height \\n[dn]
+.ne \\n[dn]u+1v
+.ll \\n[box*ll]u
+.in \\n[box*ind]u
+.nr box*y-pos \\n[.d]u
+.nf
+.box*div
+.fi
+\v'-1v+.25m'\
+\D'l \\n[box*wid]u 0'\
+\D'l 0 -\\n[box*height]u'\
+\D'l -\\n[box*wid]u 0'\
+\D'l 0 \\n[box*height]u'
+.br
+.sp -1
+.ev
+.sp .20v
+.in \\n[box*ind]u
+.ll \\n[box*ll]u
+.rm box*div
+.nr box*ll 0
+..
+.\"########################### module ref ############################
+.nr ref*nr 0 1
+.nr ref*nr-width 5n
+.nr ref*flag 0 \" for end-of-text
+.ds Rf \v'-.4m'\s-3[\\n+[ref*nr]]\s0\v'.4m'
+.\"
+.\" start reference
+.de RS
+.if !''\\$1' .ds \\$1 \\n[ref*nr]
+.nr ref*flag 1
+.ev ref*ev
+.da ref*div
+.init@reset
+.ll \\n[@ll]u
+.in \\n[ref*nr-width]u
+.ti -(\w@\\n[ref*nr].@u+1n)
+\\n[ref*nr].
+.sp -1
+..
+.de RF
+.br
+.if \\n[Ls] .SP \\n[Lsp]u
+.di
+.ev
+..
+.\"-----------
+.de RP
+.if !d ref*div .@error "RP: No references!"
+.nr ref*flag 0
+.nr ref*i 0\\$2
+.if \\n[ref*i]<2 .SK
+.SP 2
+.ref@print-refs
+.if 0\\$1<1 .nr ref*nr 0 1
+.if ((\\n[ref*i]=0):(\\n[ref*i]=2)) .SK
+..
+.\"-----------
+.\" called by end-of-text!
+.de ref@eot-print
+.if \\n[ref*flag] \{\
+. if \\n[D]>2 .tm Print references, called by eot
+. nr ref*flag 0
+. br
+. misc@ev-keep ne
+. init@reset
+\c
+' bp
+. ev
+. ref@print-refs
+.\}
+..
+.\"-----------
+.\" prints the references
+.de ref@print-refs
+.toc@save 1 "" "\\*[Rp]" \\n[%]
+.ev ref*ev
+.ce
+\fI\\*[Rp]\fP
+.sp
+.in 0
+.nf
+.ref*div
+.in
+.rm ref*div
+.ev
+..
+.\"########################### module app ############################
+.\"
+.nr app*nr 0 1
+.af app*nr A
+.nr app*dnr 0 1
+.\"------------
+.\" .APP name text
+.\" name == "" -> autonumber
+.de APP
+.\" .if \\n[.$]<2 .@error "APP: too few arguments"
+.app@set-ind "\\$1"
+.\"
+.ie \\n[Aph] .app@header \\*[app*ind] "\\$2"
+.el .bp
+.app@index "\\*[app*ind]" "\\$2"
+..
+.\"------------
+.\" .APPSK name pages text
+.\" name == "" -> autonumber
+.de APPSK
+.if \\n[.$]<2 .@error "APPSK: too few arguments"
+.app@set-ind "\\$1"
+.\"
+.ie \\n[Aph] .app@header \\*[app*ind] "\\$3"
+.el .bp
+.app@index "\\*[app*ind]" "\\$3"
+.pn +\\$2
+..
+.\"------------
+.de app@set-ind
+.ie \w@\\$1@ .ds app*ind \\$1
+.el \{\
+. if !\\n[app*dnr] \{\
+. nr H1 0 1
+. af H1 A
+. \}
+. ds app*ind \\n+[app*nr]
+. nr H1 \\n+[app*dnr]
+.\}
+.\" clear lower counters
+.nr app*i 1 1
+.while \\n+[app*i]<8 .nr H\\n[app*i] 0 1
+..
+.\"------------
+.de app@index
+.toc@save 1 "" "\\*[App] \\$1: \\$2" \\n[%]
+..
+.\"------------
+.\" app@heaer name text
+.de app@header
+.bp
+.SP (u;\\n[Lsp]*4)
+.ce 1
+\s+4\fB\\*[App]\ \\$1\fP\s0
+.SP (u;\\n[Lsp]*2)
+.if \w@\\$2@<\\n[.l] .ce 1
+\fB\s+2\\$2\s0\fP
+.SP (u;\\n[Lsp]*4)
+..
+.\"########################### module cov ############################
+.\" title stored in diversion cov*title
+.\" abstract stored in diversion cov*abstract
+.\" arg to abstract stored in cov*abs-arg
+.\" indent stored in cov*abs-ind
+.\" number of authors stored in cov*au
+.\" author(s) stored in cov*au!x!y
+.\" author(s) title stored in cov*at!x!y
+.\" x is the author-index [1-cov*au], y is the argument-index [1-9].
+.\" author(s) firm stored in cov*firm
+.\" new date (if .ND exists) is stored in cov*new-date
+.\"
+.\"
+.ds cov*abs-name ABSTRACT
+.\"
+.nr cov*au 0
+.de TL
+.if \\n[.$]>0 .ds cov*title-charge-case \\$1
+.if \\n[.$]>1 .ds cov*title-file-case \\$2
+.pg@disable-top-trap
+.eo
+.de cov*title AU
+..
+.\"-------------------
+.de cov@title-end
+.ec
+..
+.\"-------------------
+.\" .AU name [initials [loc [dept [ext [room [arg [arg [arg]]]]]]]]
+.de AU
+.cov@title-end
+.pg@disable-top-trap
+.if \\n[.$]<1 .@error "AU: no arguments"
+.nr cov*au +1
+.nr cov*i 0 1
+.while \\n[.$]>=\\n+[cov*i] \{\
+. ds cov*au!\\n[cov*au]!\\n[cov*i] "\\$[\\n[cov*i]]
+.\}
+.if (\\n[.$]>=3)&(\w@\\$3@) \{\
+. if d cov*location-\\$3] \{\
+. ds cov*au!3!\\n[cov*au] \\*[cov*location-\\$3]
+. \}
+.\}
+..
+.\"-------------------
+.\" .AT title1 [title2 [... [title9] ]]]]
+.\" Well, thats all that COVEND look for.
+.\" Must appear directly after .AU
+.de AT
+.if \\n[.$]<1 .@error "AT: no arguments"
+.nr cov*i 0 1
+.while \\n[.$]>=\\n+[cov*i] \{\
+. ds cov*at!\\n[cov*au]!\\n[cov*i] "\\$[\\n[cov*i]]
+.\}
+..
+.\"-------------------
+.de AF
+.cov@title-end
+.if \\n[.$]<1 .@error "AF: no arguments"
+.ds cov*firm \\$1
+..
+.de AST
+.ds cov*abs-name \\$1
+..
+.de AS
+.pg@disable-top-trap
+.if d cov*abstract .@error "AS: only one abstract allowed"
+.if !''\\n[.z]' .@error "AS: no diversion allowed (previous .AS?)"
+.nr cov*abs-arg 0\\$1
+.nr cov*abs-ind (n;0\\$2)
+.de cov*abstract AE
+..
+.de AE
+..
+.\" I am planning to use mgm some time :-)
+.ie \\n[yr]<50 .ds cov*new-date \\*[MO\\n[mo]] \\n[dy], 20\\n[yr]
+.el .ds cov*new-date \\*[MO\\n[mo]] \\n[dy], 19\\n[yr]
+.als DT cov*new-date
+.de ND
+.\" don't remember why I did this: .pg@disable-top-trap
+.ds cov*new-date \\$1
+..
+.\"-------------------
+.\" save technical numbers.
+.de TM
+.nr cov*i 0 1
+.while \\n[.$]>=\\n+[cov*i] .ds cov*mt-tm!\\n[cov*i] \\$[\\n[cov*i]]
+.nr cov*mt-tm-max \\n[.$]
+..
+.\"-----------------------
+.\" cover sheet
+.\" the file must have the following last lines (somewhere):
+.\" .pg@enable-top-trap
+.\" .bp 1
+.\" .pg@enable-trap
+.ds cov*mt-file!0 0.MT
+.ds cov*mt-file!1 0.MT
+.ds cov*mt-file!2 0.MT
+.ds cov*mt-file!3 0.MT
+.ds cov*mt-file!4 4.MT
+.ds cov*mt-file!5 5.MT
+.ds cov*mt-file!6 0.MT
+.\"------------
+.de MT
+.ie \\n[.$] \{\
+. ie d cov*mt-file!\\$1 .ds cov*mt-type \\$1
+. el .ds cov*mt-type 6
+.\}
+.el .ds cov*mt-type 1
+.ds cov*mt-addresse "\\$2
+.ds cov*mt-type-text "\\$1
+.ie d @language .ds cov*str mm/\\*[@language]_
+.el .ds cov*str mm/
+.mso \\*[cov*str]\\*[cov*mt-file!\\*[cov*mt-type]]
+..
+.de COVER
+.ie !\\n[.$] .ds cov*cov-type ms
+.el .ds cov*cov-type \\$1
+.pg@disable-top-trap
+.ie d @language .ds cov*str mm/\\*[@language]_\\*[cov*cov-type].cov
+.el .ds cov*str mm/\\*[cov*cov-type].cov
+.mso \\*[cov*str]
+..
+.\"########################### module qrf ############################
+.\" forward and backward reference thru special files.
+.\"
+.\" init reference system
+.de INITR
+.if \\n[.$]<1 .@error "INITR:filename missing"
+.\" ignore if INITR has already been used
+.if !r qrf*pass \{\
+.\"
+. ds qrf*file \\$1
+. sy test -f \\*[qrf*file].tmp
+. ie \\n[systat] \{\
+. \" PASS 1
+. if \\n[D]=1 .tm PASS 1
+. if \\n[D]>1 .tm INITR: file \\*[qrf*file].tmp, PASS 1
+. nr qrf*pass 1
+. open qrf*stream \\*[qrf*file].tmp
+. write qrf*stream .\\\\" references for \\*[qrf*file]
+. close qrf*stream
+. \}
+. el \{\
+. nr qrf*pass 2
+. if \\n[D]=1 .tm PASS 2
+. if \\n[D]>1 .tm INITR: file \\*[qrf*file].tmp, PASS 2
+. sy mv \\*[qrf*file].tmp \\*[qrf*file].qrf
+' so \\*[qrf*file].qrf
+. \}
+.\}
+..
+.\"---------------
+.\" set a reference.
+.de SETR
+.if \\n[.$]<1 .@error "SETR:reference name missing"
+.ie !r qrf*pass .tm "SETR: No .INITR in this file"
+.el \{\
+. ds qrf*name qrf*ref-\\$1
+.\" probably pass two if already defined
+. if \\n[qrf*pass]<2 \{\
+. if \\n[D]>2 .tm SETR: ref \\*[qrf*name]=\\*[hd*toc-mark],\\n[%]
+. \" heading-number
+. ds \\*[qrf*name]-hn \\*[hd*toc-mark]
+. \" page-number
+. ds \\*[qrf*name]-pn \\n[%]
+. \"
+. \" append to file
+. opena qrf*stream \\*[qrf*file].tmp
+. write qrf*stream .ds \\*[qrf*name]-hn \\*[hd*toc-mark]
+. write qrf*stream .ds \\*[qrf*name]-pn \\n[%]
+. if !'\\$2'' .write qrf*stream .ds \\*[qrf*name]-xx \\$2
+. close qrf*stream
+. \}
+.\}
+..
+.\"---------------
+.\" get misc-string, output <->42<-> in pass 1
+.\" If two arg -> set var. arg to misc-string.
+.de GETST
+.if \\n[.$]<1 .@error "GETST:reference name missing"
+.if !r qrf*pass .tm "GETST: No .INITR in this file"
+.ds qrf*name qrf*ref-\\$1
+.ie \\n[qrf*pass]=2 \{\
+. ie !d \\*[qrf*name]-xx .tm "GETHN:\\$1 not defined"
+. el \{\
+. ie \\n[.$]>1 .ds \\$2 \\*[\\*[qrf*name]-xx]
+. el \\*[\\*[qrf*name]-xx]\c
+. \}
+.\}
+.\" The answer...
+.el <->42<->\c
+..
+.\"---------------
+.\" get header-number, output X.X.X. in pass 1
+.\" If two arg -> set var. arg to header-number.
+.de GETHN
+.if \\n[.$]<1 .@error "GETHN:reference name missing"
+.if !r qrf*pass .tm "GETHN: No .INITR in this file"
+.ds qrf*name qrf*ref-\\$1
+.ie \\n[qrf*pass]=2 \{\
+. ie !d \\*[qrf*name]-hn .tm "GETHN:\\$1 not defined"
+. el \{\
+. ie \\n[.$]>1 .ds \\$2 \\*[\\*[qrf*name]-hn]
+. el \\*[\\*[qrf*name]-hn]\c
+. \}
+.\}
+.el X.X.X.\c
+..
+.\"---------------
+.\" get page-number, output 9999 in pass 1
+.\" If two arg -> set var. arg to page-number.
+.de GETPN
+.if \\n[.$]<1 .@error "GETPN:reference name missing"
+.if !r qrf*pass .tm "GETPN: No .INITR in this file"
+.ds qrf*name qrf*ref-\\$1
+.ie \\n[qrf*pass]=2 \{\
+. ie !d \\*[qrf*name]-pn .tm "GETPN:\\$1 not defined"
+. el \{\
+. ie \\n[.$]>1 .ds \\$2 \\*[\\*[qrf*name]-pn]
+. el \\*[\\*[qrf*name]-pn]\c
+. \}
+.\}
+.el 9999\c
+..
+.\"----------
+.de GETR
+.if \\n[.$]<1 .@error "GETR:reference name missing"
+.ie !r qrf*pass \{\
+. tm "GETR: No .INITR in this file"
+.\}
+.el \{\
+. if \\n[qrf*pass]=2 \{\
+. GETHN \\$1 Qrfh
+. GETPN \\$1 Qrfp
+\\*[Qrf]
+. \}
+.\}
+..
diff --git a/gnu/usr.bin/groff/mm/tmac.mse b/gnu/usr.bin/groff/mm/tmac.mse
new file mode 100644
index 000000000000..315d684d2fad
--- /dev/null
+++ b/gnu/usr.bin/groff/mm/tmac.mse
@@ -0,0 +1,42 @@
+.\" swedish version of mm
+.\" for mgm version 1.04
+.mso tmac.m
+.ds @language se
+.\"
+.ds Lf Figurer
+.ds Lt Tabeller
+.ds Lx Uppställningar
+.ds Le Ekvationer
+.\" Page length
+.if !r L .nr @pl 28.5c
+.\" page width
+.if !r W .nr @ll 13c
+.\" page offset
+.if !r O .nr @po 3.5c
+.\" set the above parameters
+.ll \n[@ll]u
+.po \n[@po]u
+.pl \n[@pl]u
+.ds Lifg Figur
+.ds Litb Tabell
+.ds Liex Uppställning
+.ds Liec Ekvation
+.ds Licon Innehållsförteckning
+.ds Qrf Se kapitel \\*[Qrfh], sidan \\*[Qrfp].
+.ds Rp Referenser
+.\"
+.ds MO1 januari
+.ds MO2 februari
+.ds MO3 mars
+.ds MO4 april
+.ds MO5 maj
+.ds MO6 juni
+.ds MO7 juli
+.ds MO8 augusti
+.ds MO9 september
+.ds MO10 oktober
+.ds MO11 november
+.ds MO12 december
+.ie \\n[yr]<50 .ds cov*new-date \\n[dy] \\*[MO\\n[mo]] 20\\n[yr]
+.el .ds cov*new-date \\n[dy] \\*[MO\\n[mo]] 19\\n[yr]
+.nr pg*footer-size 4\" 1v+footer+even/odd footer+1v
diff --git a/gnu/usr.bin/groff/nroff/Makefile b/gnu/usr.bin/groff/nroff/Makefile
new file mode 100644
index 000000000000..36d1a885d4c8
--- /dev/null
+++ b/gnu/usr.bin/groff/nroff/Makefile
@@ -0,0 +1,11 @@
+MAN1= nroff.1
+
+afterinstall:
+ install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ $(.CURDIR)/nroff.sh $(DESTDIR)$(BINDIR)/nroff
+ install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ $(.CURDIR)/psroff.sh $(DESTDIR)$(BINDIR)/psroff
+
+.include <../../../usr.bin/Makefile.inc>
+.include <../Makefile.cfg>
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/nroff/nroff.1 b/gnu/usr.bin/groff/nroff/nroff.1
new file mode 100644
index 000000000000..1dae0571869f
--- /dev/null
+++ b/gnu/usr.bin/groff/nroff/nroff.1
@@ -0,0 +1,58 @@
+.TH NROFF 1 "10 August 1992" "Groff Version 1.08"
+.SH NAME
+nroff \- emulate nroff command with groff
+.SH SYNOPSIS
+.B nroff
+[
+.B \-hi
+]
+[
+.BI \-m name
+]
+[
+.BI \-n num
+]
+[
+.BI \-o list
+]
+[
+.BI \-r cn
+]
+[
+.BI \-T name
+]
+[
+.I file\|.\|.\|.
+]
+.SH DESCRIPTION
+The
+.B nroff
+script emulates the
+.B nroff
+command using groff.
+The
+.B \-T
+option with an argument other than
+.B ascii
+and
+.B latin1
+will be ignored.
+The
+.B \-h
+option
+is equivalent to the
+.B grotty
+.B \-h
+option.
+Other options are as described in
+.BR troff (1).
+In addition the
+.BR \-e ,
+.B \-q
+and
+.B \-s
+options are silently ignored.
+.SH "SEE ALSO"
+.BR groff (1),
+.BR troff (1),
+.BR grotty (1)
diff --git a/gnu/usr.bin/groff/nroff/nroff.sh b/gnu/usr.bin/groff/nroff/nroff.sh
new file mode 100644
index 000000000000..1be695995f2d
--- /dev/null
+++ b/gnu/usr.bin/groff/nroff/nroff.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# Emulate nroff with groff.
+
+prog="$0"
+# Default device.
+T=-Tascii
+opts=
+
+for i
+do
+ case $1 in
+ -h)
+ opts="$opts -P-h"
+ ;;
+ -[eq]|-s*)
+ # ignore these options
+ ;;
+ -[mrnoT])
+ echo "$prog: option $1 requires an argument" >&2
+ exit 1
+ ;;
+ -i|-[mrno]*)
+ opts="$opts $1";
+ ;;
+
+ -Tascii|-Tlatin1)
+ T=$1
+ ;;
+ -T*)
+ # ignore other devices
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -)
+ break
+ ;;
+ -*)
+ echo "$prog: invalid option $1" >&2
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+# This shell script is intended for use with man, so warnings are
+# probably not wanted. Also load nroff-style character definitions.
+exec groff -Wall -mtty-char $T $opts ${1+"$@"}
diff --git a/gnu/usr.bin/groff/nroff/psroff.sh b/gnu/usr.bin/groff/nroff/psroff.sh
new file mode 100644
index 000000000000..8a9008234b43
--- /dev/null
+++ b/gnu/usr.bin/groff/nroff/psroff.sh
@@ -0,0 +1,2 @@
+#! /bin/sh -
+exec groff -Tps -l -C ${1+"$@"}
diff --git a/gnu/usr.bin/groff/pfbtops/Makefile b/gnu/usr.bin/groff/pfbtops/Makefile
new file mode 100644
index 000000000000..9e5029101c85
--- /dev/null
+++ b/gnu/usr.bin/groff/pfbtops/Makefile
@@ -0,0 +1,10 @@
+# Makefile for pfbtops
+
+PROG= pfbtops
+SRCS= pfbtops.c
+LDADD+= $(LIBGROFF)
+DPADD+= $(LIBGROFF)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/pfbtops/pfbtops.1 b/gnu/usr.bin/groff/pfbtops/pfbtops.1
new file mode 100644
index 000000000000..46c353c393c9
--- /dev/null
+++ b/gnu/usr.bin/groff/pfbtops/pfbtops.1
@@ -0,0 +1,27 @@
+.\" -*- nroff -*-
+.TH PFBTOPS 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+pfbtops \- translate a PostScript font in .pfb format to ASCII
+.SH SYNOPSIS
+.B pfbtops
+[
+.I pfb_file
+]
+.SH DESCRIPTION
+.B pfbtops
+translates a PostScript font in
+.B .pfb
+format to ASCII.
+If
+.I pfb_file
+is omitted the pfb file will be read from the standard input.
+The ASCII format PostScript font will be written on the standard output.
+PostScript fonts for MS-DOS are normally supplied in
+.B .pfb
+format.
+.LP
+The resulting ASCII format PostScript font can be used with groff.
+It must first be listed in
+.BR /usr/share/groff_font/devps/download .
+.SH "SEE ALSO"
+.BR grops (1)
diff --git a/gnu/usr.bin/groff/pfbtops/pfbtops.c b/gnu/usr.bin/groff/pfbtops/pfbtops.c
new file mode 100644
index 000000000000..bc79bce59db3
--- /dev/null
+++ b/gnu/usr.bin/groff/pfbtops/pfbtops.c
@@ -0,0 +1,112 @@
+/* This translates ps fonts in .pfb format to ASCII ps files. */
+
+#include <stdio.h>
+
+/* Binary bytes per output line. */
+#define BYTES_PER_LINE (79/2)
+#define HEX_DIGITS "0123456789ABCDEF"
+
+static char *program_name;
+
+static void error(s)
+ char *s;
+{
+ fprintf(stderr, "%s: %s\n", program_name, s);
+ exit(2);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-v] [pfb_file]\n", program_name);
+ exit(1);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int opt;
+ extern int optind;
+
+ program_name = argv[0];
+
+ while ((opt = getopt(argc, argv, "v")) != EOF) {
+ switch (opt) {
+ case 'v':
+ {
+ extern char *version_string;
+ fprintf(stderr, "pfbtops groff version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ }
+ }
+
+ if (argc - optind > 1)
+ usage();
+ if (argc > optind && !freopen(argv[optind], "r", stdin))
+ {
+ perror(argv[optind]);
+ exit(1);
+ }
+ for (;;)
+ {
+ int type, c, i;
+ long n;
+
+ c = getchar();
+ if (c != 0x80)
+ error("first byte of packet not 0x80");
+ type = getchar();
+ if (type == 3)
+ break;
+ if (type != 1 && type != 2)
+ error("bad packet type");
+ n = 0;
+ for (i = 0; i < 4; i++)
+ {
+ c = getchar();
+ if (c == EOF)
+ error("end of file in packet header");
+ n |= (long)c << (i << 3);
+ }
+ if (n < 0)
+ error("negative packet length");
+ if (type == 1)
+ {
+ while (--n >= 0)
+ {
+ c = getchar();
+ if (c == EOF)
+ error("end of file in text packet");
+ if (c == '\r')
+ c = '\n';
+ putchar(c);
+ }
+ if (c != '\n')
+ putchar('\n');
+ }
+ else
+ {
+ int count = 0;
+ while (--n >= 0)
+ {
+ c = getchar();
+ if (c == EOF)
+ error("end of file in binary packet");
+ if (count >= BYTES_PER_LINE)
+ {
+ putchar('\n');
+ count = 0;
+ }
+ count++;
+ putchar(HEX_DIGITS[(c >> 4) & 0xf]);
+ putchar(HEX_DIGITS[c & 0xf]);
+ }
+ putchar('\n');
+ }
+ }
+ exit(0);
+}
diff --git a/gnu/usr.bin/groff/pic/Makefile b/gnu/usr.bin/groff/pic/Makefile
new file mode 100644
index 000000000000..69af66cb3d75
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/Makefile
@@ -0,0 +1,17 @@
+# Makefile for pic
+
+PROG= pic
+SRCS= lex.cc main.cc object.cc common.cc troff.cc tex.cc
+OBJS= pic.o
+CFLAGS+= -I. -I$(.CURDIR)/../include
+CXXFLAGS+= -I. -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF) -lm
+DPADD+= $(LIBGROFF) $(LIBMATH)
+
+CLEANFILES+= pic.cc pic.tab.h
+
+beforedepend: pic.cc
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/pic/TODO b/gnu/usr.bin/groff/pic/TODO
new file mode 100644
index 000000000000..2346b575e1de
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/TODO
@@ -0,0 +1,37 @@
+Dotted and dashed ellipses.
+
+In troff mode, dotted and dashed splines.
+
+Make DELIMITED have type lstr; this would allow us to give better
+error messages for problems within the body of for and if constructs.
+
+In troff mode without -x, fake \D't' with .ps commands.
+
+Perhaps an option to set command char.
+
+Add an output class for dumb line printers. It wouldn't be pretty but
+it would be better than nothing. Integrate it with texinfo. Useful
+for groff -Tascii as well.
+
+Option to allow better positioning of arrowheads on arcs.
+
+Perhaps add PostScript output mode.
+
+Change the interface to the output class so that output devices have
+the opportunity to handle arrowheads themselves.
+
+Consider whether the line thickness should scale.
+
+Consider whether the test in a for loop should be fuzzy (as it
+apparently is in grap).
+
+Possibly change fillval so that zero is black.
+
+Provide a way of getting text blocks (positioned with `.in' rather
+than \h), into pic. Should be possible to use block of diverted text
+in pic. Possibly something similar to T{ and T} in tbl.
+
+Option to provide macro backtraces.
+
+Have a path that is searched by `copy' statement. Set by environment
+variable or command line option.
diff --git a/gnu/usr.bin/groff/pic/common.cc b/gnu/usr.bin/groff/pic/common.cc
new file mode 100644
index 000000000000..0f61c750eb32
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/common.cc
@@ -0,0 +1,495 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "pic.h"
+#include "common.h"
+
+// output a dashed circle as a series of arcs
+
+void common_output::dashed_circle(const position &cent, double rad,
+ const line_type &lt)
+{
+ assert(lt.type == line_type::dashed);
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ double dash_angle = lt.dash_width/rad;
+ int ndashes;
+ double gap_angle;
+ if (dash_angle >= M_PI/4.0) {
+ if (dash_angle < M_PI/2.0) {
+ gap_angle = M_PI/2.0 - dash_angle;
+ ndashes = 4;
+ }
+ else if (dash_angle < M_PI) {
+ gap_angle = M_PI - dash_angle;
+ ndashes = 2;
+ }
+ else {
+ circle(cent, rad, slt, -1.0);
+ return;
+ }
+ }
+ else {
+ ndashes = 4*int(ceil(M_PI/(4.0*dash_angle)));
+ gap_angle = (M_PI*2.0)/ndashes - dash_angle;
+ }
+ for (int i = 0; i < ndashes; i++) {
+ double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0;
+ solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt);
+ }
+}
+
+// output a dotted circle as a series of dots
+
+void common_output::dotted_circle(const position &cent, double rad,
+ const line_type &lt)
+{
+ assert(lt.type == line_type::dotted);
+ double gap_angle = lt.dash_width/rad;
+ int ndots;
+ if (gap_angle >= M_PI/2.0) {
+ // always have at least 2 dots
+ gap_angle = M_PI;
+ ndots = 2;
+ }
+ else {
+ ndots = 4*int(M_PI/(2.0*gap_angle));
+ gap_angle = (M_PI*2.0)/ndots;
+ }
+ double ang = 0.0;
+ for (int i = 0; i < ndots; i++, ang += gap_angle)
+ dot(cent + position(cos(ang), sin(ang))*rad, lt);
+}
+
+// return non-zero iff we can compute a center
+
+int compute_arc_center(const position &start, const position &cent,
+ const position &end, position *result)
+{
+ // This finds the point along the vector from start to cent that
+ // is equidistant between start and end.
+ distance c = cent - start;
+ distance e = end - start;
+ double n = c*e;
+ if (n == 0.0)
+ return 0;
+ *result = start + c*((e*e)/(2.0*n));
+ return 1;
+}
+
+// output a dashed arc as a series of arcs
+
+void common_output::dashed_arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ assert(lt.type == line_type::dashed);
+ position c;
+ if (!compute_arc_center(start, cent, end, &c)) {
+ line(start, &end, 1, lt);
+ return;
+ }
+ distance start_offset = start - c;
+ distance end_offset = end - c;
+ double start_angle = atan2(start_offset.y, start_offset.x);
+ double end_angle = atan2(end_offset.y, end_offset.x);
+ double rad = hypot(c - start);
+ double dash_angle = lt.dash_width/rad;
+ double total_angle = end_angle - start_angle;
+ while (total_angle < 0)
+ total_angle += M_PI + M_PI;
+ if (total_angle <= dash_angle*2.0) {
+ solid_arc(cent, rad, start_angle, end_angle, lt);
+ return;
+ }
+ int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5);
+ double dash_and_gap_angle = (total_angle - dash_angle)/ndashes;
+ for (int i = 0; i <= ndashes; i++)
+ solid_arc(cent, rad, start_angle + i*dash_and_gap_angle,
+ start_angle + i*dash_and_gap_angle + dash_angle, lt);
+}
+
+// output a dotted arc as a series of dots
+
+void common_output::dotted_arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ assert(lt.type == line_type::dotted);
+ position c;
+ if (!compute_arc_center(start, cent, end, &c)) {
+ line(start, &end, 1, lt);
+ return;
+ }
+ distance start_offset = start - c;
+ distance end_offset = end - c;
+ double start_angle = atan2(start_offset.y, start_offset.x);
+ double total_angle = atan2(end_offset.y, end_offset.x) - start_angle;
+ while (total_angle < 0)
+ total_angle += M_PI + M_PI;
+ double rad = hypot(c - start);
+ int ndots = int(total_angle/(lt.dash_width/rad) + .5);
+ if (ndots == 0)
+ dot(start, lt);
+ else {
+ for (int i = 0; i <= ndots; i++) {
+ double a = start_angle + (total_angle*i)/ndots;
+ dot(cent + position(cos(a), sin(a))*rad, lt);
+ }
+ }
+}
+
+void common_output::solid_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt)
+{
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ arc(cent + position(cos(start_angle), sin(start_angle))*rad,
+ cent,
+ cent + position(cos(end_angle), sin(end_angle))*rad,
+ slt);
+}
+
+
+void common_output::rounded_box(const position &cent, const distance &dim,
+ double rad, const line_type &lt, double fill)
+{
+ if (fill >= 0.0)
+ filled_rounded_box(cent, dim, rad, fill);
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_rounded_box(cent, dim, rad, lt);
+ break;
+ case line_type::dotted:
+ dotted_rounded_box(cent, dim, rad, lt);
+ break;
+ case line_type::solid:
+ solid_rounded_box(cent, dim, rad, lt);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+void common_output::dashed_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ const line_type &lt)
+{
+ line_type slt = lt;
+ slt.type = line_type::solid;
+
+ double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
+ int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5);
+ double hor_gap_width = (n_hor_dashes != 0
+ ? hor_length/n_hor_dashes - lt.dash_width
+ : 0.0);
+
+ double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
+ int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5);
+ double vert_gap_width = (n_vert_dashes != 0
+ ? vert_length/n_vert_dashes - lt.dash_width
+ : 0.0);
+ // Note that each corner arc has to be split into two for dashing,
+ // because one part is dashed using vert_gap_width, and the other
+ // using hor_gap_width.
+ double offset = lt.dash_width/2.0;
+ dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset);
+ dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
+ cent + position(dim.x/2.0, dim.y/2.0 - rad),
+ slt, lt.dash_width, vert_gap_width, &offset);
+ dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ 0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
+
+ offset = lt.dash_width/2.0;
+ dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset);
+ dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
+ cent + position(-dim.x/2.0 + rad, dim.y/2.0),
+ slt, lt.dash_width, hor_gap_width, &offset);
+ dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset);
+
+ offset = lt.dash_width/2.0;
+ dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ 3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset);
+ dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
+ cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
+ slt, lt.dash_width, vert_gap_width, &offset);
+ dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
+
+ offset = lt.dash_width/2.0;
+ dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ 5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset);
+ dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
+ cent + position(dim.x/2.0 - rad, -dim.y/2.0),
+ slt, lt.dash_width, hor_gap_width, &offset);
+ dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ 3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset);
+}
+
+// Used by dashed_rounded_box.
+
+void common_output::dash_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt,
+ double dash_width, double gap_width,
+ double *offsetp)
+{
+ double length = (end_angle - start_angle)*rad;
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp >= dash_width) {
+ double rem = dash_width + gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+ else {
+ double rem = dash_width - *offsetp;
+ if (pos + rem > length) {
+ solid_arc(cent, rad, start_angle + pos/rad, end_angle, lt);
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ solid_arc(cent, rad, start_angle + pos/rad,
+ start_angle + (pos + rem)/rad, lt);
+ pos += rem;
+ *offsetp = dash_width;
+ }
+ }
+ }
+}
+
+// Used by dashed_rounded_box.
+
+void common_output::dash_line(const position &start, const position &end,
+ const line_type &lt,
+ double dash_width, double gap_width,
+ double *offsetp)
+{
+ distance dist = end - start;
+ double length = hypot(dist);
+ if (length == 0.0)
+ return;
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp >= dash_width) {
+ double rem = dash_width + gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+ else {
+ double rem = dash_width - *offsetp;
+ if (pos + rem > length) {
+ line(start + dist*(pos/length), &end, 1, lt);
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ position p(start + dist*((pos + rem)/length));
+ line(start + dist*(pos/length), &p, 1, lt);
+ pos += rem;
+ *offsetp = dash_width;
+ }
+ }
+ }
+}
+
+void common_output::dotted_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ const line_type &lt)
+{
+ line_type slt = lt;
+ slt.type = line_type::solid;
+
+ double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
+ int n_hor_dots = int(hor_length/lt.dash_width + .5);
+ double hor_gap_width = (n_hor_dots != 0
+ ? hor_length/n_hor_dots
+ : lt.dash_width);
+
+ double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
+ int n_vert_dots = int(vert_length/lt.dash_width + .5);
+ double vert_gap_width = (n_vert_dots != 0
+ ? vert_length/n_vert_dots
+ : lt.dash_width);
+ double epsilon = lt.dash_width/(rad*100.0);
+
+ double offset = 0.0;
+ dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ -M_PI/4.0, 0, slt, vert_gap_width, &offset);
+ dot_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
+ cent + position(dim.x/2.0, dim.y/2.0 - rad),
+ slt, vert_gap_width, &offset);
+ dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ 0, M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
+
+ offset = 0.0;
+ dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ M_PI/4.0, M_PI/2, slt, hor_gap_width, &offset);
+ dot_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
+ cent + position(-dim.x/2.0 + rad, dim.y/2.0),
+ slt, hor_gap_width, &offset);
+ dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ M_PI/2, 3*M_PI/4.0 - epsilon, slt, hor_gap_width, &offset);
+
+ offset = 0.0;
+ dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ 3.0*M_PI/4.0, M_PI, slt, vert_gap_width, &offset);
+ dot_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
+ cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
+ slt, vert_gap_width, &offset);
+ dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ M_PI, 5.0*M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
+
+ offset = 0.0;
+ dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ 5*M_PI/4.0, 3*M_PI/2.0, slt, hor_gap_width, &offset);
+ dot_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
+ cent + position(dim.x/2.0 - rad, -dim.y/2.0),
+ slt, hor_gap_width, &offset);
+ dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ 3*M_PI/2, 7*M_PI/4 - epsilon, slt, hor_gap_width, &offset);
+}
+
+// Used by dotted_rounded_box.
+
+void common_output::dot_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt, double gap_width,
+ double *offsetp)
+{
+ double length = (end_angle - start_angle)*rad;
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp == 0.0) {
+ double ang = start_angle + pos/rad;
+ dot(cent + position(cos(ang), sin(ang))*rad, lt);
+ }
+ double rem = gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+}
+
+// Used by dotted_rounded_box.
+
+void common_output::dot_line(const position &start, const position &end,
+ const line_type &lt, double gap_width,
+ double *offsetp)
+{
+ distance dist = end - start;
+ double length = hypot(dist);
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp == 0.0)
+ dot(start + dist*(pos/length), lt);
+ double rem = gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+}
+
+
+void common_output::solid_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ const line_type &lt)
+{
+ position tem = cent - dim/2.0;
+ arc(tem + position(0.0, rad),
+ tem + position(rad, rad),
+ tem + position(rad, 0.0),
+ lt);
+ tem = cent + position(-dim.x/2.0, dim.y/2.0);
+ arc(tem + position(rad, 0.0),
+ tem + position(rad, -rad),
+ tem + position(0.0, -rad),
+ lt);
+ tem = cent + dim/2.0;
+ arc(tem + position(0.0, -rad),
+ tem + position(-rad, -rad),
+ tem + position(-rad, 0.0),
+ lt);
+ tem = cent + position(dim.x/2.0, -dim.y/2.0);
+ arc(tem + position(-rad, 0.0),
+ tem + position(-rad, rad),
+ tem + position(0.0, rad),
+ lt);
+ position end;
+ end = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
+ line(cent - dim/2.0 + position(0.0, rad), &end, 1, lt);
+ end = cent + position(dim.x/2.0 - rad, dim.y/2.0);
+ line(cent + position(-dim.x/2.0 + rad, dim.y/2.0), &end, 1, lt);
+ end = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
+ line(cent + position(dim.x/2.0, dim.y/2.0 - rad), &end, 1, lt);
+ end = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
+ line(cent + position(dim.x/2.0 - rad, -dim.y/2.0), &end, 1, lt);
+}
+
+void common_output::filled_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ double fill)
+{
+ line_type ilt;
+ ilt.type = line_type::invisible;
+ circle(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, ilt, fill);
+ circle(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, ilt, fill);
+ circle(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, ilt, fill);
+ circle(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, ilt, fill);
+ position vec[4];
+ vec[0] = cent + position(dim.x/2.0, dim.y/2.0 - rad);
+ vec[1] = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
+ vec[2] = cent + position(-dim.x/2.0, -dim.y/2.0 + rad);
+ vec[3] = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
+ polygon(vec, 4, ilt, fill);
+ vec[0] = cent + position(dim.x/2.0 - rad, dim.y/2.0);
+ vec[1] = cent + position(-dim.x/2.0 + rad, dim.y/2.0);
+ vec[2] = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
+ vec[3] = cent + position(dim.x/2.0 - rad, -dim.y/2.0);
+ polygon(vec, 4, ilt, fill);
+}
diff --git a/gnu/usr.bin/groff/pic/common.h b/gnu/usr.bin/groff/pic/common.h
new file mode 100644
index 000000000000..47560ce1c68e
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/common.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+class common_output : public output {
+private:
+ void dash_line(const position &start, const position &end,
+ const line_type &lt, double dash_width, double gap_width,
+ double *offsetp);
+ void dash_arc(const position &cent, double rad,
+ double start_angle, double end_angle, const line_type &lt,
+ double dash_width, double gap_width, double *offsetp);
+ void dot_line(const position &start, const position &end,
+ const line_type &lt, double gap_width, double *offsetp);
+ void dot_arc(const position &cent, double rad,
+ double start_angle, double end_angle, const line_type &lt,
+ double gap_width, double *offsetp);
+protected:
+ virtual void dot(const position &, const line_type &) = 0;
+ void dashed_circle(const position &, double rad, const line_type &);
+ void dotted_circle(const position &, double rad, const line_type &);
+ void dashed_arc(const position &, const position &, const position &,
+ const line_type &);
+ void dotted_arc(const position &, const position &, const position &,
+ const line_type &);
+ virtual void solid_arc(const position &cent, double rad, double start_angle,
+ double end_angle, const line_type &lt);
+ void dashed_rounded_box(const position &, const distance &, double,
+ const line_type &);
+ void dotted_rounded_box(const position &, const distance &, double,
+ const line_type &);
+ void solid_rounded_box(const position &, const distance &, double,
+ const line_type &);
+ void filled_rounded_box(const position &, const distance &, double, double);
+public:
+ void start_picture(double sc, const position &ll, const position &ur) = 0;
+ void finish_picture() = 0;
+ void circle(const position &, double rad, const line_type &, double) = 0;
+ void text(const position &, text_piece *, int, double) = 0;
+ void line(const position &, const position *, int n, const line_type &) = 0;
+ void polygon(const position *, int n, const line_type &, double) = 0;
+ void spline(const position &, const position *, int n,
+ const line_type &) = 0;
+ void arc(const position &, const position &, const position &,
+ const line_type &) = 0;
+ void ellipse(const position &, const distance &,
+ const line_type &, double) = 0;
+ void rounded_box(const position &, const distance &, double,
+ const line_type &, double);
+};
+
+int compute_arc_center(const position &start, const position &cent,
+ const position &end, position *result);
+
diff --git a/gnu/usr.bin/groff/pic/depend b/gnu/usr.bin/groff/pic/depend
new file mode 100644
index 000000000000..73ac3ab9093c
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/depend
@@ -0,0 +1,21 @@
+pic.tab.o : pic.tab.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h ../lib/ptable.h object.h
+lex.o : lex.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h ../lib/ptable.h object.h pic.tab.h
+main.o : main.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h
+object.o : object.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h ../lib/ptable.h object.h
+common.o : common.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h common.h
+troff.o : troff.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h common.h
+tex.o : tex.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h common.h
diff --git a/gnu/usr.bin/groff/pic/lex.cc b/gnu/usr.bin/groff/pic/lex.cc
new file mode 100644
index 000000000000..a066533b552d
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/lex.cc
@@ -0,0 +1,1938 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "pic.h"
+#include "ptable.h"
+#include "object.h"
+#include "pic.tab.h"
+
+declare_ptable(char)
+implement_ptable(char)
+
+PTABLE(char) macro_table;
+
+class macro_input : public input {
+ char *s;
+ char *p;
+public:
+ macro_input(const char *);
+ ~macro_input();
+ int get();
+ int peek();
+};
+
+class argument_macro_input : public input {
+ char *s;
+ char *p;
+ char *ap;
+ int argc;
+ char *argv[9];
+public:
+ argument_macro_input(const char *, int, char **);
+ ~argument_macro_input();
+ int get();
+ int peek();
+};
+
+input::input() : next(0)
+{
+}
+
+input::~input()
+{
+}
+
+int input::get_location(const char **, int *)
+{
+ return 0;
+}
+
+file_input::file_input(FILE *f, const char *fn)
+: lineno(0), ptr(""), filename(fn)
+{
+ fp = f;
+}
+
+file_input::~file_input()
+{
+ fclose(fp);
+}
+
+int file_input::read_line()
+{
+ for (;;) {
+ line.clear();
+ lineno++;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ else if (illegal_input_char(c))
+ lex_error("illegal input character code %1", c);
+ else {
+ line += char(c);
+ if (c == '\n')
+ break;
+ }
+ }
+ if (line.length() == 0)
+ return 0;
+ if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'P'
+ && (line[2] == 'S' || line[2] == 'E' || line[2] == 'F')
+ && (line.length() == 3 || line[3] == ' ' || line[3] == '\n'
+ || compatible_flag))) {
+ line += '\0';
+ ptr = line.contents();
+ return 1;
+ }
+ }
+}
+
+int file_input::get()
+{
+ if (*ptr != '\0' || read_line())
+ return (unsigned char)*ptr++;
+ else
+ return EOF;
+}
+
+int file_input::peek()
+{
+ if (*ptr != '\0' || read_line())
+ return (unsigned char)*ptr;
+ else
+ return EOF;
+}
+
+int file_input::get_location(const char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+macro_input::macro_input(const char *str)
+{
+ p = s = strsave(str);
+}
+
+macro_input::~macro_input()
+{
+ a_delete s;
+}
+
+int macro_input::get()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return (unsigned char)*p++;
+}
+
+int macro_input::peek()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return (unsigned char)*p;
+}
+
+// Character respresenting $1. Must be illegal input character.
+#define ARG1 14
+
+char *process_body(const char *body)
+{
+ char *s = strsave(body);
+ int j = 0;
+ for (int i = 0; s[i] != '\0'; i++)
+ if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') {
+ if (s[i+1] != '0')
+ s[j++] = ARG1 + s[++i] - '1';
+ }
+ else
+ s[j++] = s[i];
+ s[j] = '\0';
+ return s;
+}
+
+
+argument_macro_input::argument_macro_input(const char *body, int ac, char **av)
+: argc(ac), ap(0)
+{
+ for (int i = 0; i < argc; i++)
+ argv[i] = av[i];
+ p = s = process_body(body);
+}
+
+
+argument_macro_input::~argument_macro_input()
+{
+ for (int i = 0; i < argc; i++)
+ a_delete argv[i];
+ a_delete s;
+}
+
+int argument_macro_input::get()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap++;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return (unsigned char)*ap++;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return (unsigned char)*p++;
+}
+
+int argument_macro_input::peek()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return (unsigned char)*ap;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return (unsigned char)*p;
+}
+
+class input_stack {
+ static input *current_input;
+ static int bol_flag;
+public:
+ static void push(input *);
+ static void clear();
+ static int get_char();
+ static int peek_char();
+ static int get_location(const char **fnp, int *lnp);
+ static void push_back(unsigned char c, int was_bol = 0);
+ static int bol();
+};
+
+input *input_stack::current_input = 0;
+int input_stack::bol_flag = 0;
+
+inline int input_stack::bol()
+{
+ return bol_flag;
+}
+
+void input_stack::clear()
+{
+ while (current_input != 0) {
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ bol_flag = 1;
+}
+
+void input_stack::push(input *in)
+{
+ in->next = current_input;
+ current_input = in;
+}
+
+void lex_init(input *top)
+{
+ input_stack::clear();
+ input_stack::push(top);
+}
+
+void lex_cleanup()
+{
+ while (input_stack::get_char() != EOF)
+ ;
+}
+
+int input_stack::get_char()
+{
+ while (current_input != 0) {
+ int c = current_input->get();
+ if (c != EOF) {
+ bol_flag = c == '\n';
+ return c;
+ }
+ // don't pop the top-level input off the stack
+ if (current_input->next == 0)
+ return EOF;
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ return EOF;
+}
+
+int input_stack::peek_char()
+{
+ while (current_input != 0) {
+ int c = current_input->peek();
+ if (c != EOF)
+ return c;
+ if (current_input->next == 0)
+ return EOF;
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ return EOF;
+}
+
+class char_input : public input {
+ int c;
+public:
+ char_input(int);
+ int get();
+ int peek();
+};
+
+char_input::char_input(int n) : c((unsigned char)n)
+{
+}
+
+int char_input::get()
+{
+ int n = c;
+ c = EOF;
+ return n;
+}
+
+int char_input::peek()
+{
+ return c;
+}
+
+void input_stack::push_back(unsigned char c, int was_bol)
+{
+ push(new char_input(c));
+ bol_flag = was_bol;
+}
+
+int input_stack::get_location(const char **fnp, int *lnp)
+{
+ for (input *p = current_input; p; p = p->next)
+ if (p->get_location(fnp, lnp))
+ return 1;
+ return 0;
+}
+
+string context_buffer;
+
+string token_buffer;
+double token_double;
+int token_int;
+
+void interpolate_macro_with_args(const char *body)
+{
+ char *argv[9];
+ int argc = 0;
+ for (int i = 0; i < 9; i++)
+ argv[i] = 0;
+ int level = 0;
+ int c;
+ enum { NORMAL, IN_STRING, IN_STRING_QUOTED } state = NORMAL;
+ do {
+ token_buffer.clear();
+ for (;;) {
+ c = input_stack::get_char();
+ if (c == EOF) {
+ lex_error("end of input while scanning macro arguments");
+ break;
+ }
+ if (state == NORMAL && level == 0 && (c == ',' || c == ')')) {
+ if (token_buffer.length() > 0) {
+ token_buffer += '\0';
+ argv[argc] = strsave(token_buffer.contents());
+ }
+ // for `foo()', argc = 0
+ if (argc > 0 || c != ')' || i > 0)
+ argc++;
+ break;
+ }
+ token_buffer += char(c);
+ switch (state) {
+ case NORMAL:
+ if (c == '"')
+ state = IN_STRING;
+ else if (c == '(')
+ level++;
+ else if (c == ')')
+ level--;
+ break;
+ case IN_STRING:
+ if (c == '"')
+ state = NORMAL;
+ else if (c == '\\')
+ state = IN_STRING_QUOTED;
+ break;
+ case IN_STRING_QUOTED:
+ state = IN_STRING;
+ break;
+ }
+ }
+ } while (c != ')' && c != EOF);
+ input_stack::push(new argument_macro_input(body, argc, argv));
+}
+
+static int docmp(const char *s1, int n1, const char *s2, int n2)
+{
+ if (n1 < n2) {
+ int r = memcmp(s1, s2, n1);
+ return r ? r : -1;
+ }
+ else if (n1 > n2) {
+ int r = memcmp(s1, s2, n2);
+ return r ? r : 1;
+ }
+ else
+ return memcmp(s1, s2, n1);
+}
+
+int lookup_keyword(const char *str, int len)
+{
+ static struct keyword {
+ const char *name;
+ int token;
+ } table[] = {
+ "Here", HERE,
+ "above", ABOVE,
+ "aligned", ALIGNED,
+ "and", AND,
+ "arc", ARC,
+ "arrow", ARROW,
+ "at", AT,
+ "atan2", ATAN2,
+ "below", BELOW,
+ "between", BETWEEN,
+ "bottom", BOTTOM,
+ "box", BOX,
+ "by", BY,
+ "ccw", CCW,
+ "center", CENTER,
+ "chop", CHOP,
+ "circle", CIRCLE,
+ "command", COMMAND,
+ "copy", COPY,
+ "cos", COS,
+ "cw", CW,
+ "dashed", DASHED,
+ "define", DEFINE,
+ "diam", DIAMETER,
+ "diameter", DIAMETER,
+ "do", DO,
+ "dotted", DOTTED,
+ "down", DOWN,
+ "ellipse", ELLIPSE,
+ "else", ELSE,
+ "end", END,
+ "exp", EXP,
+ "fill", FILL,
+ "filled", FILL,
+ "for", FOR,
+ "from", FROM,
+ "height", HEIGHT,
+ "ht", HEIGHT,
+ "if", IF,
+ "int", INT,
+ "invis", INVISIBLE,
+ "invisible", INVISIBLE,
+ "last", LAST,
+ "left", LEFT,
+ "line", LINE,
+ "ljust", LJUST,
+ "log", LOG,
+ "lower", LOWER,
+ "max", K_MAX,
+ "min", K_MIN,
+ "move", MOVE,
+ "of", OF,
+ "plot", PLOT,
+ "print", PRINT,
+ "rad", RADIUS,
+ "radius", RADIUS,
+ "rand", RAND,
+ "reset", RESET,
+ "right", RIGHT,
+ "rjust", RJUST,
+ "same", SAME,
+ "sh", SH,
+ "sin", SIN,
+ "spline", SPLINE,
+ "sprintf", SPRINTF,
+ "sqrt", SQRT,
+ "start", START,
+ "the", THE,
+ "then", THEN,
+ "thick", THICKNESS,
+ "thickness", THICKNESS,
+ "thru", THRU,
+ "to", TO,
+ "top", TOP,
+ "undef", UNDEF,
+ "until", UNTIL,
+ "up", UP,
+ "upper", UPPER,
+ "way", WAY,
+ "wid", WIDTH,
+ "width", WIDTH,
+ "with", WITH,
+ };
+
+ const keyword *start = table;
+ const keyword *end = table + sizeof(table)/sizeof(table[0]);
+ while (start < end) {
+ // start <= target < end
+ const keyword *mid = start + (end - start)/2;
+
+ int cmp = docmp(str, len, mid->name, strlen(mid->name));
+ if (cmp == 0)
+ return mid->token;
+ if (cmp < 0)
+ end = mid;
+ else
+ start = mid + 1;
+ }
+ return 0;
+}
+
+int get_token_after_dot(int c)
+{
+ // get_token deals with the case where c is a digit
+ switch (c) {
+ case 'h':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".ht";
+ return DOT_HT;
+ }
+ else if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'i') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'g') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".height";
+ return DOT_HT;
+ }
+ input_stack::push_back('h');
+ }
+ input_stack::push_back('g');
+ }
+ input_stack::push_back('i');
+ }
+ input_stack::push_back('e');
+ }
+ input_stack::push_back('h');
+ return '.';
+ case 'x':
+ input_stack::get_char();
+ context_buffer = ".x";
+ return DOT_X;
+ case 'y':
+ input_stack::get_char();
+ context_buffer = ".y";
+ return DOT_Y;
+ case 'c':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'n') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'r') {
+ input_stack::get_char();
+ context_buffer = ".center";
+ return DOT_C;
+ }
+ input_stack::push_back('e');
+ }
+ input_stack::push_back('t');
+ }
+ input_stack::push_back('n');
+ }
+ input_stack::push_back('e');
+ }
+ context_buffer = ".c";
+ return DOT_C;
+ case 'n':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ context_buffer = ".ne";
+ return DOT_NE;
+ }
+ else if (c == 'w') {
+ input_stack::get_char();
+ context_buffer = ".nw";
+ return DOT_NW;
+ }
+ else {
+ context_buffer = ".n";
+ return DOT_N;
+ }
+ break;
+ case 'e':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'n') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ context_buffer = ".end";
+ return DOT_END;
+ }
+ input_stack::push_back('n');
+ context_buffer = ".e";
+ return DOT_E;
+ }
+ context_buffer = ".e";
+ return DOT_E;
+ case 'w':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'i') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ context_buffer = ".width";
+ return DOT_WID;
+ }
+ input_stack::push_back('t');
+ }
+ context_buffer = ".wid";
+ return DOT_WID;
+ }
+ input_stack::push_back('i');
+ }
+ context_buffer = ".w";
+ return DOT_W;
+ case 's':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ context_buffer = ".se";
+ return DOT_SE;
+ }
+ else if (c == 'w') {
+ input_stack::get_char();
+ context_buffer = ".sw";
+ return DOT_SW;
+ }
+ else {
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'a') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'r') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".start";
+ return DOT_START;
+ }
+ input_stack::push_back('r');
+ }
+ input_stack::push_back('a');
+ }
+ input_stack::push_back('t');
+ }
+ context_buffer = ".s";
+ return DOT_S;
+ }
+ break;
+ case 't':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'o') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'p') {
+ input_stack::get_char();
+ context_buffer = ".top";
+ return DOT_N;
+ }
+ input_stack::push_back('o');
+ }
+ context_buffer = ".t";
+ return DOT_N;
+ case 'l':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'f') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".left";
+ return DOT_W;
+ }
+ input_stack::push_back('f');
+ }
+ input_stack::push_back('e');
+ }
+ context_buffer = ".l";
+ return DOT_W;
+ case 'r':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'a') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ context_buffer = ".rad";
+ return DOT_RAD;
+ }
+ input_stack::push_back('a');
+ }
+ else if (c == 'i') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'g') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".right";
+ return DOT_E;
+ }
+ input_stack::push_back('h');
+ }
+ input_stack::push_back('g');
+ }
+ input_stack::push_back('i');
+ }
+ context_buffer = ".r";
+ return DOT_E;
+ case 'b':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'o') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'o') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'm') {
+ input_stack::get_char();
+ context_buffer = ".bottom";
+ return DOT_S;
+ }
+ input_stack::push_back('o');
+ }
+ input_stack::push_back('t');
+ }
+ context_buffer = ".bot";
+ return DOT_S;
+ }
+ input_stack::push_back('o');
+ }
+ context_buffer = ".b";
+ return DOT_S;
+ default:
+ context_buffer = '.';
+ return '.';
+ }
+}
+
+int get_token(int lookup_flag)
+{
+ context_buffer.clear();
+ for (;;) {
+ int n = 0;
+ int bol = input_stack::bol();
+ int c = input_stack::get_char();
+ if (bol && c == command_char) {
+ token_buffer.clear();
+ token_buffer += c;
+ // the newline is not part of the token
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || c == '\n')
+ break;
+ input_stack::get_char();
+ token_buffer += char(c);
+ }
+ context_buffer = token_buffer;
+ return COMMAND_LINE;
+ }
+ switch (c) {
+ case EOF:
+ return EOF;
+ case ' ':
+ case '\t':
+ break;
+ case '\\':
+ {
+ int d = input_stack::peek_char();
+ if (d != '\n') {
+ context_buffer = '\\';
+ return '\\';
+ }
+ input_stack::get_char();
+ break;
+ }
+ case '#':
+ do {
+ c = input_stack::get_char();
+ } while (c != '\n' && c != EOF);
+ if (c == '\n')
+ context_buffer = '\n';
+ return c;
+ case '"':
+ context_buffer = '"';
+ token_buffer.clear();
+ for (;;) {
+ c = input_stack::get_char();
+ if (c == '\\') {
+ context_buffer += '\\';
+ c = input_stack::peek_char();
+ if (c == '"') {
+ input_stack::get_char();
+ token_buffer += '"';
+ context_buffer += '"';
+ }
+ else
+ token_buffer += '\\';
+ }
+ else if (c == '\n') {
+ error("newline in string");
+ break;
+ }
+ else if (c == EOF) {
+ error("missing `\"'");
+ break;
+ }
+ else if (c == '"') {
+ context_buffer += '"';
+ break;
+ }
+ else {
+ context_buffer += char(c);
+ token_buffer += char(c);
+ }
+ }
+ return TEXT;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int overflow = 0;
+ n = 0;
+ for (;;) {
+ if (n > (INT_MAX - 9)/10) {
+ overflow = 1;
+ break;
+ }
+ n *= 10;
+ n += c - '0';
+ context_buffer += char(c);
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c))
+ break;
+ c = input_stack::get_char();
+ }
+ token_double = n;
+ if (overflow) {
+ for (;;) {
+ token_double *= 10.0;
+ token_double += c - '0';
+ context_buffer += char(c);
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c))
+ break;
+ c = input_stack::get_char();
+ }
+ // if somebody asks for 1000000000000th, we will silently
+ // give them INT_MAXth
+ double temp = token_double; // work around gas 1.34/sparc bug
+ if (token_double > INT_MAX)
+ n = INT_MAX;
+ else
+ n = int(temp);
+ }
+ }
+ switch (c) {
+ case 'i':
+ case 'I':
+ context_buffer += char(c);
+ input_stack::get_char();
+ return NUMBER;
+ case '.':
+ {
+ context_buffer += '.';
+ input_stack::get_char();
+ got_dot:
+ double factor = 1.0;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (!c == EOF || !csdigit(c))
+ break;
+ input_stack::get_char();
+ context_buffer += char(c);
+ factor /= 10.0;
+ if (c != '0')
+ token_double += factor*(c - '0');
+ }
+ if (c != 'e' && c != 'E') {
+ if (c == 'i' || c == 'I') {
+ context_buffer += char(c);
+ input_stack::get_char();
+ }
+ return NUMBER;
+ }
+ }
+ // fall through
+ case 'e':
+ case 'E':
+ {
+ int echar = c;
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ int sign = '+';
+ if (c == '+' || c == '-') {
+ sign = c;
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c)) {
+ input_stack::push_back(sign);
+ input_stack::push_back(echar);
+ return NUMBER;
+ }
+ context_buffer += char(echar);
+ context_buffer += char(sign);
+ }
+ else {
+ if (c == EOF || !csdigit(c)) {
+ input_stack::push_back(echar);
+ return NUMBER;
+ }
+ context_buffer += char(echar);
+ }
+ input_stack::get_char();
+ context_buffer += char(c);
+ n = c - '0';
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c))
+ break;
+ input_stack::get_char();
+ context_buffer += char(c);
+ n = n*10 + (c - '0');
+ }
+ if (sign == '-')
+ n = -n;
+ if (c == 'i' || c == 'I') {
+ context_buffer += char(c);
+ input_stack::get_char();
+ }
+ token_double *= pow(10.0, n);
+ return NUMBER;
+ }
+ case 'n':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "nd";
+ return ORDINAL;
+ }
+ input_stack::push_back('n');
+ return NUMBER;
+ case 'r':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "rd";
+ return ORDINAL;
+ }
+ input_stack::push_back('r');
+ return NUMBER;
+ case 't':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "th";
+ return ORDINAL;
+ }
+ input_stack::push_back('t');
+ return NUMBER;
+ case 's':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "st";
+ return ORDINAL;
+ }
+ input_stack::push_back('s');
+ return NUMBER;
+ default:
+ return NUMBER;
+ }
+ break;
+ case '\'':
+ {
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ context_buffer = "'th";
+ return TH;
+ }
+ else
+ input_stack::push_back('t');
+ }
+ context_buffer = "'";
+ return '\'';
+ }
+ case '.':
+ {
+ c = input_stack::peek_char();
+ if (c != EOF && csdigit(c)) {
+ n = 0;
+ token_double = 0.0;
+ context_buffer = '.';
+ goto got_dot;
+ }
+ return get_token_after_dot(c);
+ }
+ case '<':
+ c = input_stack::peek_char();
+ if (c == '-') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == '>') {
+ input_stack::get_char();
+ context_buffer = "<->";
+ return DOUBLE_ARROW_HEAD;
+ }
+ context_buffer = "<-";
+ return LEFT_ARROW_HEAD;
+ }
+ else if (c == '=') {
+ input_stack::get_char();
+ context_buffer = "<=";
+ return LESSEQUAL;
+ }
+ context_buffer = "<";
+ return '<';
+ case '-':
+ c = input_stack::peek_char();
+ if (c == '>') {
+ input_stack::get_char();
+ context_buffer = "->";
+ return RIGHT_ARROW_HEAD;
+ }
+ context_buffer = "-";
+ return '-';
+ case '!':
+ c = input_stack::peek_char();
+ if (c == '=') {
+ input_stack::get_char();
+ context_buffer = "!=";
+ return NOTEQUAL;
+ }
+ context_buffer = "!";
+ return '!';
+ case '>':
+ c = input_stack::peek_char();
+ if (c == '=') {
+ input_stack::get_char();
+ context_buffer = ">=";
+ return GREATEREQUAL;
+ }
+ context_buffer = ">";
+ return '>';
+ case '=':
+ c = input_stack::peek_char();
+ if (c == '=') {
+ input_stack::get_char();
+ context_buffer = "==";
+ return EQUALEQUAL;
+ }
+ context_buffer = "=";
+ return '=';
+ case '&':
+ c = input_stack::peek_char();
+ if (c == '&') {
+ input_stack::get_char();
+ context_buffer = "&&";
+ return ANDAND;
+ }
+ context_buffer = "&";
+ return '&';
+ case '|':
+ c = input_stack::peek_char();
+ if (c == '|') {
+ input_stack::get_char();
+ context_buffer = "||";
+ return OROR;
+ }
+ context_buffer = "|";
+ return '|';
+ default:
+ if (c != EOF && csalpha(c)) {
+ token_buffer.clear();
+ token_buffer = c;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || (!csalnum(c) && c != '_'))
+ break;
+ input_stack::get_char();
+ token_buffer += char(c);
+ }
+ int tok = lookup_keyword(token_buffer.contents(),
+ token_buffer.length());
+ if (tok != 0) {
+ context_buffer = token_buffer;
+ return tok;
+ }
+ char *def = 0;
+ if (lookup_flag) {
+ token_buffer += '\0';
+ def = macro_table.lookup(token_buffer.contents());
+ token_buffer.set_length(token_buffer.length() - 1);
+ if (def) {
+ if (c == '(') {
+ input_stack::get_char();
+ interpolate_macro_with_args(def);
+ }
+ else
+ input_stack::push(new macro_input(def));
+ }
+ }
+ if (!def) {
+ context_buffer = token_buffer;
+ if (csupper(token_buffer[0]))
+ return LABEL;
+ else
+ return VARIABLE;
+ }
+ }
+ else {
+ context_buffer = char(c);
+ return (unsigned char)c;
+ }
+ break;
+ }
+ }
+}
+
+int get_delimited()
+{
+ token_buffer.clear();
+ int c = input_stack::get_char();
+ while (c == ' ' || c == '\t' || c == '\n')
+ c = input_stack::get_char();
+ if (c == EOF) {
+ lex_error("missing delimiter");
+ return 0;
+ }
+ context_buffer = char(c);
+ int had_newline = 0;
+ int start = c;
+ int level = 0;
+ enum { NORMAL, IN_STRING, IN_STRING_QUOTED, DELIM_END } state = NORMAL;
+ for (;;) {
+ c = input_stack::get_char();
+ if (c == EOF) {
+ lex_error("missing closing delimiter");
+ return 0;
+ }
+ if (c == '\n')
+ had_newline = 1;
+ else if (!had_newline)
+ context_buffer += char(c);
+ switch (state) {
+ case NORMAL:
+ if (start == '{') {
+ if (c == '{') {
+ level++;
+ break;
+ }
+ if (c == '}') {
+ if (--level < 0)
+ state = DELIM_END;
+ break;
+ }
+ }
+ else {
+ if (c == start) {
+ state = DELIM_END;
+ break;
+ }
+ }
+ if (c == '"')
+ state = IN_STRING;
+ break;
+ case IN_STRING_QUOTED:
+ if (c == '\n')
+ state = NORMAL;
+ else
+ state = IN_STRING;
+ break;
+ case IN_STRING:
+ if (c == '"' || c == '\n')
+ state = NORMAL;
+ else if (c == '\\')
+ state = IN_STRING_QUOTED;
+ break;
+ case DELIM_END:
+ // This case it just to shut cfront 2.0 up.
+ default:
+ assert(0);
+ }
+ if (state == DELIM_END)
+ break;
+ token_buffer += c;
+ }
+ return 1;
+}
+
+void do_define()
+{
+ int t = get_token(0); // do not expand what we are defining
+ if (t != VARIABLE && t != LABEL) {
+ lex_error("can only define variable or placename");
+ return;
+ }
+ token_buffer += '\0';
+ string nm = token_buffer;
+ const char *name = nm.contents();
+ if (!get_delimited())
+ return;
+ token_buffer += '\0';
+ macro_table.define(name, strsave(token_buffer.contents()));
+}
+
+void do_undef()
+{
+ int t = get_token(0); // do not expand what we are undefining
+ if (t != VARIABLE && t != LABEL) {
+ lex_error("can only define variable or placename");
+ return;
+ }
+ token_buffer += '\0';
+ macro_table.define(token_buffer.contents(), 0);
+}
+
+
+class for_input : public input {
+ char *var;
+ char *body;
+ double to;
+ int by_is_multiplicative;
+ double by;
+ const char *p;
+ int done_newline;
+public:
+ for_input(char *, double, int, double, char *);
+ ~for_input();
+ int get();
+ int peek();
+};
+
+for_input::for_input(char *vr, double t, int bim, double b, char *bd)
+: var(vr), to(t), by_is_multiplicative(bim), by(b), body(bd), p(body),
+ done_newline(0)
+{
+}
+
+for_input::~for_input()
+{
+ a_delete var;
+ a_delete body;
+}
+
+int for_input::get()
+{
+ if (p == 0)
+ return EOF;
+ for (;;) {
+ if (*p != '\0')
+ return (unsigned char)*p++;
+ if (!done_newline) {
+ done_newline = 1;
+ return '\n';
+ }
+ double val;
+ if (!lookup_variable(var, &val)) {
+ lex_error("body of `for' terminated enclosing block");
+ return EOF;
+ }
+ if (by_is_multiplicative)
+ val *= by;
+ else
+ val += by;
+ define_variable(var, val);
+ if (val > to) {
+ p = 0;
+ return EOF;
+ }
+ p = body;
+ done_newline = 0;
+ }
+}
+
+int for_input::peek()
+{
+ if (p == 0)
+ return EOF;
+ if (*p != '\0')
+ return (unsigned char)*p;
+ if (!done_newline)
+ return '\n';
+ double val;
+ if (!lookup_variable(var, &val))
+ return EOF;
+ if (by_is_multiplicative) {
+ if (val * by > to)
+ return EOF;
+ }
+ else {
+ if (val + by > to)
+ return EOF;
+ }
+ if (*body == '\0')
+ return EOF;
+ return (unsigned char)*body;
+}
+
+void do_for(char *var, double from, double to, int by_is_multiplicative,
+ double by, char *body)
+{
+ define_variable(var, from);
+ if (from <= to)
+ input_stack::push(new for_input(var, to, by_is_multiplicative, by, body));
+}
+
+
+void do_copy(const char *filename)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ lex_error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ input_stack::push(new file_input(fp, filename));
+}
+
+class copy_thru_input : public input {
+ int done;
+ char *body;
+ char *until;
+ const char *p;
+ const char *ap;
+ int argv[9];
+ int argc;
+ string line;
+ int get_line();
+ virtual int inget() = 0;
+public:
+ copy_thru_input(const char *b, const char *u);
+ ~copy_thru_input();
+ int get();
+ int peek();
+};
+
+class copy_file_thru_input : public copy_thru_input {
+ input *in;
+public:
+ copy_file_thru_input(input *, const char *b, const char *u);
+ ~copy_file_thru_input();
+ int inget();
+};
+
+copy_file_thru_input::copy_file_thru_input(input *i, const char *b,
+ const char *u)
+: in(i), copy_thru_input(b, u)
+{
+}
+
+copy_file_thru_input::~copy_file_thru_input()
+{
+ delete in;
+}
+
+int copy_file_thru_input::inget()
+{
+ if (!in)
+ return EOF;
+ else
+ return in->get();
+}
+
+class copy_rest_thru_input : public copy_thru_input {
+public:
+ copy_rest_thru_input(const char *, const char *u);
+ int inget();
+};
+
+copy_rest_thru_input::copy_rest_thru_input(const char *b, const char *u)
+: copy_thru_input(b, u)
+{
+}
+
+int copy_rest_thru_input::inget()
+{
+ while (next != 0) {
+ int c = next->get();
+ if (c != EOF)
+ return c;
+ if (next->next == 0)
+ return EOF;
+ input *tem = next;
+ next = next->next;
+ delete tem;
+ }
+ return EOF;
+
+}
+
+copy_thru_input::copy_thru_input(const char *b, const char *u)
+: done(0)
+{
+ ap = 0;
+ body = process_body(b);
+ p = 0;
+ until = strsave(u);
+}
+
+
+copy_thru_input::~copy_thru_input()
+{
+ a_delete body;
+ a_delete until;
+}
+
+int copy_thru_input::get()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap++;
+ ap = 0;
+ }
+ for (;;) {
+ if (p == 0) {
+ if (!get_line())
+ break;
+ p = body;
+ }
+ if (*p == '\0') {
+ p = 0;
+ return '\n';
+ }
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && line[argv[i]] != '\0') {
+ ap = line.contents() + argv[i];
+ return (unsigned char)*ap++;
+ }
+ }
+ if (*p != '\0')
+ return (unsigned char)*p++;
+ }
+ return EOF;
+}
+
+int copy_thru_input::peek()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap;
+ ap = 0;
+ }
+ for (;;) {
+ if (p == 0) {
+ if (!get_line())
+ break;
+ p = body;
+ }
+ if (*p == '\0')
+ return '\n';
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && line[argv[i]] != '\0') {
+ ap = line.contents() + argv[i];
+ return (unsigned char)*ap;
+ }
+ }
+ if (*p != '\0')
+ return (unsigned char)*p;
+ }
+ return EOF;
+}
+
+int copy_thru_input::get_line()
+{
+ if (done)
+ return 0;
+ line.clear();
+ argc = 0;
+ int c = inget();
+ for (;;) {
+ while (c == ' ')
+ c = inget();
+ if (c == EOF || c == '\n')
+ break;
+ if (argc == 9) {
+ do {
+ c = inget();
+ } while (c != '\n' && c != EOF);
+ break;
+ }
+ argv[argc++] = line.length();
+ do {
+ line += char(c);
+ c = inget();
+ } while (c != ' ' && c != '\n');
+ line += '\0';
+ }
+ if (until != 0 && argc > 0 && strcmp(&line[argv[0]], until) == 0) {
+ done = 1;
+ return 0;
+ }
+ return argc > 0 || c == '\n';
+}
+
+class simple_file_input : public input {
+ const char *filename;
+ int lineno;
+ FILE *fp;
+public:
+ simple_file_input(FILE *, const char *);
+ ~simple_file_input();
+ int get();
+ int peek();
+ int get_location(const char **, int *);
+};
+
+simple_file_input::simple_file_input(FILE *p, const char *s)
+: filename(s), fp(p), lineno(1)
+{
+}
+
+simple_file_input::~simple_file_input()
+{
+ // don't delete the filename
+ fclose(fp);
+}
+
+int simple_file_input::get()
+{
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", c);
+ c = getc(fp);
+ }
+ if (c == '\n')
+ lineno++;
+ return c;
+}
+
+int simple_file_input::peek()
+{
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", c);
+ c = getc(fp);
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ return c;
+}
+
+int simple_file_input::get_location(const char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+
+void copy_file_thru(const char *filename, const char *body, const char *until)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ lex_error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ input *in = new copy_file_thru_input(new simple_file_input(fp, filename),
+ body, until);
+ input_stack::push(in);
+}
+
+void copy_rest_thru(const char *body, const char *until)
+{
+ input_stack::push(new copy_rest_thru_input(body, until));
+}
+
+void push_body(const char *s)
+{
+ input_stack::push(new char_input('\n'));
+ input_stack::push(new macro_input(s));
+}
+
+int delim_flag = 0;
+
+char *get_thru_arg()
+{
+ int c = input_stack::peek_char();
+ while (c == ' ') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ }
+ if (c != EOF && csalpha(c)) {
+ // looks like a macro
+ input_stack::get_char();
+ token_buffer = c;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || (!csalnum(c) && c != '_'))
+ break;
+ input_stack::get_char();
+ token_buffer += char(c);
+ }
+ context_buffer = token_buffer;
+ token_buffer += '\0';
+ char *def = macro_table.lookup(token_buffer.contents());
+ if (def)
+ return strsave(def);
+ // I guess it wasn't a macro after all; so push the macro name back.
+ // -2 because we added a '\0'
+ for (int i = token_buffer.length() - 2; i >= 0; i--)
+ input_stack::push_back(token_buffer[i]);
+ }
+ if (get_delimited()) {
+ token_buffer += '\0';
+ return strsave(token_buffer.contents());
+ }
+ else
+ return 0;
+}
+
+int lookahead_token = -1;
+string old_context_buffer;
+
+void do_lookahead()
+{
+ if (lookahead_token == -1) {
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ }
+}
+
+int yylex()
+{
+ if (delim_flag) {
+ assert(lookahead_token == -1);
+ if (delim_flag == 2) {
+ if ((yylval.str = get_thru_arg()) != 0)
+ return DELIMITED;
+ else
+ return 0;
+ }
+ else {
+ if (get_delimited()) {
+ token_buffer += '\0';
+ yylval.str = strsave(token_buffer.contents());
+ return DELIMITED;
+ }
+ else
+ return 0;
+ }
+ }
+ for (;;) {
+ int t;
+ if (lookahead_token >= 0) {
+ t = lookahead_token;
+ lookahead_token = -1;
+ }
+ else
+ t = get_token(1);
+ switch (t) {
+ case '\n':
+ return ';';
+ case EOF:
+ return 0;
+ case DEFINE:
+ do_define();
+ break;
+ case UNDEF:
+ do_undef();
+ break;
+ case ORDINAL:
+ yylval.n = token_int;
+ return t;
+ case NUMBER:
+ yylval.x = token_double;
+ return t;
+ case COMMAND_LINE:
+ case TEXT:
+ token_buffer += '\0';
+ if (!input_stack::get_location(&yylval.lstr.filename,
+ &yylval.lstr.lineno)) {
+ yylval.lstr.filename = 0;
+ yylval.lstr.lineno = -1;
+ }
+ yylval.lstr.str = strsave(token_buffer.contents());
+ return t;
+ case LABEL:
+ case VARIABLE:
+ token_buffer += '\0';
+ yylval.str = strsave(token_buffer.contents());
+ return t;
+ case LEFT:
+ // change LEFT to LEFT_CORNER when followed by OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token == OF)
+ return LEFT_CORNER;
+ else
+ return t;
+ case RIGHT:
+ // change RIGHT to RIGHT_CORNER when followed by OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token == OF)
+ return RIGHT_CORNER;
+ else
+ return t;
+ case UPPER:
+ // recognise UPPER only before LEFT or RIGHT
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != LEFT && lookahead_token != RIGHT) {
+ yylval.str = strsave("upper");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case LOWER:
+ // recognise LOWER only before LEFT or RIGHT
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != LEFT && lookahead_token != RIGHT) {
+ yylval.str = strsave("lower");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case TOP:
+ // recognise TOP only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("top");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case BOTTOM:
+ // recognise BOTTOM only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("bottom");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case CENTER:
+ // recognise CENTER only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("center");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case START:
+ // recognise START only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("start");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case END:
+ // recognise END only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("end");
+ return VARIABLE;
+ }
+ else
+ return t;
+ default:
+ return t;
+ }
+ }
+}
+
+void lex_error(const char *message,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ if (!input_stack::get_location(&filename, &lineno))
+ error(message, arg1, arg2, arg3);
+ else
+ error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
+}
+
+void lex_warning(const char *message,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ if (!input_stack::get_location(&filename, &lineno))
+ warning(message, arg1, arg2, arg3);
+ else
+ warning_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
+}
+
+void yyerror(const char *s)
+{
+ const char *filename;
+ int lineno;
+ const char *context = 0;
+ if (lookahead_token == -1) {
+ if (context_buffer.length() > 0) {
+ context_buffer += '\0';
+ context = context_buffer.contents();
+ }
+ }
+ else {
+ if (old_context_buffer.length() > 0) {
+ old_context_buffer += '\0';
+ context = old_context_buffer.contents();
+ }
+ }
+ if (!input_stack::get_location(&filename, &lineno)) {
+ if (context) {
+ if (context[0] == '\n' && context[1] == '\0')
+ error("%1 before newline", s);
+ else
+ error("%1 before `%2'", s, context);
+ }
+ else
+ error("%1 at end of picture", s);
+ }
+ else {
+ if (context) {
+ if (context[0] == '\n' && context[1] == '\0')
+ error_with_file_and_line(filename, lineno, "%1 before newline", s);
+ else
+ error_with_file_and_line(filename, lineno, "%1 before `%2'",
+ s, context);
+ }
+ else
+ error_with_file_and_line(filename, lineno, "%1 at end of picture", s);
+ }
+}
+
diff --git a/gnu/usr.bin/groff/pic/main.cc b/gnu/usr.bin/groff/pic/main.cc
new file mode 100644
index 000000000000..fe608ebd98a9
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/main.cc
@@ -0,0 +1,611 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "pic.h"
+
+extern int yyparse();
+
+output *out;
+
+int flyback_flag;
+int zero_length_line_flag = 0;
+// Non-zero means we're using a groff driver.
+int driver_extension_flag = 1;
+int compatible_flag = 0;
+int command_char = '.'; // the character that introduces lines
+ // that should be passed through tranparently
+static int lf_flag = 1; // non-zero if we should attempt to understand
+ // lines beginning with `.lf'
+
+void do_file(const char *filename);
+
+class top_input : public input {
+ FILE *fp;
+ int bol;
+ int eof;
+ int push_back[3];
+ int start_lineno;
+public:
+ top_input(FILE *);
+ int get();
+ int peek();
+ int get_location(const char **, int *);
+};
+
+top_input::top_input(FILE *p) : fp(p), bol(1), eof(0)
+{
+ push_back[0] = push_back[1] = push_back[2] = EOF;
+ start_lineno = current_lineno;
+}
+
+int top_input::get()
+{
+ if (eof)
+ return EOF;
+ if (push_back[2] != EOF) {
+ int c = push_back[2];
+ push_back[2] = EOF;
+ return c;
+ }
+ else if (push_back[1] != EOF) {
+ int c = push_back[1];
+ push_back[1] = EOF;
+ return c;
+ }
+ else if (push_back[0] != EOF) {
+ int c = push_back[0];
+ push_back[0] = EOF;
+ return c;
+ }
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", int(c));
+ c = getc(fp);
+ bol = 0;
+ }
+ if (bol && c == '.') {
+ c = getc(fp);
+ if (c == 'P') {
+ c = getc(fp);
+ if (c == 'F' || c == 'E') {
+ int d = getc(fp);
+ if (d != EOF)
+ ungetc(d, fp);
+ if (d == EOF || d == ' ' || d == '\n' || compatible_flag) {
+ eof = 1;
+ flyback_flag = c == 'F';
+ return EOF;
+ }
+ push_back[0] = c;
+ push_back[1] = 'P';
+ return '.';
+ }
+ if (c == 'S') {
+ c = getc(fp);
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == EOF || c == ' ' || c == '\n' || compatible_flag) {
+ error("nested .PS");
+ eof = 1;
+ return EOF;
+ }
+ push_back[0] = 'S';
+ push_back[1] = 'P';
+ return '.';
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ push_back[0] = 'P';
+ return '.';
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ return '.';
+ }
+ }
+ if (c == '\n') {
+ bol = 1;
+ current_lineno++;
+ return '\n';
+ }
+ bol = 0;
+ if (c == EOF) {
+ eof = 1;
+ error("end of file before .PE or .PF");
+ error_with_file_and_line(current_filename, start_lineno - 1,
+ ".PS was here");
+ }
+ return c;
+}
+
+int top_input::peek()
+{
+ if (eof)
+ return EOF;
+ if (push_back[2] != EOF)
+ return push_back[2];
+ if (push_back[1] != EOF)
+ return push_back[1];
+ if (push_back[0] != EOF)
+ return push_back[0];
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", int(c));
+ c = getc(fp);
+ bol = 0;
+ }
+ if (bol && c == '.') {
+ c = getc(fp);
+ if (c == 'P') {
+ c = getc(fp);
+ if (c == 'F' || c == 'E') {
+ int d = getc(fp);
+ if (d != EOF)
+ ungetc(d, fp);
+ if (d == EOF || d == ' ' || d == '\n' || compatible_flag) {
+ eof = 1;
+ flyback_flag = c == 'F';
+ return EOF;
+ }
+ push_back[0] = c;
+ push_back[1] = 'P';
+ push_back[2] = '.';
+ return '.';
+ }
+ if (c == 'S') {
+ c = getc(fp);
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == EOF || c == ' ' || c == '\n' || compatible_flag) {
+ error("nested .PS");
+ eof = 1;
+ return EOF;
+ }
+ push_back[0] = 'S';
+ push_back[1] = 'P';
+ push_back[2] = '.';
+ return '.';
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ push_back[0] = 'P';
+ push_back[1] = '.';
+ return '.';
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ push_back[0] = '.';
+ return '.';
+ }
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == '\n')
+ return '\n';
+ return c;
+}
+
+int top_input::get_location(const char **filenamep, int *linenop)
+{
+ *filenamep = current_filename;
+ *linenop = current_lineno;
+ return 1;
+}
+
+void do_picture(FILE *fp)
+{
+ flyback_flag = 0;
+ int c;
+ while ((c = getc(fp)) == ' ')
+ ;
+ if (c == '<') {
+ string filename;
+ while ((c = getc(fp)) == ' ')
+ ;
+ while (c != EOF && c != ' ' && c != '\n') {
+ filename += char(c);
+ c = getc(fp);
+ }
+ if (c == ' ') {
+ do {
+ c = getc(fp);
+ } while (c != EOF && c != '\n');
+ }
+ if (c == '\n')
+ current_lineno++;
+ if (filename.length() == 0)
+ error("missing filename after `<'");
+ else {
+ filename += '\0';
+ const char *old_filename = current_filename;
+ int old_lineno = current_lineno;
+ // filenames must be permanent
+ do_file(strsave(filename.contents()));
+ current_filename = old_filename;
+ current_lineno = old_lineno;
+ }
+ out->set_location(current_filename, current_lineno);
+ }
+ else {
+ out->set_location(current_filename, current_lineno);
+ string start_line;
+ while (c != EOF) {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ start_line += c;
+ c = getc(fp);
+ }
+ if (c == EOF)
+ return;
+ start_line += '\0';
+ double wid, ht;
+ switch (sscanf(&start_line[0], "%lf %lf", &wid, &ht)) {
+ case 1:
+ ht = 0.0;
+ break;
+ case 2:
+ break;
+ default:
+ ht = wid = 0.0;
+ break;
+ }
+ out->set_desired_width_height(wid, ht);
+ out->set_args(start_line.contents());
+ lex_init(new top_input(fp));
+ if (yyparse())
+ lex_error("giving up on this picture");
+ parse_cleanup();
+ lex_cleanup();
+
+ // skip the rest of the .PF/.PE line
+ while ((c = getc(fp)) != EOF && c != '\n')
+ ;
+ if (c == '\n')
+ current_lineno++;
+ out->set_location(current_filename, current_lineno);
+ }
+}
+
+void do_file(const char *filename)
+{
+ FILE *fp;
+ if (strcmp(filename, "-") == 0)
+ fp = stdin;
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0)
+ fatal("can't open `%1': %2", filename, strerror(errno));
+ }
+ out->set_location(filename, 1);
+ current_filename = filename;
+ current_lineno = 1;
+ enum { START, MIDDLE, HAD_DOT, HAD_P, HAD_PS, HAD_l, HAD_lf } state = START;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ switch (state) {
+ case START:
+ if (c == '.')
+ state = HAD_DOT;
+ else {
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ break;
+ case HAD_DOT:
+ if (c == 'P')
+ state = HAD_P;
+ else if (lf_flag && c == 'l')
+ state = HAD_l;
+ else {
+ putchar('.');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_P:
+ if (c == 'S')
+ state = HAD_PS;
+ else {
+ putchar('.');
+ putchar('P');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_PS:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ ungetc(c, fp);
+ do_picture(fp);
+ state = START;
+ }
+ else {
+ fputs(".PS", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ case HAD_l:
+ if (c == 'f')
+ state = HAD_lf;
+ else {
+ putchar('.');
+ putchar('l');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ while (c != EOF) {
+ line += c;
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ c = getc(fp);
+ }
+ line += '\0';
+ interpret_lf_args(line.contents());
+ printf(".lf%s", line.contents());
+ state = START;
+ }
+ else {
+ fputs(".lf", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ switch (state) {
+ case START:
+ break;
+ case MIDDLE:
+ putchar('\n');
+ break;
+ case HAD_DOT:
+ fputs(".\n", stdout);
+ break;
+ case HAD_P:
+ fputs(".P\n", stdout);
+ break;
+ case HAD_PS:
+ fputs(".PS\n", stdout);
+ break;
+ case HAD_l:
+ fputs(".l\n", stdout);
+ break;
+ case HAD_lf:
+ fputs(".lf\n", stdout);
+ break;
+ }
+ if (fp != stdin)
+ fclose(fp);
+}
+
+#ifdef FIG_SUPPORT
+void do_whole_file(const char *filename)
+{
+ // Do not set current_filename.
+ FILE *fp;
+ if (strcmp(filename, "-") == 0)
+ fp = stdin;
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0)
+ fatal("can't open `%1': %2", filename, strerror(errno));
+ }
+ lex_init(new file_input(fp, filename));
+ yyparse();
+ parse_cleanup();
+ lex_cleanup();
+}
+#endif
+
+void usage()
+{
+ fprintf(stderr, "usage: %s [ -nvC ] [ filename ... ]\n", program_name);
+#ifdef TEX_SUPPORT
+ fprintf(stderr, " %s -t [ -cvzC ] [ filename ... ]\n", program_name);
+#endif
+#ifdef FIG_SUPPORT
+ fprintf(stderr, " %s -f [ -v ] [ filename ]\n", program_name);
+#endif
+ exit(1);
+}
+
+#ifdef __MSDOS__
+static char *fix_program_name(char *arg, char *dflt)
+{
+ if (!arg)
+ return dflt;
+ char *prog = strchr(arg, '\0');
+ for (;;) {
+ if (prog == arg)
+ break;
+ --prog;
+ if (strchr("\\/:", *prog)) {
+ prog++;
+ break;
+ }
+ }
+ char *ext = strchr(prog, '.');
+ if (ext)
+ *ext = '\0';
+ for (char *p = prog; *p; p++)
+ if ('A' <= *p && *p <= 'Z')
+ *p = 'a' + (*p - 'A');
+ return prog;
+}
+#endif /* __MSDOS__ */
+
+int main(int argc, char **argv)
+{
+#ifdef __MSDOS__
+ argv[0] = fix_program_name(argv[0], "pic");
+#endif /* __MSDOS__ */
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+#ifdef TEX_SUPPORT
+ int tex_flag = 0;
+ int tpic_flag = 0;
+#endif
+#ifdef FIG_SUPPORT
+ int whole_file_flag = 0;
+ int fig_flag = 0;
+#endif
+ while ((opt = getopt(argc, argv, "T:CDtcvnxzpf")) != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'D':
+ case 'T':
+ break;
+ case 'f':
+#ifdef FIG_SUPPORT
+ whole_file_flag++;
+ fig_flag++;
+#else
+ fatal("fig support not included");
+#endif
+ break;
+ case 'n':
+ driver_extension_flag = 0;
+ break;
+ case 'p':
+ case 'x':
+ warning("-%1 option is obsolete", char(opt));
+ break;
+ case 't':
+#ifdef TEX_SUPPORT
+ tex_flag++;
+#else
+ fatal("TeX support not included");
+#endif
+ break;
+ case 'c':
+#ifdef TEX_SUPPORT
+ tpic_flag++;
+#else
+ fatal("TeX support not included");
+#endif
+ break;
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU pic version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'z':
+ // zero length lines will be printed as dots
+ zero_length_line_flag++;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ parse_init();
+#ifdef TEX_SUPPORT
+ if (tpic_flag) {
+ out = make_tpic_output();
+ lf_flag = 0;
+ }
+ else if (tex_flag) {
+ out = make_tex_output();
+ command_char = '\\';
+ lf_flag = 0;
+ }
+ else
+#endif
+#ifdef FIG_SUPPORT
+ if (fig_flag)
+ out = make_fig_output();
+ else
+#endif
+ out = make_troff_output();
+#ifdef FIG_SUPPORT
+ if (whole_file_flag) {
+ if (optind >= argc)
+ do_whole_file("-");
+ else if (argc - optind > 1)
+ usage();
+ else
+ do_whole_file(argv[optind]);
+ }
+ else {
+#endif
+ if (optind >= argc)
+ do_file("-");
+ else
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+#ifdef FIG_SUPPORT
+ }
+#endif
+ delete out;
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ exit(0);
+}
+
diff --git a/gnu/usr.bin/groff/pic/object.cc b/gnu/usr.bin/groff/pic/object.cc
new file mode 100644
index 000000000000..b5fbf59a8e49
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/object.cc
@@ -0,0 +1,1815 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "pic.h"
+#include "ptable.h"
+#include "object.h"
+
+void print_object_list(object *);
+
+line_type::line_type()
+: type(solid), thickness(1.0)
+{
+}
+
+output::output() : desired_height(0.0), desired_width(0.0), args(0)
+{
+}
+
+output::~output()
+{
+ a_delete args;
+}
+
+void output::set_desired_width_height(double wid, double ht)
+{
+ desired_width = wid;
+ desired_height = ht;
+}
+
+void output::set_args(const char *s)
+{
+ a_delete args;
+ if (s == 0 || *s == '\0')
+ args = 0;
+ else
+ args = strsave(s);
+}
+
+void output::command(const char *, const char *, int)
+{
+}
+
+void output::set_location(const char *, int)
+{
+}
+
+int output::supports_filled_polygons()
+{
+ return 0;
+}
+
+void output::begin_block(const position &, const position &)
+{
+}
+
+void output::end_block()
+{
+}
+
+double output::compute_scale(double sc, const position &ll, const position &ur)
+{
+ distance dim = ur - ll;
+ if (desired_width != 0.0 || desired_height != 0.0) {
+ sc = 0.0;
+ if (desired_width != 0.0) {
+ if (dim.x == 0.0)
+ error("width specified for picture with zero width");
+ else
+ sc = dim.x/desired_width;
+ }
+ if (desired_height != 0.0) {
+ if (dim.y == 0.0)
+ error("height specified for picture with zero height");
+ else {
+ double tem = dim.y/desired_height;
+ if (tem > sc)
+ sc = tem;
+ }
+ }
+ return sc == 0.0 ? 1.0 : sc;
+ }
+ else {
+ if (sc <= 0.0)
+ sc = 1.0;
+ distance sdim = dim/sc;
+ double max_width = 0.0;
+ lookup_variable("maxpswid", &max_width);
+ double max_height = 0.0;
+ lookup_variable("maxpsht", &max_height);
+ if ((max_width > 0.0 && sdim.x > max_width)
+ || (max_height > 0.0 && sdim.y > max_height)) {
+ double xscale = dim.x/max_width;
+ double yscale = dim.y/max_height;
+ return xscale > yscale ? xscale : yscale;
+ }
+ else
+ return sc;
+ }
+}
+
+position::position(const place &pl)
+{
+ if (pl.obj != 0) {
+ // Use two statements to work around bug in SGI C++.
+ object *tem = pl.obj;
+ *this = tem->origin();
+ }
+ else {
+ x = pl.x;
+ y = pl.y;
+ }
+}
+
+position::position() : x(0.0), y(0.0)
+{
+}
+
+position::position(double a, double b) : x(a), y(b)
+{
+}
+
+
+int operator==(const position &a, const position &b)
+{
+ return a.x == b.x && a.y == b.y;
+}
+
+int operator!=(const position &a, const position &b)
+{
+ return a.x != b.x || a.y != b.y;
+}
+
+position &position::operator+=(const position &a)
+{
+ x += a.x;
+ y += a.y;
+ return *this;
+}
+
+position &position::operator-=(const position &a)
+{
+ x -= a.x;
+ y -= a.y;
+ return *this;
+}
+
+position &position::operator*=(double a)
+{
+ x *= a;
+ y *= a;
+ return *this;
+}
+
+position &position::operator/=(double a)
+{
+ x /= a;
+ y /= a;
+ return *this;
+}
+
+position operator-(const position &a)
+{
+ return position(-a.x, -a.y);
+}
+
+position operator+(const position &a, const position &b)
+{
+ return position(a.x + b.x, a.y + b.y);
+}
+
+position operator-(const position &a, const position &b)
+{
+ return position(a.x - b.x, a.y - b.y);
+}
+
+position operator/(const position &a, double n)
+{
+ return position(a.x/n, a.y/n);
+}
+
+position operator*(const position &a, double n)
+{
+ return position(a.x*n, a.y*n);
+}
+
+// dot product
+
+double operator*(const position &a, const position &b)
+{
+ return a.x*b.x + a.y*b.y;
+}
+
+double hypot(const position &a)
+{
+ return hypot(a.x, a.y);
+}
+
+struct arrow_head_type {
+ double height;
+ double width;
+ int solid;
+};
+
+void draw_arrow(const position &pos, const distance &dir,
+ const arrow_head_type &aht, const line_type &lt)
+{
+ double hyp = hypot(dir);
+ if (hyp == 0.0) {
+ error("cannot draw arrow on object with zero length");
+ return;
+ }
+ position base = -dir;
+ base *= aht.height/hyp;
+ position n(dir.y, -dir.x);
+ n *= aht.width/(hyp*2.0);
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ if (aht.solid && out->supports_filled_polygons()) {
+ position v[3];
+ v[0] = pos;
+ v[1] = pos + base + n;
+ v[2] = pos + base - n;
+ // A value > 1 means fill with the current color.
+ out->polygon(v, 3, slt, 2.0);
+ }
+ else {
+ position v[2];
+ v[0] = pos;
+ v[1] = pos + base + n;
+ out->line(pos + base - n, v, 2, slt);
+ }
+}
+
+object::object() : prev(0), next(0)
+{
+}
+
+object::~object()
+{
+}
+
+void object::move_by(const position &)
+{
+}
+
+void object::print()
+{
+}
+
+void object::print_text()
+{
+}
+
+int object::blank()
+{
+ return 0;
+}
+
+struct bounding_box {
+ int blank;
+ position ll;
+ position ur;
+
+ bounding_box();
+ void encompass(const position &);
+};
+
+bounding_box::bounding_box()
+: blank(1)
+{
+}
+
+void bounding_box::encompass(const position &pos)
+{
+ if (blank) {
+ ll = pos;
+ ur = pos;
+ blank = 0;
+ }
+ else {
+ if (pos.x < ll.x)
+ ll.x = pos.x;
+ if (pos.y < ll.y)
+ ll.y = pos.y;
+ if (pos.x > ur.x)
+ ur.x = pos.x;
+ if (pos.y > ur.y)
+ ur.y = pos.y;
+ }
+}
+
+void object::update_bounding_box(bounding_box *)
+{
+}
+
+position object::origin()
+{
+ return position(0.0,0.0);
+}
+
+position object::north()
+{
+ return origin();
+}
+
+position object::south()
+{
+ return origin();
+}
+
+position object::east()
+{
+ return origin();
+}
+
+position object::west()
+{
+ return origin();
+}
+
+position object::north_east()
+{
+ return origin();
+}
+
+position object::north_west()
+{
+ return origin();
+}
+
+position object::south_east()
+{
+ return origin();
+}
+
+position object::south_west()
+{
+ return origin();
+}
+
+position object::start()
+{
+ return origin();
+}
+
+position object::end()
+{
+ return origin();
+}
+
+position object::center()
+{
+ return origin();
+}
+
+double object::width()
+{
+ return 0.0;
+}
+
+double object::radius()
+{
+ return 0.0;
+}
+
+double object::height()
+{
+ return 0.0;
+}
+
+place *object::find_label(const char *)
+{
+ return 0;
+}
+
+segment::segment(const position &a, int n, segment *p)
+: pos(a), is_absolute(n), next(p)
+{
+}
+
+text_item::text_item(char *t, const char *fn, int ln)
+: filename(fn), lineno(ln), text(t), next(0)
+{
+ adj.h = CENTER_ADJUST;
+ adj.v = NONE_ADJUST;
+}
+
+text_item::~text_item()
+{
+ a_delete text;
+}
+
+object_spec::object_spec(object_type t) : type(t)
+{
+ flags = 0;
+ tbl = 0;
+ segment_list = 0;
+ segment_width = segment_height = 0.0;
+ segment_is_absolute = 0;
+ text = 0;
+ with = 0;
+ dir = RIGHT_DIRECTION;
+}
+
+object_spec::~object_spec()
+{
+ delete tbl;
+ while (segment_list != 0) {
+ segment *tem = segment_list;
+ segment_list = segment_list->next;
+ delete tem;
+ }
+ object *p = oblist.head;
+ while (p != 0) {
+ object *tem = p;
+ p = p->next;
+ delete tem;
+ }
+ while (text != 0) {
+ text_item *tem = text;
+ text = text->next;
+ delete tem;
+ }
+ delete with;
+}
+
+class command_object : public object {
+ char *s;
+ const char *filename;
+ int lineno;
+public:
+ command_object(char *, const char *, int);
+ ~command_object();
+ object_type type() { return OTHER_OBJECT; }
+ void print();
+};
+
+command_object::command_object(char *p, const char *fn, int ln)
+: s(p), filename(fn), lineno(ln)
+{
+}
+
+command_object::~command_object()
+{
+ a_delete s;
+}
+
+void command_object::print()
+{
+ out->command(s, filename, lineno);
+}
+
+object *make_command_object(char *s, const char *fn, int ln)
+{
+ return new command_object(s, fn, ln);
+}
+
+class mark_object : public object {
+public:
+ mark_object();
+ object_type type();
+};
+
+object *make_mark_object()
+{
+ return new mark_object();
+}
+
+mark_object::mark_object()
+{
+}
+
+object_type mark_object::type()
+{
+ return MARK_OBJECT;
+}
+
+object_list::object_list() : head(0), tail(0)
+{
+}
+
+void object_list::append(object *obj)
+{
+ if (tail == 0) {
+ obj->next = obj->prev = 0;
+ head = tail = obj;
+ }
+ else {
+ obj->prev = tail;
+ obj->next = 0;
+ tail->next = obj;
+ tail = obj;
+ }
+}
+
+void object_list::wrap_up_block(object_list *ol)
+{
+ for (object *p = tail; p && p->type() != MARK_OBJECT; p = p->prev)
+ ;
+ assert(p != 0);
+ ol->head = p->next;
+ if (ol->head) {
+ ol->tail = tail;
+ ol->head->prev = 0;
+ }
+ else
+ ol->tail = 0;
+ tail = p->prev;
+ if (tail)
+ tail->next = 0;
+ else
+ head = 0;
+ delete p;
+}
+
+text_piece::text_piece()
+: text(0), filename(0), lineno(-1)
+{
+ adj.h = CENTER_ADJUST;
+ adj.v = NONE_ADJUST;
+}
+
+text_piece::~text_piece()
+{
+ a_delete text;
+}
+
+class graphic_object : public object {
+ int ntext;
+ text_piece *text;
+ int aligned;
+protected:
+ line_type lt;
+public:
+ graphic_object();
+ ~graphic_object();
+ object_type type() = 0;
+ void print_text();
+ void add_text(text_item *, int);
+ void set_dotted(double);
+ void set_dashed(double);
+ void set_thickness(double);
+ void set_invisible();
+ virtual void set_fill(double);
+};
+
+graphic_object::graphic_object() : ntext(0), text(0), aligned(0)
+{
+}
+
+void graphic_object::set_dotted(double wid)
+{
+ lt.type = line_type::dotted;
+ lt.dash_width = wid;
+}
+
+void graphic_object::set_dashed(double wid)
+{
+ lt.type = line_type::dashed;
+ lt.dash_width = wid;
+}
+
+void graphic_object::set_thickness(double th)
+{
+ lt.thickness = th;
+}
+
+void graphic_object::set_fill(double)
+{
+}
+
+void graphic_object::set_invisible()
+{
+ lt.type = line_type::invisible;
+}
+
+void graphic_object::add_text(text_item *t, int a)
+{
+ aligned = a;
+ int len = 0;
+ for (text_item *p = t; p; p = p->next)
+ len++;
+ if (len == 0)
+ text = 0;
+ else {
+ text = new text_piece[len];
+ for (p = t, len = 0; p; p = p->next, len++) {
+ text[len].text = p->text;
+ p->text = 0;
+ text[len].adj = p->adj;
+ text[len].filename = p->filename;
+ text[len].lineno = p->lineno;
+ }
+ }
+ ntext = len;
+}
+
+void graphic_object::print_text()
+{
+ double angle = 0.0;
+ if (aligned) {
+ position d(end() - start());
+ if (d.x != 0.0 || d.y != 0.0)
+ angle = atan2(d.y, d.x);
+ }
+ if (text != 0)
+ out->text(center(), text, ntext, angle);
+}
+
+graphic_object::~graphic_object()
+{
+ if (text)
+ ad_delete(ntext) text;
+}
+
+class rectangle_object : public graphic_object {
+protected:
+ position cent;
+ position dim;
+public:
+ rectangle_object(const position &);
+ double width() { return dim.x; }
+ double height() { return dim.y; }
+ position origin() { return cent; }
+ position center() { return cent; }
+ position north() { return position(cent.x, cent.y + dim.y/2.0); }
+ position south() { return position(cent.x, cent.y - dim.y/2.0); }
+ position east() { return position(cent.x + dim.x/2.0, cent.y); }
+ position west() { return position(cent.x - dim.x/2.0, cent.y); }
+ position north_east() { return position(cent.x + dim.x/2.0, cent.y + dim.y/2.0); }
+ position north_west() { return position(cent.x - dim.x/2.0, cent.y + dim.y/2.0); }
+ position south_east() { return position(cent.x + dim.x/2.0, cent.y - dim.y/2.0); }
+ position south_west() { return position(cent.x - dim.x/2.0, cent.y - dim.y/2.0); }
+ object_type type() = 0;
+ void update_bounding_box(bounding_box *);
+ void move_by(const position &);
+};
+
+rectangle_object::rectangle_object(const position &d)
+: dim(d)
+{
+}
+
+void rectangle_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(cent - dim/2.0);
+ p->encompass(cent + dim/2.0);
+}
+
+void rectangle_object::move_by(const position &a)
+{
+ cent += a;
+}
+
+class closed_object : public rectangle_object {
+public:
+ closed_object(const position &);
+ object_type type() = 0;
+ void set_fill(double);
+protected:
+ double fill; // < 0 if not filled
+};
+
+closed_object::closed_object(const position &pos)
+: rectangle_object(pos), fill(-1.0)
+{
+}
+
+void closed_object::set_fill(double f)
+{
+ assert(f >= 0.0);
+ fill = f;
+}
+
+
+class box_object : public closed_object {
+ double xrad;
+ double yrad;
+public:
+ box_object(const position &, double);
+ object_type type() { return BOX_OBJECT; }
+ void print();
+ position north_east();
+ position north_west();
+ position south_east();
+ position south_west();
+};
+
+box_object::box_object(const position &pos, double r)
+: closed_object(pos), xrad(dim.x > 0 ? r : -r), yrad(dim.y > 0 ? r : -r)
+{
+}
+
+const double CHOP_FACTOR = 1.0 - 1.0/M_SQRT2;
+
+position box_object::north_east()
+{
+ return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad,
+ cent.y + dim.y/2.0 - CHOP_FACTOR*yrad);
+}
+
+position box_object::north_west()
+{
+ return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad,
+ cent.y + dim.y/2.0 - CHOP_FACTOR*yrad);
+}
+
+position box_object::south_east()
+{
+ return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad,
+ cent.y - dim.y/2.0 + CHOP_FACTOR*yrad);
+}
+
+position box_object::south_west()
+{
+ return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad,
+ cent.y - dim.y/2.0 + CHOP_FACTOR*yrad);
+}
+
+void box_object::print()
+{
+ if (lt.type == line_type::invisible && fill < 0.0)
+ return;
+ if (xrad == 0.0) {
+ distance dim2 = dim/2.0;
+ position vec[4];
+ vec[0] = cent + position(dim2.x, -dim2.y);
+ vec[1] = cent + position(dim2.x, dim2.y);
+ vec[2] = cent + position(-dim2.x, dim2.y);
+ vec[3] = cent + position(-dim2.x, -dim2.y);
+ out->polygon(vec, 4, lt, fill);
+ }
+ else {
+ distance abs_dim(fabs(dim.x), fabs(dim.y));
+ out->rounded_box(cent, abs_dim, fabs(xrad), lt, fill);
+ }
+}
+
+graphic_object *object_spec::make_box(position *curpos, direction *dirp)
+{
+ static double last_box_height;
+ static double last_box_width;
+ static double last_box_radius;
+ static int have_last_box = 0;
+ if (!(flags & HAS_HEIGHT)) {
+ if ((flags & IS_SAME) && have_last_box)
+ height = last_box_height;
+ else
+ lookup_variable("boxht", &height);
+ }
+ if (!(flags & HAS_WIDTH)) {
+ if ((flags & IS_SAME) && have_last_box)
+ width = last_box_width;
+ else
+ lookup_variable("boxwid", &width);
+ }
+ if (!(flags & HAS_RADIUS)) {
+ if ((flags & IS_SAME) && have_last_box)
+ radius = last_box_radius;
+ else
+ lookup_variable("boxrad", &radius);
+ }
+ last_box_width = width;
+ last_box_height = height;
+ last_box_radius = radius;
+ have_last_box = 1;
+ radius = fabs(radius);
+ if (radius*2.0 > fabs(width))
+ radius = fabs(width/2.0);
+ if (radius*2.0 > fabs(height))
+ radius = fabs(height/2.0);
+ box_object *p = new box_object(position(width, height), radius);
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ p = 0;
+ }
+ return p;
+}
+
+// return non-zero for success
+
+int object_spec::position_rectangle(rectangle_object *p,
+ position *curpos, direction *dirp)
+{
+ position pos;
+ dir = *dirp; // ignore any direction in attribute list
+ position motion;
+ switch (dir) {
+ case UP_DIRECTION:
+ motion.y = p->height()/2.0;
+ break;
+ case DOWN_DIRECTION:
+ motion.y = -p->height()/2.0;
+ break;
+ case LEFT_DIRECTION:
+ motion.x = -p->width()/2.0;
+ break;
+ case RIGHT_DIRECTION:
+ motion.x = p->width()/2.0;
+ break;
+ default:
+ assert(0);
+ }
+ if (flags & HAS_AT) {
+ pos = at;
+ if (flags & HAS_WITH) {
+ place offset;
+ place here;
+ here.obj = p;
+ if (!with->follow(here, &offset))
+ return 0;
+ pos -= offset;
+ }
+ }
+ else {
+ pos = *curpos;
+ pos += motion;
+ }
+ p->move_by(pos);
+ pos += motion;
+ *curpos = pos;
+ return 1;
+}
+
+class block_object : public rectangle_object {
+ object_list oblist;
+ PTABLE(place) *tbl;
+public:
+ block_object(const position &, const object_list &ol, PTABLE(place) *t);
+ ~block_object();
+ place *find_label(const char *);
+ object_type type();
+ void move_by(const position &);
+ void print();
+};
+
+block_object::block_object(const position &d, const object_list &ol,
+ PTABLE(place) *t)
+: oblist(ol), tbl(t), rectangle_object(d)
+{
+}
+
+block_object::~block_object()
+{
+ delete tbl;
+ object *p = oblist.head;
+ while (p != 0) {
+ object *tem = p;
+ p = p->next;
+ delete tem;
+ }
+}
+
+void block_object::print()
+{
+ out->begin_block(south_west(), north_east());
+ print_object_list(oblist.head);
+ out->end_block();
+}
+
+static void adjust_objectless_places(PTABLE(place) *tbl, const position &a)
+{
+ // Adjust all the labels that aren't attached to objects.
+ PTABLE_ITERATOR(place) iter(tbl);
+ const char *key;
+ place *pl;
+ while (iter.next(&key, &pl))
+ if (key && csupper(key[0]) && pl->obj == 0) {
+ pl->x += a.x;
+ pl->y += a.y;
+ }
+}
+
+void block_object::move_by(const position &a)
+{
+ cent += a;
+ for (object *p = oblist.head; p; p = p->next)
+ p->move_by(a);
+ adjust_objectless_places(tbl, a);
+}
+
+
+place *block_object::find_label(const char *name)
+{
+ return tbl->lookup(name);
+}
+
+object_type block_object::type()
+{
+ return BLOCK_OBJECT;
+}
+
+graphic_object *object_spec::make_block(position *curpos, direction *dirp)
+{
+ bounding_box bb;
+ for (object *p = oblist.head; p; p = p->next)
+ p->update_bounding_box(&bb);
+ position dim;
+ if (!bb.blank) {
+ position m = -(bb.ll + bb.ur)/2.0;
+ for (object *p = oblist.head; p; p = p->next)
+ p->move_by(m);
+ adjust_objectless_places(tbl, m);
+ dim = bb.ur - bb.ll;
+ }
+ if (flags & HAS_WIDTH)
+ dim.x = width;
+ if (flags & HAS_HEIGHT)
+ dim.y = height;
+ block_object *block = new block_object(dim, oblist, tbl);
+ if (!position_rectangle(block, curpos, dirp)) {
+ delete block;
+ block = 0;
+ }
+ tbl = 0;
+ oblist.head = oblist.tail = 0;
+ return block;
+}
+
+class text_object : public rectangle_object {
+public:
+ text_object(const position &);
+ object_type type() { return TEXT_OBJECT; }
+};
+
+text_object::text_object(const position &d)
+: rectangle_object(d)
+{
+}
+
+graphic_object *object_spec::make_text(position *curpos, direction *dirp)
+{
+ if (!(flags & HAS_HEIGHT)) {
+ lookup_variable("textht", &height);
+ int nitems = 0;
+ for (text_item *t = text; t; t = t->next)
+ nitems++;
+ height *= nitems;
+ }
+ if (!(flags & HAS_WIDTH))
+ lookup_variable("textwid", &width);
+ text_object *p = new text_object(position(width, height));
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ p = 0;
+ }
+ return p;
+}
+
+
+class ellipse_object : public closed_object {
+public:
+ ellipse_object(const position &);
+ position north_east() { return position(cent.x + dim.x/(M_SQRT2*2.0),
+ cent.y + dim.y/(M_SQRT2*2.0)); }
+ position north_west() { return position(cent.x - dim.x/(M_SQRT2*2.0),
+ cent.y + dim.y/(M_SQRT2*2.0)); }
+ position south_east() { return position(cent.x + dim.x/(M_SQRT2*2.0),
+ cent.y - dim.y/(M_SQRT2*2.0)); }
+ position south_west() { return position(cent.x - dim.x/(M_SQRT2*2.0),
+ cent.y - dim.y/(M_SQRT2*2.0)); }
+ double radius() { return dim.x/2.0; }
+ object_type type() { return ELLIPSE_OBJECT; }
+ void print();
+};
+
+ellipse_object::ellipse_object(const position &d)
+: closed_object(d)
+{
+}
+
+void ellipse_object::print()
+{
+ if (lt.type == line_type::invisible && fill < 0.0)
+ return;
+ out->ellipse(cent, dim, lt, fill);
+}
+
+graphic_object *object_spec::make_ellipse(position *curpos, direction *dirp)
+{
+ static double last_ellipse_height;
+ static double last_ellipse_width;
+ static int have_last_ellipse = 0;
+ if (!(flags & HAS_HEIGHT)) {
+ if ((flags & IS_SAME) && have_last_ellipse)
+ height = last_ellipse_height;
+ else
+ lookup_variable("ellipseht", &height);
+ }
+ if (!(flags & HAS_WIDTH)) {
+ if ((flags & IS_SAME) && have_last_ellipse)
+ width = last_ellipse_width;
+ else
+ lookup_variable("ellipsewid", &width);
+ }
+ last_ellipse_width = width;
+ last_ellipse_height = height;
+ have_last_ellipse = 1;
+ ellipse_object *p = new ellipse_object(position(width, height));
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ return 0;
+ }
+ return p;
+}
+
+class circle_object : public ellipse_object {
+public:
+ circle_object(double);
+ object_type type() { return CIRCLE_OBJECT; }
+ void print();
+};
+
+circle_object::circle_object(double diam)
+: ellipse_object(position(diam, diam))
+{
+}
+
+void circle_object::print()
+{
+ if (lt.type == line_type::invisible && fill < 0.0)
+ return;
+ out->circle(cent, dim.x/2.0, lt, fill);
+}
+
+graphic_object *object_spec::make_circle(position *curpos, direction *dirp)
+{
+ static double last_circle_radius;
+ static int have_last_circle = 0;
+ if (!(flags & HAS_RADIUS)) {
+ if ((flags & IS_SAME) && have_last_circle)
+ radius = last_circle_radius;
+ else
+ lookup_variable("circlerad", &radius);
+ }
+ last_circle_radius = radius;
+ have_last_circle = 1;
+ circle_object *p = new circle_object(radius*2.0);
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ return 0;
+ }
+ return p;
+}
+
+class move_object : public graphic_object {
+ position strt;
+ position en;
+public:
+ move_object(const position &s, const position &e);
+ position origin() { return en; }
+ object_type type() { return MOVE_OBJECT; }
+ void update_bounding_box(bounding_box *);
+ void move_by(const position &);
+};
+
+move_object::move_object(const position &s, const position &e)
+: strt(s), en(e)
+{
+}
+
+void move_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ p->encompass(en);
+}
+
+void move_object::move_by(const position &a)
+{
+ strt += a;
+ en += a;
+}
+
+graphic_object *object_spec::make_move(position *curpos, direction *dirp)
+{
+ static position last_move;
+ static int have_last_move = 0;
+ *dirp = dir;
+ // No need to look at at since `at' attribute sets `from' attribute.
+ position startpos = (flags & HAS_FROM) ? from : *curpos;
+ if (!(flags & HAS_SEGMENT)) {
+ if ((flags && IS_SAME) && have_last_move)
+ segment_pos = last_move;
+ else {
+ switch (dir) {
+ case UP_DIRECTION:
+ segment_pos.y = segment_height;
+ break;
+ case DOWN_DIRECTION:
+ segment_pos.y = -segment_height;
+ break;
+ case LEFT_DIRECTION:
+ segment_pos.x = -segment_width;
+ break;
+ case RIGHT_DIRECTION:
+ segment_pos.x = segment_width;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ segment_list = new segment(segment_pos, segment_is_absolute, segment_list);
+ // Reverse the segment_list so that it's in forward order.
+ segment *old = segment_list;
+ segment_list = 0;
+ while (old != 0) {
+ segment *tem = old->next;
+ old->next = segment_list;
+ segment_list = old;
+ old = tem;
+ }
+ // Compute the end position.
+ position endpos = startpos;
+ for (segment *s = segment_list; s; s = s->next)
+ if (s->is_absolute)
+ endpos = s->pos;
+ else
+ endpos += s->pos;
+ have_last_move = 1;
+ last_move = endpos - startpos;
+ move_object *p = new move_object(startpos, endpos);
+ *curpos = endpos;
+ return p;
+}
+
+class linear_object : public graphic_object {
+protected:
+ char arrow_at_start;
+ char arrow_at_end;
+ arrow_head_type aht;
+ position strt;
+ position en;
+public:
+ linear_object(const position &s, const position &e);
+ position start() { return strt; }
+ position end() { return en; }
+ void move_by(const position &);
+ void update_bounding_box(bounding_box *) = 0;
+ object_type type() = 0;
+ void add_arrows(int at_start, int at_end, const arrow_head_type &);
+};
+
+class line_object : public linear_object {
+protected:
+ position *v;
+ int n;
+public:
+ line_object(const position &s, const position &e, position *, int);
+ ~line_object();
+ position origin() { return strt; }
+ position center() { return (strt + en)/2.0; }
+ position north() { return (en.y - strt.y) > 0 ? en : strt; }
+ position south() { return (en.y - strt.y) < 0 ? en : strt; }
+ position east() { return (en.x - strt.x) > 0 ? en : strt; }
+ position west() { return (en.x - strt.x) < 0 ? en : strt; }
+ object_type type() { return LINE_OBJECT; }
+ void update_bounding_box(bounding_box *);
+ void print();
+ void move_by(const position &);
+};
+
+class arrow_object : public line_object {
+public:
+ arrow_object(const position &, const position &, position *, int);
+ object_type type() { return ARROW_OBJECT; }
+};
+
+class spline_object : public line_object {
+public:
+ spline_object(const position &, const position &, position *, int);
+ object_type type() { return SPLINE_OBJECT; }
+ void print();
+ void update_bounding_box(bounding_box *);
+};
+
+linear_object::linear_object(const position &s, const position &e)
+: strt(s), en(e), arrow_at_start(0), arrow_at_end(0)
+{
+}
+
+void linear_object::move_by(const position &a)
+{
+ strt += a;
+ en += a;
+}
+
+void linear_object::add_arrows(int at_start, int at_end,
+ const arrow_head_type &a)
+{
+ arrow_at_start = at_start;
+ arrow_at_end = at_end;
+ aht = a;
+}
+
+line_object::line_object(const position &s, const position &e,
+ position *p, int i)
+: v(p), n(i), linear_object(s, e)
+{
+}
+
+void line_object::print()
+{
+ if (lt.type == line_type::invisible)
+ return;
+ out->line(strt, v, n, lt);
+ if (arrow_at_start)
+ draw_arrow(strt, strt-v[0], aht, lt);
+ if (arrow_at_end)
+ draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+}
+
+void line_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ for (int i = 0; i < n; i++)
+ p->encompass(v[i]);
+}
+
+void line_object::move_by(const position &pos)
+{
+ linear_object::move_by(pos);
+ for (int i = 0; i < n; i++)
+ v[i] += pos;
+}
+
+void spline_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ p->encompass(en);
+ /*
+
+ If
+
+ p1 = q1/2 + q2/2
+ p2 = q1/6 + q2*5/6
+ p3 = q2*5/6 + q3/6
+ p4 = q2/2 + q3/2
+ [ the points for the Bezier cubic ]
+
+ and
+
+ t = .5
+
+ then
+
+ (1-t)^3*p1 + 3*t*(t - 1)^2*p2 + 3*t^2*(1-t)*p3 + t^3*p4
+ [ the equation for the Bezier cubic ]
+
+ = .125*q1 + .75*q2 + .125*q3
+
+ */
+ for (int i = 1; i < n; i++)
+ p->encompass((i == 1 ? strt : v[i-2])*.125 + v[i-1]*.75 + v[i]*.125);
+}
+
+arrow_object::arrow_object(const position &s, const position &e,
+ position *p, int i)
+: line_object(s, e, p, i)
+{
+}
+
+spline_object::spline_object(const position &s, const position &e,
+ position *p, int i)
+: line_object(s, e, p, i)
+{
+}
+
+void spline_object::print()
+{
+ if (lt.type == line_type::invisible)
+ return;
+ out->spline(strt, v, n, lt);
+ if (arrow_at_start)
+ draw_arrow(strt, strt-v[0], aht, lt);
+ if (arrow_at_end)
+ draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+}
+
+line_object::~line_object()
+{
+ a_delete v;
+}
+
+linear_object *object_spec::make_line(position *curpos, direction *dirp)
+{
+ static position last_line;
+ static int have_last_line = 0;
+ *dirp = dir;
+ // No need to look at at since `at' attribute sets `from' attribute.
+ position startpos = (flags & HAS_FROM) ? from : *curpos;
+ if (!(flags & HAS_SEGMENT)) {
+ if ((flags & IS_SAME) && (type == LINE_OBJECT || type == ARROW_OBJECT)
+ && have_last_line)
+ segment_pos = last_line;
+ else
+ switch (dir) {
+ case UP_DIRECTION:
+ segment_pos.y = segment_height;
+ break;
+ case DOWN_DIRECTION:
+ segment_pos.y = -segment_height;
+ break;
+ case LEFT_DIRECTION:
+ segment_pos.x = -segment_width;
+ break;
+ case RIGHT_DIRECTION:
+ segment_pos.x = segment_width;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ segment_list = new segment(segment_pos, segment_is_absolute, segment_list);
+ // reverse the segment_list so that it's in forward order
+ segment *old = segment_list;
+ segment_list = 0;
+ while (old != 0) {
+ segment *tem = old->next;
+ old->next = segment_list;
+ segment_list = old;
+ old = tem;
+ }
+ // Absolutise all movements
+ position endpos = startpos;
+ int nsegments = 0;
+ for (segment *s = segment_list; s; s = s->next, nsegments++)
+ if (s->is_absolute)
+ endpos = s->pos;
+ else {
+ endpos += s->pos;
+ s->pos = endpos;
+ s->is_absolute = 1; // to avoid confusion
+ }
+ // handle chop
+ line_object *p = 0;
+ position *v = new position[nsegments];
+ int i = 0;
+ for (s = segment_list; s; s = s->next, i++)
+ v[i] = s->pos;
+ if (flags & IS_DEFAULT_CHOPPED) {
+ lookup_variable("circlerad", &start_chop);
+ end_chop = start_chop;
+ flags |= IS_CHOPPED;
+ }
+ if (flags & IS_CHOPPED) {
+ position start_chop_vec, end_chop_vec;
+ if (start_chop != 0.0) {
+ start_chop_vec = v[0] - startpos;
+ start_chop_vec *= start_chop / hypot(start_chop_vec);
+ }
+ if (end_chop != 0.0) {
+ end_chop_vec = (v[nsegments - 1]
+ - (nsegments > 1 ? v[nsegments - 2] : startpos));
+ end_chop_vec *= end_chop / hypot(end_chop_vec);
+ }
+ startpos += start_chop_vec;
+ v[nsegments - 1] -= end_chop_vec;
+ endpos -= end_chop_vec;
+ }
+ switch (type) {
+ case SPLINE_OBJECT:
+ p = new spline_object(startpos, endpos, v, nsegments);
+ break;
+ case ARROW_OBJECT:
+ p = new arrow_object(startpos, endpos, v, nsegments);
+ break;
+ case LINE_OBJECT:
+ p = new line_object(startpos, endpos, v, nsegments);
+ break;
+ default:
+ assert(0);
+ }
+ have_last_line = 1;
+ last_line = endpos - startpos;
+ *curpos = endpos;
+ return p;
+}
+
+class arc_object : public linear_object {
+ int clockwise;
+ position cent;
+ double rad;
+public:
+ arc_object(int, const position &, const position &, const position &);
+ position origin() { return cent; }
+ position center() { return cent; }
+ double radius() { return rad; }
+ position north();
+ position south();
+ position east();
+ position west();
+ position north_east();
+ position north_west();
+ position south_east();
+ position south_west();
+ void update_bounding_box(bounding_box *);
+ object_type type() { return ARC_OBJECT; }
+ void print();
+ void move_by(const position &pos);
+};
+
+arc_object::arc_object(int cw, const position &s, const position &e,
+ const position &c)
+: linear_object(s, e), clockwise(cw), cent(c)
+{
+ rad = hypot(c - s);
+}
+
+void arc_object::move_by(const position &pos)
+{
+ linear_object::move_by(pos);
+ cent += pos;
+}
+
+// we get arc corners from the corresponding circle
+
+position arc_object::north()
+{
+ position result(cent);
+ result.y += rad;
+ return result;
+}
+
+position arc_object::south()
+{
+ position result(cent);
+ result.y -= rad;
+ return result;
+}
+
+position arc_object::east()
+{
+ position result(cent);
+ result.x += rad;
+ return result;
+}
+
+position arc_object::west()
+{
+ position result(cent);
+ result.x -= rad;
+ return result;
+}
+
+position arc_object::north_east()
+{
+ position result(cent);
+ result.x += rad/M_SQRT2;
+ result.y += rad/M_SQRT2;
+ return result;
+}
+
+position arc_object::north_west()
+{
+ position result(cent);
+ result.x -= rad/M_SQRT2;
+ result.y += rad/M_SQRT2;
+ return result;
+}
+
+position arc_object::south_east()
+{
+ position result(cent);
+ result.x += rad/M_SQRT2;
+ result.y -= rad/M_SQRT2;
+ return result;
+}
+
+position arc_object::south_west()
+{
+ position result(cent);
+ result.x -= rad/M_SQRT2;
+ result.y -= rad/M_SQRT2;
+ return result;
+}
+
+
+void arc_object::print()
+{
+ if (lt.type == line_type::invisible)
+ return;
+ if (clockwise)
+ out->arc(en, cent, strt, lt);
+ else
+ out->arc(strt, cent, en, lt);
+ if (arrow_at_start) {
+ position c = cent - strt;
+ draw_arrow(strt,
+ (clockwise ? position(c.y, -c.x) : position(-c.y, c.x)),
+ aht, lt);
+ }
+ if (arrow_at_end) {
+ position e = en - cent;
+ draw_arrow(en,
+ (clockwise ? position(e.y, -e.x) : position(-e.y, e.x)),
+ aht, lt);
+ }
+}
+
+inline double max(double a, double b)
+{
+ return a > b ? a : b;
+}
+
+void arc_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ p->encompass(en);
+ position start_offset = strt - cent;
+ if (start_offset.x == 0.0 && start_offset.y == 0.0)
+ return;
+ position end_offset = en - cent;
+ if (end_offset.x == 0.0 && end_offset.y == 0.0)
+ return;
+ double start_quad = atan2(start_offset.y, start_offset.x)/(M_PI/2.0);
+ double end_quad = atan2(end_offset.y, end_offset.x)/(M_PI/2.0);
+ if (clockwise) {
+ double temp = start_quad;
+ start_quad = end_quad;
+ end_quad = temp;
+ }
+ if (start_quad < 0.0)
+ start_quad += 4.0;
+ while (end_quad <= start_quad)
+ end_quad += 4.0;
+ double radius = max(hypot(start_offset), hypot(end_offset));
+ for (int q = int(start_quad) + 1; q < end_quad; q++) {
+ position offset;
+ switch (q % 4) {
+ case 0:
+ offset.x = radius;
+ break;
+ case 1:
+ offset.y = radius;
+ break;
+ case 2:
+ offset.x = -radius;
+ break;
+ case 3:
+ offset.y = -radius;
+ break;
+ }
+ p->encompass(cent + offset);
+ }
+}
+
+// We ignore the with attribute. The at attribute always refers to the center.
+
+linear_object *object_spec::make_arc(position *curpos, direction *dirp)
+{
+ *dirp = dir;
+ int cw = (flags & IS_CLOCKWISE) != 0;
+ // compute the start
+ position startpos;
+ if (flags & HAS_FROM)
+ startpos = from;
+ else
+ startpos = *curpos;
+ if (!(flags & HAS_RADIUS))
+ lookup_variable("arcrad", &radius);
+ // compute the end
+ position endpos;
+ if (flags & HAS_TO)
+ endpos = to;
+ else {
+ position m(radius, radius);
+ // Adjust the signs.
+ if (cw) {
+ if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION)
+ m.x = -m.x;
+ if (dir == DOWN_DIRECTION || dir == RIGHT_DIRECTION)
+ m.y = -m.y;
+ *dirp = direction((dir + 3) % 4);
+ }
+ else {
+ if (dir == UP_DIRECTION || dir == LEFT_DIRECTION)
+ m.x = -m.x;
+ if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION)
+ m.y = -m.y;
+ *dirp = direction((dir + 1) % 4);
+ }
+ endpos = startpos + m;
+ }
+ // compute the center
+ position centerpos;
+ if (flags & HAS_AT)
+ centerpos = at;
+ else if (startpos == endpos)
+ centerpos = startpos;
+ else {
+ position h = (endpos - startpos)/2.0;
+ double d = hypot(h);
+ if (radius <= 0)
+ radius = .25;
+ // make the radius big enough
+ while (radius < d)
+ radius *= 2.0;
+ double alpha = acos(d/radius);
+ double theta = atan2(h.y, h.x);
+ if (cw)
+ theta -= alpha;
+ else
+ theta += alpha;
+ centerpos = position(cos(theta), sin(theta))*radius + startpos;
+ }
+ arc_object *p = new arc_object(cw, startpos, endpos, centerpos);
+ *curpos = endpos;
+ return p;
+}
+
+graphic_object *object_spec::make_linear(position *curpos, direction *dirp)
+{
+ linear_object *obj;
+ if (type == ARC_OBJECT)
+ obj = make_arc(curpos, dirp);
+ else
+ obj = make_line(curpos, dirp);
+ if (type == ARROW_OBJECT
+ && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD)) == 0)
+ flags |= HAS_RIGHT_ARROW_HEAD;
+ if (obj && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD))) {
+ arrow_head_type a;
+ int at_start = (flags & HAS_LEFT_ARROW_HEAD) != 0;
+ int at_end = (flags & HAS_RIGHT_ARROW_HEAD) != 0;
+ if (flags & HAS_HEIGHT)
+ a.height = height;
+ else
+ lookup_variable("arrowht", &a.height);
+ if (flags & HAS_WIDTH)
+ a.width = width;
+ else
+ lookup_variable("arrowwid", &a.width);
+ double solid;
+ lookup_variable("arrowhead", &solid);
+ a.solid = solid != 0.0;
+ obj->add_arrows(at_start, at_end, a);
+ }
+ return obj;
+}
+
+object *object_spec::make_object(position *curpos, direction *dirp)
+{
+ graphic_object *obj = 0;
+ switch (type) {
+ case BLOCK_OBJECT:
+ obj = make_block(curpos, dirp);
+ break;
+ case BOX_OBJECT:
+ obj = make_box(curpos, dirp);
+ break;
+ case TEXT_OBJECT:
+ obj = make_text(curpos, dirp);
+ break;
+ case ELLIPSE_OBJECT:
+ obj = make_ellipse(curpos, dirp);
+ break;
+ case CIRCLE_OBJECT:
+ obj = make_circle(curpos, dirp);
+ break;
+ case MOVE_OBJECT:
+ obj = make_move(curpos, dirp);
+ break;
+ case ARC_OBJECT:
+ case LINE_OBJECT:
+ case SPLINE_OBJECT:
+ case ARROW_OBJECT:
+ obj = make_linear(curpos, dirp);
+ break;
+ case MARK_OBJECT:
+ case OTHER_OBJECT:
+ default:
+ assert(0);
+ break;
+ }
+ if (obj) {
+ if (flags & IS_INVISIBLE)
+ obj->set_invisible();
+ if (text != 0)
+ obj->add_text(text, (flags & IS_ALIGNED) != 0);
+ if (flags & IS_DOTTED)
+ obj->set_dotted(dash_width);
+ else if (flags & IS_DASHED)
+ obj->set_dashed(dash_width);
+ double th;
+ if (flags & HAS_THICKNESS)
+ th = thickness;
+ else
+ lookup_variable("linethick", &th);
+ obj->set_thickness(th);
+ if (flags & (IS_DEFAULT_FILLED|IS_FILLED)) {
+ if (flags & IS_DEFAULT_FILLED)
+ lookup_variable("fillval", &fill);
+ if (fill < 0.0)
+ error("bad fill value %1", fill);
+ else
+ obj->set_fill(fill);
+ }
+ }
+ return obj;
+}
+
+struct string_list {
+ string_list *next;
+ char *str;
+ string_list(char *);
+ ~string_list();
+};
+
+string_list::string_list(char *s)
+: next(0), str(s)
+{
+}
+
+string_list::~string_list()
+{
+ a_delete str;
+}
+
+/* A path is used to hold the argument to the with attribute. For example,
+`.nw' or `.A.s' or `.A'. The major operation on a path is to take a
+place and follow the path through the place to place within the place.
+Note that `.A.B.C.sw' will work. */
+
+path::path(corner c)
+: label_list(0), crn(c)
+{
+}
+
+path::path(char *l, corner c)
+: crn(c)
+{
+ label_list = new string_list(l);
+}
+
+path::~path()
+{
+ while (label_list) {
+ string_list *tem = label_list;
+ label_list = label_list->next;
+ delete tem;
+ }
+}
+
+void path::append(corner c)
+{
+ assert(crn == 0);
+ crn = c;
+}
+
+void path::append(char *s)
+{
+ for (string_list **p = &label_list; *p; p = &(*p)->next)
+ ;
+ *p = new string_list(s);
+}
+
+// return non-zero for success
+
+int path::follow(const place &pl, place *result) const
+{
+ const place *p = &pl;
+ for (string_list *lb = label_list; lb; lb = lb->next)
+ if (p->obj == 0 || (p = p->obj->find_label(lb->str)) == 0) {
+ lex_error("object does not contain a place `%1'", lb->str);
+ return 0;
+ }
+ if (crn == 0 || p->obj == 0)
+ *result = *p;
+ else {
+ position pos = ((p->obj)->*(crn))();
+ result->x = pos.x;
+ result->y = pos.y;
+ result->obj = 0;
+ }
+ return 1;
+}
+
+void print_object_list(object *p)
+{
+ for (; p; p = p->next) {
+ p->print();
+ p->print_text();
+ }
+}
+
+void print_picture(object *obj)
+{
+ bounding_box bb;
+ for (object *p = obj; p; p = p->next)
+ p->update_bounding_box(&bb);
+ double scale;
+ lookup_variable("scale", &scale);
+ out->start_picture(scale, bb.ll, bb.ur);
+ print_object_list(obj);
+ out->finish_picture();
+}
+
diff --git a/gnu/usr.bin/groff/pic/object.h b/gnu/usr.bin/groff/pic/object.h
new file mode 100644
index 000000000000..39240b634f27
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/object.h
@@ -0,0 +1,215 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct place;
+
+enum object_type {
+ OTHER_OBJECT,
+ BOX_OBJECT,
+ CIRCLE_OBJECT,
+ ELLIPSE_OBJECT,
+ ARC_OBJECT,
+ SPLINE_OBJECT,
+ LINE_OBJECT,
+ ARROW_OBJECT,
+ MOVE_OBJECT,
+ TEXT_OBJECT,
+ BLOCK_OBJECT,
+ MARK_OBJECT
+ };
+
+struct bounding_box;
+
+struct object {
+ object *prev;
+ object *next;
+ object();
+ virtual ~object();
+ virtual position origin();
+ virtual double width();
+ virtual double radius();
+ virtual double height();
+ virtual position north();
+ virtual position south();
+ virtual position east();
+ virtual position west();
+ virtual position north_east();
+ virtual position north_west();
+ virtual position south_east();
+ virtual position south_west();
+ virtual position start();
+ virtual position end();
+ virtual position center();
+ virtual place *find_label(const char *);
+ virtual void move_by(const position &);
+ virtual int blank();
+ virtual void update_bounding_box(bounding_box *);
+ virtual object_type type() = 0;
+ virtual void print();
+ virtual void print_text();
+};
+
+typedef position (object::*corner)();
+
+struct place {
+ object *obj;
+ double x, y;
+};
+
+struct string_list;
+
+class path {
+ corner crn;
+ string_list *label_list;
+public:
+ path(corner = 0);
+ path(char *, corner = 0);
+ ~path();
+ void append(corner);
+ void append(char *);
+ int follow(const place &, place *) const;
+};
+
+struct object_list {
+ object *head;
+ object *tail;
+ object_list();
+ void append(object *);
+ void wrap_up_block(object_list *);
+};
+
+declare_ptable(place)
+
+// these go counterclockwise
+enum direction {
+ RIGHT_DIRECTION,
+ UP_DIRECTION,
+ LEFT_DIRECTION,
+ DOWN_DIRECTION
+ };
+
+struct graphics_state {
+ double x, y;
+ direction dir;
+};
+
+struct saved_state : graphics_state {
+ saved_state *prev;
+ PTABLE(place) *tbl;
+};
+
+
+struct text_item {
+ text_item *next;
+ char *text;
+ adjustment adj;
+ const char *filename;
+ int lineno;
+
+ text_item(char *, const char *, int);
+ ~text_item();
+};
+
+const unsigned long IS_DOTTED = 01;
+const unsigned long IS_DASHED = 02;
+const unsigned long IS_CLOCKWISE = 04;
+const unsigned long IS_INVISIBLE = 020;
+const unsigned long HAS_LEFT_ARROW_HEAD = 040;
+const unsigned long HAS_RIGHT_ARROW_HEAD = 0100;
+const unsigned long HAS_SEGMENT = 0200;
+const unsigned long IS_SAME = 0400;
+const unsigned long HAS_FROM = 01000;
+const unsigned long HAS_AT = 02000;
+const unsigned long HAS_WITH = 04000;
+const unsigned long HAS_HEIGHT = 010000;
+const unsigned long HAS_WIDTH = 020000;
+const unsigned long HAS_RADIUS = 040000;
+const unsigned long HAS_TO = 0100000;
+const unsigned long IS_CHOPPED = 0200000;
+const unsigned long IS_DEFAULT_CHOPPED = 0400000;
+const unsigned long HAS_THICKNESS = 01000000;
+const unsigned long IS_FILLED = 02000000;
+const unsigned long IS_DEFAULT_FILLED = 04000000;
+const unsigned long IS_ALIGNED = 010000000;
+
+struct segment {
+ int is_absolute;
+ position pos;
+ segment *next;
+ segment(const position &, int, segment *);
+};
+
+struct rectangle_object;
+struct graphic_object;
+struct linear_object;
+
+struct object_spec {
+ unsigned long flags;
+ object_type type;
+ object_list oblist;
+ PTABLE(place) *tbl;
+ double dash_width;
+ position from;
+ position to;
+ position at;
+ position by;
+ path *with;
+ text_item *text;
+ double height;
+ double radius;
+ double width;
+ double segment_width;
+ double segment_height;
+ double start_chop;
+ double end_chop;
+ double thickness;
+ double fill;
+ direction dir;
+ segment *segment_list;
+ position segment_pos;
+ int segment_is_absolute;
+
+ object_spec(object_type);
+ ~object_spec();
+ object *make_object(position *, direction *);
+ graphic_object *make_box(position *, direction *);
+ graphic_object *make_block(position *, direction *);
+ graphic_object *make_text(position *, direction *);
+ graphic_object *make_ellipse(position *, direction *);
+ graphic_object *make_circle(position *, direction *);
+ linear_object *make_line(position *, direction *);
+ linear_object *make_arc(position *, direction *);
+ graphic_object *make_linear(position *, direction *);
+ graphic_object *make_move(position *, direction *);
+ int position_rectangle(rectangle_object *p, position *curpos,
+ direction *dirp);
+};
+
+
+object *make_object(object_spec *, position *, direction *);
+
+object *make_mark_object();
+object *make_command_object(char *, const char *, int);
+
+int lookup_variable(const char *name, double *val);
+void define_variable(const char *name, double val);
+
+void print_picture(object *);
+
diff --git a/gnu/usr.bin/groff/pic/output.h b/gnu/usr.bin/groff/pic/output.h
new file mode 100644
index 000000000000..ddcc4b5bf7b6
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/output.h
@@ -0,0 +1,79 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct line_type {
+ enum { invisible, solid, dotted, dashed } type;
+ double dash_width;
+ double thickness; // the thickness is in points
+
+ line_type();
+};
+
+
+class output {
+protected:
+ char *args;
+ double desired_height; // zero if no height specified
+ double desired_width; // zero if no depth specified
+ double compute_scale(double, const position &, const position &);
+public:
+ output();
+ virtual ~output();
+ void set_desired_width_height(double wid, double ht);
+ void set_args(const char *);
+ virtual void start_picture(double sc, const position &ll, const position &ur) = 0;
+ virtual void finish_picture() = 0;
+ virtual void circle(const position &, double rad,
+ const line_type &, double) = 0;
+ virtual void text(const position &, text_piece *, int, double) = 0;
+ virtual void line(const position &, const position *, int n,
+ const line_type &) = 0;
+ virtual void polygon(const position *, int n,
+ const line_type &, double) = 0;
+ virtual void spline(const position &, const position *, int n,
+ const line_type &) = 0;
+ virtual void arc(const position &, const position &, const position &,
+ const line_type &) = 0;
+ virtual void ellipse(const position &, const distance &,
+ const line_type &, double) = 0;
+ virtual void rounded_box(const position &, const distance &, double,
+ const line_type &, double) = 0;
+ virtual void command(const char *, const char *, int);
+ virtual void set_location(const char *, int);
+ virtual int supports_filled_polygons();
+ virtual void begin_block(const position &ll, const position &ur);
+ virtual void end_block();
+};
+
+extern output *out;
+
+/* #define FIG_SUPPORT 1 */
+#define TEX_SUPPORT 1
+
+output *make_troff_output();
+
+#ifdef TEX_SUPPORT
+output *make_tex_output();
+output *make_tpic_output();
+#endif /* TEX_SUPPORT */
+
+#ifdef FIG_SUPPORT
+output *make_fig_output();
+#endif /* FIG_SUPPORT */
diff --git a/gnu/usr.bin/groff/pic/pic.1 b/gnu/usr.bin/groff/pic/pic.1
new file mode 100644
index 000000000000..3b0345b95363
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/pic.1
@@ -0,0 +1,730 @@
+.\" -*- nroff -*-
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.ie \n(.g .ds ic \/
+.el .ds ic \^
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH PIC 1 "9 August 1992" "Groff Version 1.08"
+.SH NAME
+pic \- compile pictures for troff or TeX
+.SH SYNOPSIS
+.B pic
+[
+.B \-nvC
+]
+[
+.I filename
+\&.\|.\|.
+]
+.br
+.B pic
+.B \-t
+[
+.B \-cvzC
+]
+[
+.I filename
+\&.\|.\|.
+]
+.SH DESCRIPTION
+.LP
+This manual page descibes the GNU version of
+.BR pic ,
+which is part of the groff document formatting system.
+.B pic
+compiles descriptions of pictures embedded within
+.B troff
+or \*(tx input files into commands that are understood by \*(tx or
+.BR troff .
+Each picture starts with a line beginning with
+.B .PS
+and ends with a line beginning with
+.BR .PE .
+Anything outside of
+.B .PS
+and
+.B .PE
+is passed through without change.
+.LP
+It is the user's responsibility to provide appropriate definitions of the
+.B PS
+and
+.B PE
+macros.
+When the macro package being used does not supply such definitions
+(for example, old versions of \-ms),
+appropriate definitions can be obtained with
+.BR \-mpic :
+these will center each picture.
+.SH OPTIONS
+.LP
+Options that do not take arguments may be grouped behind a single
+.BR \- .
+The special option
+.B \-\^\-
+can be used to mark the end of the options.
+A filename of
+.B \-
+refers to the standard input.
+.TP
+.B \-C
+Recognize
+.B .PS
+and
+.B .PE
+even when followed by a character other than space or newline.
+.TP
+.B \-n
+Don't use the groff extensions to the troff drawing commands.
+You should use this if you are using a postprocessor that doesn't support
+these extensions.
+The extensions are described in
+.BR groff_out (5).
+The
+.B \-n
+option also causes pic
+not to use zero-length lines to draw dots in troff mode.
+.TP
+.B \-t
+\*(tx mode.
+.TP
+.B \-c
+Be more compatible with
+.BR tpic .
+Implies
+.BR \-t .
+Lines beginning with
+.B \e
+are not passed through transparently.
+Lines beginning with
+.B .
+are passed through with the initial
+.B .
+changed to
+.BR \e .
+A line beginning with
+.B .ps
+is given special treatment:
+it takes an optional integer argument specifying
+the line thickness (pen size) in milliinches;
+a missing argument restores the previous line thickness;
+the default line thickness is 8 milliinches.
+The line thickness thus specified takes effect only
+when a non-negative line thickness has not been
+specified by use of the
+.B thickness
+attribute or by setting the
+.B linethick
+variable.
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-z
+In \*(tx mode draw dots using zero-length lines.
+.LP
+The following options supported by other versions of
+.B pic
+are ignored:
+.TP
+.B \-D
+Draw all lines using the \eD escape sequence.
+.B pic
+always does this.
+.TP
+.BI \-T \ dev
+Generate output for the
+.B troff
+device
+.IR dev .
+This is unnecessary because the
+.B troff
+output generated by
+.B pic
+is device-independent.
+.SH USAGE
+This section describes only the differences between GNU pic and the original
+version of pic.
+Many of these differences also apply to newer versions of Unix pic.
+.SS \*(tx mode
+.LP
+\*(tx mode is enabled by the
+.B \-t
+option.
+In \*(tx mode, pic will define a vbox called
+.B \egraph
+for each picture.
+You must yourself print that vbox using, for example, the command
+.RS
+.LP
+.B
+\ecenterline{\ebox\egraph}
+.RE
+.LP
+Actually, since the vbox has a height of zero this will produce
+slightly more vertical space above the picture than below it;
+.RS
+.LP
+.B
+\ecenterline{\eraise 1em\ebox\egraph}
+.RE
+.LP
+would avoid this.
+.LP
+You must use a \*(tx driver that supports the
+.B tpic
+specials, version 2.
+.LP
+Lines beginning with
+.B \e
+are passed through transparently; a
+.B %
+is added to the end of the line to avoid unwanted spaces.
+You can safely use this feature to change fonts or to
+change the value of
+.BR \ebaselineskip .
+Anything else may well produce undesirable results; use at your own risk.
+Lines beginning with a period are not given any special treatment.
+.SS Commands
+.TP
+\fBfor\fR \fIvariable\fR \fB=\fR \fIexpr1\fR \fBto\fR \fIexpr2\fR \
+[\fBby\fR [\fB*\fR]\fIexpr3\fR] \fBdo\fR \fIX\fR \fIbody\fR \fIX\fR
+Set
+.I variable
+to
+.IR expr1 .
+While the value of
+.I variable
+is less than or equal to
+.IR expr2 ,
+do
+.I body
+and increment
+.I variable
+by
+.IR expr3 ;
+if
+.B by
+is not given, increment
+.I variable
+by 1.
+If
+.I expr3
+is prefixed by
+.B *
+then
+.I variable
+will instead be multiplied by
+.IR expr3 .
+.I X
+can be any character not occurring in
+.IR body .
+.TP
+\fBif\fR \fIexpr\fR \fBthen\fR \fIX\fR \fIif-true\fR \fIX\fR \
+[\fBelse\fR \fIY\fR \fIif-false\fR \fIY\fR]
+Evaluate
+.IR expr ;
+if it is non-zero then do
+.IR if-true ,
+otherwise do
+.IR if-false .
+.I X
+can be any character not occurring in
+.IR if-true .
+.I Y
+can be any character not occurring in
+.IR if-false .
+.TP
+\fBprint\fR \fIarg\fR\|.\|.\|.
+Concatenate the arguments and print as a line on stderr.
+Each
+.I arg
+must be an expression, a position, or text.
+This is useful for debugging.
+.TP
+\fBcommand\fR \fIarg\fR\|.\|.\|.
+Concatenate the arguments
+and pass them through as a line to troff or\*(tx.
+Each
+.I arg
+must be an expression, a position, or text.
+This has a similar effect to a line beginning with
+.B .
+or
+.BR \e ,
+but allows the values of variables to be passed through.
+.TP
+\fBsh\fR \fIX\fR \fIcommand\fR \fIX\fR
+Pass
+.I command
+to a shell.
+.I X
+can be any character not occurring in
+.IR command .
+.TP
+\fBcopy\fR \fB"\fIfilename\fB"\fR
+Include
+.I filename
+at this point in the file.
+.TP
+\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fIX\fR \fIbody\fR \fIX\fR \
+[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR]
+.ns
+.TP
+\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fImacro\fR \
+[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR]
+This construct does
+.I body
+once for each line of
+.IR filename ;
+the line is split into blank-delimited words,
+and occurrences of
+.BI $ i
+in
+.IR body ,
+for
+.I i
+between 1 and 9,
+are replaced by the
+.IR i -th
+word of the line.
+If
+.I filename
+is not given, lines are taken from the current input up to
+.BR .PE .
+If an
+.B until
+clause is specified,
+lines will be read only until a line the first word of which is
+.IR word ;
+that line will then be discarded.
+.I X
+can be any character not occurring in
+.IR body .
+For example,
+.RS
+.IP
+.ft B
+.nf
+\&.PS
+copy thru % circle at ($1,$2) % until "END"
+1 2
+3 4
+5 6
+END
+box
+\&.PE
+.ft
+.fi
+.RE
+.IP
+is equivalent to
+.RS
+.IP
+.ft B
+.nf
+\&.PS
+circle at (1,2)
+circle at (3,4)
+circle at (5,6)
+box
+\&.PE
+.ft
+.fi
+.RE
+.IP
+The commands to be performed for each line can also be taken
+from a macro defined earlier by giving the name of the macro
+as the argument to
+.BR thru .
+.LP
+.B reset
+.br
+.ns
+.TP
+\fBreset\fI variable1\fB,\fI variable2 .\^.\^.
+Reset pre-defined variables
+.IR variable1 ,
+.I variable2
+\&.\^.\^. to their default values.
+If no arguments are given, reset all pre-defined variables
+to their default values.
+Note that assigning a value to
+.B scale
+also causes all pre-defined variables that control dimensions
+to be reset to their default values times the new value of scale.
+.TP
+\fBplot\fR \fIexpr\fR [\fB"\fItext\*(ic\fB"\fR]
+This is a text object which is constructed by using
+.I text
+as a format string for sprintf
+with an argument of
+.IR expr .
+If
+.I text
+is omitted a format string of
+.B "\(ts%g\(ts"
+is used.
+Attributes can be specified in the same way as for a normal text
+object.
+Be very careful that you specify an appropriate format string;
+pic does only very limited checking of the string.
+This is deprecated in favour of
+.BR sprintf .
+.TP
+.IB variable := expr
+This is similar to
+.B =
+except
+.I variable
+must already be defined,
+and the value of
+.I variable
+will be changed only in the innermost block in which it is defined.
+(By contrast,
+.B =
+defines the variable in the current block if it is not already defined there,
+and then changes the value in the current block.)
+.LP
+Arguments of the form
+.IP
+.IR X\ anything\ X
+.LP
+are also allowed to be of the form
+.IP
+.BI {\ anything\ }
+.LP
+In this case
+.I anything
+can contain balanced occurrences of
+.B {
+and
+.BR } .
+Strings may contain
+.I X
+or imbalanced occurrences of
+.B {
+and
+.BR } .
+.SS Expressions
+The syntax for expressions has been significantly extended:
+.LP
+.IB x\ ^\ y
+(exponentiation)
+.br
+.BI sin( x )
+.br
+.BI cos( x )
+.br
+.BI atan2( y , \ x )
+.br
+.BI log( x )
+(base 10)
+.br
+.BI exp( x )
+(base 10, ie 10\v'-.4m'\fIx\*(ic\fR\v'.4m')
+.br
+.BI sqrt( x )
+.br
+.BI int( x )
+.br
+.B rand()
+(return a random number between 0 and 1)
+.br
+.BI rand( x )
+(return a random number between 1 and
+.IR x ;
+deprecated)
+.br
+.BI max( e1 , \ e2 )
+.br
+.BI min( e1 , \ e2 )
+.br
+.BI ! e
+.br
+\fIe1\fB && \fIe2\fR
+.br
+\fIe1\fB || \fIe2\fR
+.br
+\fIe1\fB == \fIe2\fR
+.br
+\fIe1\fB != \fIe2\fR
+.br
+\fIe1\fB >= \fIe2\fR
+.br
+\fIe1\fB > \fIe2\fR
+.br
+\fIe1\fB <= \fIe2\fR
+.br
+\fIe1\fB < \fIe2\fR
+.br
+\fB"\fIstr1\*(ic\fB" == "\fIstr2\*(ic\fB"\fR
+.br
+\fB"\fIstr1\*(ic\fB" != "\fIstr2\*(ic\fB"\fR
+.br
+.LP
+String comparison expressions must be parenthesised in some contexts
+to avoid ambiguity.
+.SS Other Changes
+.LP
+A bare expression,
+.IR expr ,
+is acceptable as an attribute;
+it is equivalent to
+.IR dir\ expr ,
+where
+.I dir
+is the current direction.
+For example
+.IP
+.B line 2i
+.LP
+means draw a line 2 inches long in the current direction.
+.LP
+The maximum width and height of the picture are taken from the variables
+.B maxpswid
+and
+.BR maxpsht .
+Initially these have values 8.5 and 11.
+.LP
+Scientific notation is allowed for numbers.
+For example
+.RS
+.B
+x = 5e\-2
+.RE
+.LP
+Text attributes can be compounded.
+For example,
+.RS
+.B
+"foo" above ljust
+.RE
+is legal.
+.LP
+There is no limit to the depth to which blocks can be examined.
+For example,
+.RS
+.B
+[A: [B: [C: box ]]] with .A.B.C.sw at 1,2
+.br
+.B
+circle at last [\^].A.B.C
+.RE
+is acceptable.
+.LP
+Arcs now have compass points
+determined by the circle of which the arc is a part.
+.LP
+Circles and arcs can be dotted or dashed.
+In \*(tx mode splines can be dotted or dashed.
+.LP
+Boxes can have rounded corners.
+The
+.B rad
+attribute specifies the radius of the quarter-circles at each corner.
+If no
+.B rad
+or
+.B diam
+attribute is given, a radius of
+.B boxrad
+is used.
+Initially,
+.B boxrad
+has a value of 0.
+A box with rounded corners can be dotted or dashed.
+.LP
+The
+.B .PS
+line can have a second argument specifying a maximum height for
+the picture.
+If the width of zero is specified the width will be ignored in computing
+the scaling factor for the picture.
+Note that GNU pic will always scale a picture by the same amount
+vertically as horizontally.
+This is different from the
+.SM DWB
+2.0 pic which may scale a picture by a
+different amount vertically than horizontally if a height is
+specified.
+.LP
+Each text object has an invisible box associated with it.
+The compass points of a text object are determined by this box.
+The implicit motion associated with the object is also determined
+by this box.
+The dimensions of this box are taken from the width and height attributes;
+if the width attribute is not supplied then the width will be taken to be
+.BR textwid ;
+if the height attribute is not supplied then the height will be taken to be
+the number of text strings associated with the object
+times
+.BR textht .
+Initially
+.B textwid
+and
+.B textht
+have a value of 0.
+.LP
+In places where a quoted text string can be used,
+an expression of the form
+.IP
+.BI sprintf(\(ts format \(ts,\ arg ,\fR.\|.\|.\fB)
+.LP
+can also be used;
+this will produce the arguments formatted according to
+.IR format ,
+which should be a string as described in
+.BR printf (3)
+appropriate for the number of arguments supplied,
+using only the
+.BR e ,
+.BR f ,
+.B g
+or
+.B %
+format characters.
+.LP
+The thickness of the lines used to draw objects is controlled by the
+.B linethick
+variable.
+This gives the thickness of lines in points.
+A negative value means use the default thickness:
+in \*(tx output mode, this means use a thickness of 8 milliinches;
+in \*(tx output mode with the
+.B -c
+option, this means use the line thickness specified by
+.B .ps
+lines;
+in troff output mode, this means use a thickness proportional
+to the pointsize.
+A zero value means draw the thinnest possible line supported by
+the output device.
+Initially it has a value of -1.
+There is also a
+.BR thick [ ness ]
+attribute.
+For example,
+.RS
+.LP
+.B circle thickness 1.5
+.RE
+.LP
+would draw a circle using a line with a thickness of 1.5 points.
+The thickness of lines is not affected by the
+value of the
+.B scale
+variable, nor by the width or height given in the
+.B .PS
+line.
+.LP
+Boxes (including boxes with rounded corners),
+circles and ellipses can be filled by giving then an attribute of
+.BR fill [ ed ].
+This takes an optional argument of an expression with a value between
+0 and 1; 0 will fill it with white, 1 with black, values in between
+with a proportionally gray shade.
+A value greater than 1 can also be used:
+this means fill with the
+shade of gray that is currently being used for text and lines.
+Normally this will be black, but output devices may provide
+a mechanism for changing this.
+Without an argument, then the value of the variable
+.B fillval
+will be used.
+Initially this has a value of 0.5.
+The invisible attribute does not affect the filling of objects.
+Any text associated with a filled object will be added after the
+object has been filled, so that the text will not be obscured
+by the filling.
+.LP
+Arrow heads will be drawn as solid triangles if the variable
+.B arrowhead
+is non-zero and either \*(tx mode is enabled or
+the
+.B \-x
+option has been given.
+Initially
+.B arrowhead
+has a value of 1.
+.LP
+The troff output of pic is device-independent.
+The
+.B \-T
+option is therefore redundant.
+All numbers are taken to be in inches; numbers are never interpreted
+to be in troff machine units.
+.LP
+Objects can have an
+.B aligned
+attribute.
+This will only work when the postprocessor is
+.BR grops .
+Any text associated with an object having the
+.B aligned
+attribute will be rotated about the center of the object
+so that it is aligned in the direction from the start point
+to the end point of the object.
+Note that this attribute will have no effect for objects whose start and
+end points are coincident.
+.LP
+In places where
+.IB n th
+is allowed
+.BI ` expr 'th
+is also allowed.
+Note that
+.B 'th
+is a single token: no space is allowed between the
+.B '
+and the
+.BR th .
+For example,
+.IP
+.B
+.nf
+for i = 1 to 4 do {
+ line from `i'th box.nw to `i+1'th box.se
+}
+.fi
+.SH FILES
+.Tp \w'\fB/usr/share/tmac/tmac.pic'u+3n
+.B
+/usr/share/tmac/tmac.pic
+Example definitions of the
+.B PS
+and
+.B PE
+macros.
+.SH "SEE ALSO"
+.BR troff (1),
+.BR groff_out (5),
+.BR tex (1)
+.br
+Tpic: Pic for \*(tx
+.br
+AT&T Bell Laboratories, Computing Science Technical Report No.\ 116,
+PIC \(em A Graphics Language for Typesetting.
+(This can be obtained by sending a mail message to netlib@research.att.com
+with a body of `send\ 116\ from\ research/cstr'.)
+.SH BUGS
+.LP
+Input characters that are illegal for
+.B groff
+(ie those with
+.SM ASCII
+code 0 or between 013 and 037 octal or between 0200 and 0237 octal)
+are rejected even in \*(tx mode.
+.LP
+The interpretation of
+.B fillval
+is incompatible with the pic in 10th edition Unix,
+which interprets 0 as black and 1 as white.
diff --git a/gnu/usr.bin/groff/pic/pic.h b/gnu/usr.bin/groff/pic/pic.h
new file mode 100644
index 000000000000..30c2cd5a1e8e
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/pic.h
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <errno.h>
+
+extern "C" {
+ double hypot(double, double);
+}
+
+#include "assert.h"
+#include "cset.h"
+#include "lib.h"
+#include "stringclass.h"
+#include "errarg.h"
+#include "error.h"
+#include "position.h"
+#include "text.h"
+#include "output.h"
+
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+class input {
+ input *next;
+public:
+ input();
+ virtual ~input();
+ virtual int get() = 0;
+ virtual int peek() = 0;
+ virtual int get_location(const char **, int *);
+ friend class input_stack;
+ friend class copy_rest_thru_input;
+};
+
+class file_input : public input {
+ FILE *fp;
+ const char *filename;
+ int lineno;
+ string line;
+ const char *ptr;
+ int read_line();
+public:
+ file_input(FILE *, const char *);
+ ~file_input();
+ int get();
+ int peek();
+ int get_location(const char **, int *);
+};
+
+void lex_init(input *);
+int get_location(char **, int *);
+
+void do_copy(const char *file);
+void parse_init();
+void parse_cleanup();
+
+void lex_error(const char *message,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+void lex_warning(const char *message,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+void lex_cleanup();
+
+extern int flyback_flag;
+extern int command_char;
+// zero_length_line_flag is non-zero if zero-length lines are drawn
+// as dots by the output device
+extern int zero_length_line_flag;
+extern int driver_extension_flag;
+extern int compatible_flag;
diff --git a/gnu/usr.bin/groff/pic/pic.y b/gnu/usr.bin/groff/pic/pic.y
new file mode 100644
index 000000000000..8c0405ffe43b
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/pic.y
@@ -0,0 +1,1780 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+%{
+#include "pic.h"
+#include "ptable.h"
+#include "object.h"
+
+extern int delim_flag;
+extern void do_copy(const char *);
+extern void copy_rest_thru(const char *, const char *);
+extern void copy_file_thru(const char *, const char *, const char *);
+extern void push_body(const char *);
+extern void do_for(char *var, double from, double to,
+ int by_is_multiplicative, double by, char *body);
+extern void do_lookahead();
+
+#undef fmod
+#undef rand
+
+extern "C" {
+ double fmod(double, double);
+ int rand();
+}
+
+/* Maximum number of characters produced by printf("%g") */
+#define GDIGITS 14
+
+int yylex();
+void yyerror(const char *);
+
+void reset(const char *nm);
+void reset_all();
+
+place *lookup_label(const char *);
+void define_label(const char *label, const place *pl);
+
+direction current_direction;
+position current_position;
+
+implement_ptable(place)
+
+PTABLE(place) top_table;
+
+PTABLE(place) *current_table = &top_table;
+saved_state *current_saved_state = 0;
+
+object_list olist;
+
+const char *ordinal_postfix(int n);
+const char *object_type_name(object_type type);
+char *format_number(const char *form, double n);
+char *do_sprintf(const char *form, const double *v, int nv);
+
+%}
+
+
+%union {
+ char *str;
+ int n;
+ double x;
+ struct { double x, y; } pair;
+ struct { double x; char *body; } if_data;
+ struct { char *str; const char *filename; int lineno; } lstr;
+ struct { double *v; int nv; int maxv; } dv;
+ struct { double val; int is_multiplicative; } by;
+ place pl;
+ object *obj;
+ corner crn;
+ path *pth;
+ object_spec *spec;
+ saved_state *pstate;
+ graphics_state state;
+ object_type obtype;
+}
+
+%token <str> LABEL
+%token <str> VARIABLE
+%token <x> NUMBER
+%token <lstr> TEXT
+%token <lstr> COMMAND_LINE
+%token <str> DELIMITED
+%token <n> ORDINAL
+%token TH
+%token LEFT_ARROW_HEAD
+%token RIGHT_ARROW_HEAD
+%token DOUBLE_ARROW_HEAD
+%token LAST
+%token UP
+%token DOWN
+%token LEFT
+%token RIGHT
+%token BOX
+%token CIRCLE
+%token ELLIPSE
+%token ARC
+%token LINE
+%token ARROW
+%token MOVE
+%token SPLINE
+%token HEIGHT
+%token RADIUS
+%token WIDTH
+%token DIAMETER
+%token UP
+%token DOWN
+%token RIGHT
+%token LEFT
+%token FROM
+%token TO
+%token AT
+%token WITH
+%token BY
+%token THEN
+%token DOTTED
+%token DASHED
+%token CHOP
+%token SAME
+%token INVISIBLE
+%token LJUST
+%token RJUST
+%token ABOVE
+%token BELOW
+%token OF
+%token THE
+%token WAY
+%token BETWEEN
+%token AND
+%token HERE
+%token DOT_N
+%token DOT_E
+%token DOT_W
+%token DOT_S
+%token DOT_NE
+%token DOT_SE
+%token DOT_NW
+%token DOT_SW
+%token DOT_C
+%token DOT_START
+%token DOT_END
+%token DOT_X
+%token DOT_Y
+%token DOT_HT
+%token DOT_WID
+%token DOT_RAD
+%token SIN
+%token COS
+%token ATAN2
+%token LOG
+%token EXP
+%token SQRT
+%token K_MAX
+%token K_MIN
+%token INT
+%token RAND
+%token COPY
+%token THRU
+%token TOP
+%token BOTTOM
+%token UPPER
+%token LOWER
+%token SH
+%token PRINT
+%token CW
+%token CCW
+%token FOR
+%token DO
+%token IF
+%token ELSE
+%token ANDAND
+%token OROR
+%token NOTEQUAL
+%token EQUALEQUAL
+%token LESSEQUAL
+%token GREATEREQUAL
+%token LEFT_CORNER
+%token RIGHT_CORNER
+%token CENTER
+%token END
+%token START
+%token RESET
+%token UNTIL
+%token PLOT
+%token THICKNESS
+%token FILL
+%token ALIGNED
+%token SPRINTF
+%token COMMAND
+
+%token DEFINE
+%token UNDEF
+
+/* this ensures that plot 17 "%g" parses as (plot 17 "%g") */
+%left PLOT
+%left TEXT SPRINTF
+
+/* give text adjustments higher precedence than TEXT, so that
+box "foo" above ljust == box ("foo" above ljust)
+*/
+
+%left LJUST RJUST ABOVE BELOW
+
+%left LEFT RIGHT
+/* Give attributes that take an optional expression a higher
+precedence than left and right, so that eg `line chop left'
+parses properly. */
+%left CHOP DASHED DOTTED UP DOWN FILL
+%left LABEL
+
+%left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND LAST
+%left ORDINAL HERE '`'
+
+/* these need to be lower than '-' */
+%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS
+
+/* these must have higher precedence than CHOP so that `label %prec CHOP'
+works */
+%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C
+%left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER
+%left UPPER LOWER CENTER START END
+
+%left ','
+%left OROR
+%left ANDAND
+%left EQUALEQUAL NOTEQUAL
+%left '<' '>' LESSEQUAL GREATEREQUAL
+
+%left BETWEEN OF
+%left AND
+
+%left '+' '-'
+%left '*' '/' '%'
+%right '!'
+%right '^'
+
+%type <x> expr any_expr text_expr
+%type <by> optional_by
+%type <pair> expr_pair position_not_place
+%type <if_data> simple_if
+%type <obj> nth_primitive
+%type <crn> corner
+%type <pth> path label_path relative_path
+%type <pl> place label element element_list middle_element_list
+%type <spec> object_spec
+%type <pair> position
+%type <obtype> object_type
+%type <n> optional_ordinal_last ordinal
+%type <str> until
+%type <dv> sprintf_args
+%type <lstr> text print_args print_arg
+
+%%
+
+top:
+ optional_separator
+ | element_list
+ {
+ if (olist.head)
+ print_picture(olist.head);
+ }
+ ;
+
+
+element_list:
+ optional_separator middle_element_list optional_separator
+ { $$ = $2; }
+ ;
+
+middle_element_list:
+ element
+ { $$ = $1; }
+ | middle_element_list separator element
+ { $$ = $1; }
+ ;
+
+optional_separator:
+ /* empty */
+ | separator
+ ;
+
+separator:
+ ';'
+ | separator ';'
+ ;
+
+placeless_element:
+ VARIABLE '=' any_expr
+ {
+ define_variable($1, $3);
+ a_delete $1;
+ }
+ | VARIABLE ':' '=' any_expr
+ {
+ place *p = lookup_label($1);
+ if (!p) {
+ lex_error("variable `%1' not defined", $1);
+ YYABORT;
+ }
+ p->obj = 0;
+ p->x = $4;
+ p->y = 0.0;
+ a_delete $1;
+ }
+ | UP
+ { current_direction = UP_DIRECTION; }
+ | DOWN
+ { current_direction = DOWN_DIRECTION; }
+ | LEFT
+ { current_direction = LEFT_DIRECTION; }
+ | RIGHT
+ { current_direction = RIGHT_DIRECTION; }
+ | COMMAND_LINE
+ {
+ olist.append(make_command_object($1.str, $1.filename,
+ $1.lineno));
+ }
+ | COMMAND print_args
+ {
+ olist.append(make_command_object($2.str, $2.filename,
+ $2.lineno));
+ }
+ | PRINT print_args
+ {
+ fprintf(stderr, "%s\n", $2.str);
+ a_delete $2.str;
+ fflush(stderr);
+ }
+ | SH
+ { delim_flag = 1; }
+ DELIMITED
+ {
+ delim_flag = 0;
+ system($3);
+ a_delete $3;
+ }
+ | COPY TEXT
+ {
+ if (yychar < 0)
+ do_lookahead();
+ do_copy($2.str);
+ // do not delete the filename
+ }
+ | COPY TEXT THRU
+ { delim_flag = 2; }
+ DELIMITED
+ { delim_flag = 0; }
+ until
+ {
+ if (yychar < 0)
+ do_lookahead();
+ copy_file_thru($2.str, $5, $7);
+ // do not delete the filename
+ a_delete $5;
+ a_delete $7;
+ }
+ | COPY THRU
+ { delim_flag = 2; }
+ DELIMITED
+ { delim_flag = 0; }
+ until
+ {
+ if (yychar < 0)
+ do_lookahead();
+ copy_rest_thru($4, $6);
+ a_delete $4;
+ a_delete $6;
+ }
+ | FOR VARIABLE '=' expr TO expr optional_by DO
+ { delim_flag = 1; }
+ DELIMITED
+ {
+ delim_flag = 0;
+ if (yychar < 0)
+ do_lookahead();
+ do_for($2, $4, $6, $7.is_multiplicative, $7.val, $10);
+ }
+ | simple_if
+ {
+ if (yychar < 0)
+ do_lookahead();
+ if ($1.x != 0.0)
+ push_body($1.body);
+ a_delete $1.body;
+ }
+ | simple_if ELSE
+ { delim_flag = 1; }
+ DELIMITED
+ {
+ delim_flag = 0;
+ if (yychar < 0)
+ do_lookahead();
+ if ($1.x != 0.0)
+ push_body($1.body);
+ else
+ push_body($4);
+ a_delete $1.body;
+ a_delete $4;
+ }
+ | reset_variables
+ | RESET
+ { define_variable("scale", 1.0); }
+ ;
+
+reset_variables:
+ RESET VARIABLE
+ { reset($2); a_delete $2; }
+ | reset_variables VARIABLE
+ { reset($2); a_delete $2; }
+ | reset_variables ',' VARIABLE
+ { reset($3); a_delete $3; }
+ ;
+
+print_args:
+ print_arg
+ { $$ = $1; }
+ | print_args print_arg
+ {
+ $$.str = new char[strlen($1.str) + strlen($2.str) + 1];
+ strcpy($$.str, $1.str);
+ strcat($$.str, $2.str);
+ a_delete $1.str;
+ a_delete $2.str;
+ if ($1.filename) {
+ $$.filename = $1.filename;
+ $$.lineno = $1.lineno;
+ }
+ else if ($2.filename) {
+ $$.filename = $2.filename;
+ $$.lineno = $2.lineno;
+ }
+ }
+ ;
+
+print_arg:
+ expr %prec ','
+ {
+ $$.str = new char[GDIGITS + 1];
+ sprintf($$.str, "%g", $1);
+ $$.filename = 0;
+ $$.lineno = 0;
+ }
+ | text
+ { $$ = $1; }
+ | position %prec ','
+ {
+ $$.str = new char[GDIGITS + 2 + GDIGITS + 1];
+ sprintf($$.str, "%g, %g", $1.x, $1.y);
+ $$.filename = 0;
+ $$.lineno = 0;
+ }
+
+simple_if:
+ IF any_expr THEN
+ { delim_flag = 1; }
+ DELIMITED
+ { delim_flag = 0; $$.x = $2; $$.body = $5; }
+ ;
+
+until:
+ /* empty */
+ { $$ = 0; }
+ | UNTIL TEXT
+ { $$ = $2.str; }
+ ;
+
+any_expr:
+ expr
+ { $$ = $1; }
+ | text_expr
+ { $$ = $1; }
+ ;
+
+text_expr:
+ text EQUALEQUAL text
+ {
+ $$ = strcmp($1.str, $3.str) == 0;
+ a_delete $1.str;
+ a_delete $3.str;
+ }
+ | text NOTEQUAL text
+ {
+ $$ = strcmp($1.str, $3.str) != 0;
+ a_delete $1.str;
+ a_delete $3.str;
+ }
+ | text_expr ANDAND text_expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | text_expr ANDAND expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | expr ANDAND text_expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | text_expr OROR text_expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | text_expr OROR expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | expr OROR text_expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | '!' text_expr
+ { $$ = ($2 == 0.0); }
+ ;
+
+
+optional_by:
+ /* empty */
+ { $$.val = 1.0; $$.is_multiplicative = 0; }
+ | BY expr
+ { $$.val = $2; $$.is_multiplicative = 0; }
+ | BY '*' expr
+ { $$.val = $3; $$.is_multiplicative = 1; }
+ ;
+
+element:
+ object_spec
+ {
+ $$.obj = $1->make_object(&current_position,
+ &current_direction);
+ if ($$.obj == 0)
+ YYABORT;
+ delete $1;
+ if ($$.obj)
+ olist.append($$.obj);
+ else {
+ $$.x = current_position.x;
+ $$.y = current_position.y;
+ }
+ }
+ | LABEL ':' optional_separator element
+ { $$ = $4; define_label($1, & $$); a_delete $1; }
+ | LABEL ':' optional_separator position_not_place
+ {
+ $$.obj = 0;
+ $$.x = $4.x;
+ $$.y = $4.y;
+ define_label($1, & $$);
+ a_delete $1;
+ }
+ | LABEL ':' optional_separator place
+ {
+ $$ = $4;
+ define_label($1, & $$);
+ a_delete $1;
+ }
+ | '{'
+ {
+ $<state>$.x = current_position.x;
+ $<state>$.y = current_position.y;
+ $<state>$.dir = current_direction;
+ }
+ element_list '}'
+ {
+ current_position.x = $<state>2.x;
+ current_position.y = $<state>2.y;
+ current_direction = $<state>2.dir;
+ }
+ optional_element
+ {
+ $$ = $3;
+ }
+ | placeless_element
+ {
+ $$.obj = 0;
+ $$.x = current_position.x;
+ $$.y = current_position.y;
+ }
+ ;
+
+optional_element:
+ /* empty */
+ {}
+ | element
+ {}
+ ;
+
+object_spec:
+ BOX
+ {
+ $$ = new object_spec(BOX_OBJECT);
+ }
+ | CIRCLE
+ {
+ $$ = new object_spec(CIRCLE_OBJECT);
+ }
+ | ELLIPSE
+ {
+ $$ = new object_spec(ELLIPSE_OBJECT);
+ }
+ | ARC
+ {
+ $$ = new object_spec(ARC_OBJECT);
+ $$->dir = current_direction;
+ }
+ | LINE
+ {
+ $$ = new object_spec(LINE_OBJECT);
+ lookup_variable("lineht", & $$->segment_height);
+ lookup_variable("linewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | ARROW
+ {
+ $$ = new object_spec(ARROW_OBJECT);
+ lookup_variable("lineht", & $$->segment_height);
+ lookup_variable("linewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | MOVE
+ {
+ $$ = new object_spec(MOVE_OBJECT);
+ lookup_variable("moveht", & $$->segment_height);
+ lookup_variable("movewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | SPLINE
+ {
+ $$ = new object_spec(SPLINE_OBJECT);
+ lookup_variable("lineht", & $$->segment_height);
+ lookup_variable("linewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | text %prec TEXT
+ {
+ $$ = new object_spec(TEXT_OBJECT);
+ $$->text = new text_item($1.str, $1.filename, $1.lineno);
+ }
+ | PLOT expr
+ {
+ $$ = new object_spec(TEXT_OBJECT);
+ $$->text = new text_item(format_number(0, $2), 0, -1);
+ }
+ | PLOT expr text
+ {
+ $$ = new object_spec(TEXT_OBJECT);
+ $$->text = new text_item(format_number($3.str, $2),
+ $3.filename, $3.lineno);
+ a_delete $3.str;
+ }
+ | '['
+ {
+ saved_state *p = new saved_state;
+ $<pstate>$ = p;
+ p->x = current_position.x;
+ p->y = current_position.y;
+ p->dir = current_direction;
+ p->tbl = current_table;
+ p->prev = current_saved_state;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+ current_table = new PTABLE(place);
+ current_saved_state = p;
+ olist.append(make_mark_object());
+ }
+ element_list ']'
+ {
+ current_position.x = $<pstate>2->x;
+ current_position.y = $<pstate>2->y;
+ current_direction = $<pstate>2->dir;
+ $$ = new object_spec(BLOCK_OBJECT);
+ olist.wrap_up_block(& $$->oblist);
+ $$->tbl = current_table;
+ current_table = $<pstate>2->tbl;
+ current_saved_state = $<pstate>2->prev;
+ delete $<pstate>2;
+ }
+ | object_spec HEIGHT expr
+ {
+ $$ = $1;
+ $$->height = $3;
+ $$->flags |= HAS_HEIGHT;
+ }
+ | object_spec RADIUS expr
+ {
+ $$ = $1;
+ $$->radius = $3;
+ $$->flags |= HAS_RADIUS;
+ }
+ | object_spec WIDTH expr
+ {
+ $$ = $1;
+ $$->width = $3;
+ $$->flags |= HAS_WIDTH;
+ }
+ | object_spec DIAMETER expr
+ {
+ $$ = $1;
+ $$->radius = $3/2.0;
+ $$->flags |= HAS_RADIUS;
+ }
+ | object_spec expr %prec HEIGHT
+ {
+ $$ = $1;
+ $$->flags |= HAS_SEGMENT;
+ switch ($$->dir) {
+ case UP_DIRECTION:
+ $$->segment_pos.y += $2;
+ break;
+ case DOWN_DIRECTION:
+ $$->segment_pos.y -= $2;
+ break;
+ case RIGHT_DIRECTION:
+ $$->segment_pos.x += $2;
+ break;
+ case LEFT_DIRECTION:
+ $$->segment_pos.x -= $2;
+ break;
+ }
+ }
+ | object_spec UP
+ {
+ $$ = $1;
+ $$->dir = UP_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y += $$->segment_height;
+ }
+ | object_spec UP expr
+ {
+ $$ = $1;
+ $$->dir = UP_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y += $3;
+ }
+ | object_spec DOWN
+ {
+ $$ = $1;
+ $$->dir = DOWN_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y -= $$->segment_height;
+ }
+ | object_spec DOWN expr
+ {
+ $$ = $1;
+ $$->dir = DOWN_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y -= $3;
+ }
+ | object_spec RIGHT
+ {
+ $$ = $1;
+ $$->dir = RIGHT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x += $$->segment_width;
+ }
+ | object_spec RIGHT expr
+ {
+ $$ = $1;
+ $$->dir = RIGHT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x += $3;
+ }
+ | object_spec LEFT
+ {
+ $$ = $1;
+ $$->dir = LEFT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x -= $$->segment_width;
+ }
+ | object_spec LEFT expr
+ {
+ $$ = $1;
+ $$->dir = LEFT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x -= $3;
+ }
+ | object_spec FROM position
+ {
+ $$ = $1;
+ $$->flags |= HAS_FROM;
+ $$->from.x = $3.x;
+ $$->from.y = $3.y;
+ }
+ | object_spec TO position
+ {
+ $$ = $1;
+ if ($$->flags & HAS_SEGMENT)
+ $$->segment_list = new segment($$->segment_pos,
+ $$->segment_is_absolute,
+ $$->segment_list);
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x = $3.x;
+ $$->segment_pos.y = $3.y;
+ $$->segment_is_absolute = 1;
+ $$->flags |= HAS_TO;
+ $$->to.x = $3.x;
+ $$->to.y = $3.y;
+ }
+ | object_spec AT position
+ {
+ $$ = $1;
+ $$->flags |= HAS_AT;
+ $$->at.x = $3.x;
+ $$->at.y = $3.y;
+ if ($$->type != ARC_OBJECT) {
+ $$->flags |= HAS_FROM;
+ $$->from.x = $3.x;
+ $$->from.y = $3.y;
+ }
+ }
+ | object_spec WITH path
+ {
+ $$ = $1;
+ $$->flags |= HAS_WITH;
+ $$->with = $3;
+ }
+ | object_spec BY expr_pair
+ {
+ $$ = $1;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x += $3.x;
+ $$->segment_pos.y += $3.y;
+ }
+ | object_spec THEN
+ {
+ $$ = $1;
+ if ($$->flags & HAS_SEGMENT) {
+ $$->segment_list = new segment($$->segment_pos,
+ $$->segment_is_absolute,
+ $$->segment_list);
+ $$->flags &= ~HAS_SEGMENT;
+ $$->segment_pos.x = $$->segment_pos.y = 0.0;
+ $$->segment_is_absolute = 0;
+ }
+ }
+ | object_spec DOTTED
+ {
+ $$ = $1;
+ $$->flags |= IS_DOTTED;
+ lookup_variable("dashwid", & $$->dash_width);
+ }
+ | object_spec DOTTED expr
+ {
+ $$ = $1;
+ $$->flags |= IS_DOTTED;
+ $$->dash_width = $3;
+ }
+ | object_spec DASHED
+ {
+ $$ = $1;
+ $$->flags |= IS_DASHED;
+ lookup_variable("dashwid", & $$->dash_width);
+ }
+ | object_spec DASHED expr
+ {
+ $$ = $1;
+ $$->flags |= IS_DASHED;
+ $$->dash_width = $3;
+ }
+ | object_spec FILL
+ {
+ $$ = $1;
+ $$->flags |= IS_DEFAULT_FILLED;
+ }
+ | object_spec FILL expr
+ {
+ $$ = $1;
+ $$->flags |= IS_FILLED;
+ $$->fill = $3;
+ }
+ | object_spec CHOP
+ {
+ $$ = $1;
+ // line chop chop means line chop 0 chop 0
+ if ($$->flags & IS_DEFAULT_CHOPPED) {
+ $$->flags |= IS_CHOPPED;
+ $$->flags &= ~IS_DEFAULT_CHOPPED;
+ $$->start_chop = $$->end_chop = 0.0;
+ }
+ else if ($$->flags & IS_CHOPPED) {
+ $$->end_chop = 0.0;
+ }
+ else {
+ $$->flags |= IS_DEFAULT_CHOPPED;
+ }
+ }
+ | object_spec CHOP expr
+ {
+ $$ = $1;
+ if ($$->flags & IS_DEFAULT_CHOPPED) {
+ $$->flags |= IS_CHOPPED;
+ $$->flags &= ~IS_DEFAULT_CHOPPED;
+ $$->start_chop = 0.0;
+ $$->end_chop = $3;
+ }
+ else if ($$->flags & IS_CHOPPED) {
+ $$->end_chop = $3;
+ }
+ else {
+ $$->start_chop = $$->end_chop = $3;
+ $$->flags |= IS_CHOPPED;
+ }
+ }
+ | object_spec SAME
+ {
+ $$ = $1;
+ $$->flags |= IS_SAME;
+ }
+ | object_spec INVISIBLE
+ {
+ $$ = $1;
+ $$->flags |= IS_INVISIBLE;
+ }
+ | object_spec LEFT_ARROW_HEAD
+ {
+ $$ = $1;
+ $$->flags |= HAS_LEFT_ARROW_HEAD;
+ }
+ | object_spec RIGHT_ARROW_HEAD
+ {
+ $$ = $1;
+ $$->flags |= HAS_RIGHT_ARROW_HEAD;
+ }
+ | object_spec DOUBLE_ARROW_HEAD
+ {
+ $$ = $1;
+ $$->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD);
+ }
+ | object_spec CW
+ {
+ $$ = $1;
+ $$->flags |= IS_CLOCKWISE;
+ }
+ | object_spec CCW
+ {
+ $$ = $1;
+ $$->flags &= ~IS_CLOCKWISE;
+ }
+ | object_spec text %prec TEXT
+ {
+ $$ = $1;
+ for (text_item **p = & $$->text; *p; p = &(*p)->next)
+ ;
+ *p = new text_item($2.str, $2.filename, $2.lineno);
+ }
+ | object_spec LJUST
+ {
+ $$ = $1;
+ if ($$->text) {
+ for (text_item *p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.h = LEFT_ADJUST;
+ }
+ }
+ | object_spec RJUST
+ {
+ $$ = $1;
+ if ($$->text) {
+ for (text_item *p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.h = RIGHT_ADJUST;
+ }
+ }
+ | object_spec ABOVE
+ {
+ $$ = $1;
+ if ($$->text) {
+ for (text_item *p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.v = ABOVE_ADJUST;
+ }
+ }
+ | object_spec BELOW
+ {
+ $$ = $1;
+ if ($$->text) {
+ for (text_item *p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.v = BELOW_ADJUST;
+ }
+ }
+ | object_spec THICKNESS expr
+ {
+ $$ = $1;
+ $$->flags |= HAS_THICKNESS;
+ $$->thickness = $3;
+ }
+ | object_spec ALIGNED
+ {
+ $$ = $1;
+ $$->flags |= IS_ALIGNED;
+ }
+ ;
+
+text:
+ TEXT
+ {
+ $$ = $1;
+ }
+ | SPRINTF '(' TEXT sprintf_args ')'
+ {
+ $$.filename = $3.filename;
+ $$.lineno = $3.lineno;
+ $$.str = do_sprintf($3.str, $4.v, $4.nv);
+ a_delete $4.v;
+ a_delete $3.str;
+ }
+ ;
+
+sprintf_args:
+ /* empty */
+ {
+ $$.v = 0;
+ $$.nv = 0;
+ $$.maxv = 0;
+ }
+ | sprintf_args ',' expr
+ {
+ $$ = $1;
+ if ($$.nv >= $$.maxv) {
+ if ($$.nv == 0) {
+ $$.v = new double[4];
+ $$.maxv = 4;
+ }
+ else {
+ double *oldv = $$.v;
+ $$.maxv *= 2;
+ $$.v = new double[$$.maxv];
+ memcpy($$.v, oldv, $$.nv*sizeof(double));
+ a_delete oldv;
+ }
+ }
+ $$.v[$$.nv] = $3;
+ $$.nv += 1;
+ }
+ ;
+
+position:
+ position_not_place
+ { $$ = $1; }
+ | place
+ {
+ position pos = $1;
+ $$.x = pos.x;
+ $$.y = pos.y;
+ }
+ ;
+
+position_not_place:
+ expr_pair
+ { $$ = $1; }
+ | position '+' expr_pair
+ {
+ $$.x = $1.x + $3.x;
+ $$.y = $1.y + $3.y;
+ }
+ | position '-' expr_pair
+ {
+ $$.x = $1.x - $3.x;
+ $$.y = $1.y - $3.y;
+ }
+ | '(' position ',' position ')'
+ {
+ $$.x = $2.x;
+ $$.y = $4.y;
+ }
+ | expr between position AND position
+ {
+ $$.x = (1.0 - $1)*$3.x + $1*$5.x;
+ $$.y = (1.0 - $1)*$3.y + $1*$5.y;
+ }
+ | expr '<' position ',' position '>'
+ {
+ $$.x = (1.0 - $1)*$3.x + $1*$5.x;
+ $$.y = (1.0 - $1)*$3.y + $1*$5.y;
+ }
+ ;
+
+between:
+ BETWEEN
+ | OF THE WAY BETWEEN
+ ;
+
+expr_pair:
+ expr ',' expr
+ { $$.x = $1; $$.y = $3; }
+ | '(' expr_pair ')'
+ { $$ = $2; }
+ ;
+
+place:
+ label %prec CHOP /* line at A left == line (at A) left */
+ { $$ = $1; }
+ | label corner
+ {
+ path pth($2);
+ if (!pth.follow($1, & $$))
+ YYABORT;
+ }
+ | corner label
+ {
+ path pth($1);
+ if (!pth.follow($2, & $$))
+ YYABORT;
+ }
+ | corner OF label
+ {
+ path pth($1);
+ if (!pth.follow($3, & $$))
+ YYABORT;
+ }
+ | HERE
+ {
+ $$.x = current_position.x;
+ $$.y = current_position.y;
+ $$.obj = 0;
+ }
+ ;
+
+label:
+ LABEL
+ {
+ place *p = lookup_label($1);
+ if (!p) {
+ lex_error("there is no place `%1'", $1);
+ YYABORT;
+ }
+ $$ = *p;
+ a_delete $1;
+ }
+ | nth_primitive
+ {
+ $$.obj = $1;
+ }
+ | label '.' LABEL
+ {
+ path pth($3);
+ if (!pth.follow($1, & $$))
+ YYABORT;
+ }
+ ;
+
+ordinal:
+ ORDINAL
+ { $$ = $1; }
+ | '`' any_expr TH
+ {
+ // XXX Check for overflow (and non-integers?).
+ $$ = (int)$2;
+ }
+ ;
+
+optional_ordinal_last:
+ LAST
+ { $$ = 1; }
+ | ordinal LAST
+ { $$ = $1; }
+ ;
+
+nth_primitive:
+ ordinal object_type
+ {
+ int count = 0;
+ for (object *p = olist.head; p != 0; p = p->next)
+ if (p->type() == $2 && ++count == $1) {
+ $$ = p;
+ break;
+ }
+ if (p == 0) {
+ lex_error("there is no %1%2 %3", $1, ordinal_postfix($1),
+ object_type_name($2));
+ YYABORT;
+ }
+ }
+ | optional_ordinal_last object_type
+ {
+ int count = 0;
+ for (object *p = olist.tail; p != 0; p = p->prev)
+ if (p->type() == $2 && ++count == $1) {
+ $$ = p;
+ break;
+ }
+ if (p == 0) {
+ lex_error("there is no %1%2 last %3", $1,
+ ordinal_postfix($1), object_type_name($2));
+ YYABORT;
+ }
+ }
+ ;
+
+object_type:
+ BOX
+ { $$ = BOX_OBJECT; }
+ | CIRCLE
+ { $$ = CIRCLE_OBJECT; }
+ | ELLIPSE
+ { $$ = ELLIPSE_OBJECT; }
+ | ARC
+ { $$ = ARC_OBJECT; }
+ | LINE
+ { $$ = LINE_OBJECT; }
+ | ARROW
+ { $$ = ARROW_OBJECT; }
+ | SPLINE
+ { $$ = SPLINE_OBJECT; }
+ | '[' ']'
+ { $$ = BLOCK_OBJECT; }
+ | TEXT
+ { $$ = TEXT_OBJECT; }
+ ;
+
+label_path:
+ '.' LABEL
+ {
+ $$ = new path($2);
+ }
+ | label_path '.' LABEL
+ {
+ $$ = $1;
+ $$->append($3);
+ }
+ ;
+
+relative_path:
+ corner
+ {
+ $$ = new path($1);
+ }
+ /* give this a lower precedence than LEFT and RIGHT so that
+ [A: box] with .A left == [A: box] with (.A left) */
+
+ | label_path %prec TEXT
+ {
+ $$ = $1;
+ }
+ | label_path corner
+ {
+ $$ = $1;
+ $$->append($2);
+ }
+ ;
+
+path:
+ relative_path
+ {
+ $$ = $1;
+ }
+ /* The rest of these rules are a compatibility sop. */
+ | ORDINAL LAST object_type relative_path
+ {
+ lex_warning("`%1%2 last %3' in `with' argument ignored",
+ $1, ordinal_postfix($1), object_type_name($3));
+ $$ = $4;
+ }
+ | LAST object_type relative_path
+ {
+ lex_warning("`last %1' in `with' argument ignored",
+ object_type_name($2));
+ $$ = $3;
+ }
+ | ORDINAL object_type relative_path
+ {
+ lex_warning("`%1%2 %3' in `with' argument ignored",
+ $1, ordinal_postfix($1), object_type_name($2));
+ $$ = $3;
+ }
+ | LABEL relative_path
+ {
+ lex_warning("initial `%1' in `with' argument ignored", $1);
+ a_delete $1;
+ $$ = $2;
+ }
+ ;
+
+corner:
+ DOT_N
+ { $$ = &object::north; }
+ | DOT_E
+ { $$ = &object::east; }
+ | DOT_W
+ { $$ = &object::west; }
+ | DOT_S
+ { $$ = &object::south; }
+ | DOT_NE
+ { $$ = &object::north_east; }
+ | DOT_SE
+ { $$ = &object:: south_east; }
+ | DOT_NW
+ { $$ = &object::north_west; }
+ | DOT_SW
+ { $$ = &object::south_west; }
+ | DOT_C
+ { $$ = &object::center; }
+ | DOT_START
+ { $$ = &object::start; }
+ | DOT_END
+ { $$ = &object::end; }
+ | TOP
+ { $$ = &object::north; }
+ | BOTTOM
+ { $$ = &object::south; }
+ | LEFT
+ { $$ = &object::west; }
+ | RIGHT
+ { $$ = &object::east; }
+ | UPPER LEFT
+ { $$ = &object::north_west; }
+ | LOWER LEFT
+ { $$ = &object::south_west; }
+ | UPPER RIGHT
+ { $$ = &object::north_east; }
+ | LOWER RIGHT
+ { $$ = &object::south_east; }
+ | LEFT_CORNER
+ { $$ = &object::west; }
+ | RIGHT_CORNER
+ { $$ = &object::east; }
+ | UPPER LEFT_CORNER
+ { $$ = &object::north_west; }
+ | LOWER LEFT_CORNER
+ { $$ = &object::south_west; }
+ | UPPER RIGHT_CORNER
+ { $$ = &object::north_east; }
+ | LOWER RIGHT_CORNER
+ { $$ = &object::south_east; }
+ | CENTER
+ { $$ = &object::center; }
+ | START
+ { $$ = &object::start; }
+ | END
+ { $$ = &object::end; }
+ ;
+
+expr:
+ VARIABLE
+ {
+ if (!lookup_variable($1, & $$)) {
+ lex_error("there is no variable `%1'", $1);
+ YYABORT;
+ }
+ a_delete $1;
+ }
+ | NUMBER
+ { $$ = $1; }
+ | place DOT_X
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->origin().x;
+ else
+ $$ = $1.x;
+ }
+ | place DOT_Y
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->origin().y;
+ else
+ $$ = $1.y;
+ }
+ | place DOT_HT
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->height();
+ else
+ $$ = 0.0;
+ }
+ | place DOT_WID
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->width();
+ else
+ $$ = 0.0;
+ }
+ | place DOT_RAD
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->radius();
+ else
+ $$ = 0.0;
+ }
+ | expr '+' expr
+ { $$ = $1 + $3; }
+ | expr '-' expr
+ { $$ = $1 - $3; }
+ | expr '*' expr
+ { $$ = $1 * $3; }
+ | expr '/' expr
+ {
+ if ($3 == 0.0) {
+ lex_error("division by zero");
+ YYABORT;
+ }
+ $$ = $1/$3;
+ }
+ | expr '%' expr
+ {
+ if ($3 == 0.0) {
+ lex_error("modulus by zero");
+ YYABORT;
+ }
+ $$ = fmod($1, $3);
+ }
+ | expr '^' expr
+ {
+ errno = 0;
+ $$ = pow($1, $3);
+ if (errno == EDOM) {
+ lex_error("arguments to `^' operator out of domain");
+ YYABORT;
+ }
+ if (errno == ERANGE) {
+ lex_error("result of `^' operator out of range");
+ YYABORT;
+ }
+ }
+ | '-' expr %prec '!'
+ { $$ = -$2; }
+ | '(' any_expr ')'
+ { $$ = $2; }
+ | SIN '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = sin($3);
+ if (errno == ERANGE) {
+ lex_error("sin result out of range");
+ YYABORT;
+ }
+ }
+ | COS '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = cos($3);
+ if (errno == ERANGE) {
+ lex_error("cos result out of range");
+ YYABORT;
+ }
+ }
+ | ATAN2 '(' any_expr ',' any_expr ')'
+ {
+ errno = 0;
+ $$ = atan2($3, $5);
+ if (errno == EDOM) {
+ lex_error("atan2 argument out of domain");
+ YYABORT;
+ }
+ if (errno == ERANGE) {
+ lex_error("atan2 result out of range");
+ YYABORT;
+ }
+ }
+ | LOG '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = log10($3);
+ if (errno == ERANGE) {
+ lex_error("log result out of range");
+ YYABORT;
+ }
+ }
+ | EXP '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = pow(10.0, $3);
+ if (errno == ERANGE) {
+ lex_error("exp result out of range");
+ YYABORT;
+ }
+ }
+ | SQRT '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = sqrt($3);
+ if (errno == EDOM) {
+ lex_error("sqrt argument out of domain");
+ YYABORT;
+ }
+ }
+ | K_MAX '(' any_expr ',' any_expr ')'
+ { $$ = $3 > $5 ? $3 : $5; }
+ | K_MIN '(' any_expr ',' any_expr ')'
+ { $$ = $3 < $5 ? $3 : $5; }
+ | INT '(' any_expr ')'
+ { $$ = floor($3); }
+ | RAND '(' any_expr ')'
+ { $$ = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*$3); }
+ | RAND '(' ')'
+ {
+ /* return a random number in the range [0,1) */
+ /* portable, but not very random */
+ $$ = (rand() & 0x7fff) / double(0x8000);
+ }
+ | expr '<' expr
+ { $$ = ($1 < $3); }
+ | expr LESSEQUAL expr
+ { $$ = ($1 <= $3); }
+ | expr '>' expr
+ { $$ = ($1 > $3); }
+ | expr GREATEREQUAL expr
+ { $$ = ($1 >= $3); }
+ | expr EQUALEQUAL expr
+ { $$ = ($1 == $3); }
+ | expr NOTEQUAL expr
+ { $$ = ($1 != $3); }
+ | expr ANDAND expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | expr OROR expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | '!' expr
+ { $$ = ($2 == 0.0); }
+
+ ;
+
+%%
+
+/* bison defines const to be empty unless __STDC__ is defined, which it
+isn't under cfront */
+
+#ifdef const
+#undef const
+#endif
+
+static struct {
+ const char *name;
+ double val;
+ int scaled; // non-zero if val should be multiplied by scale
+} defaults_table[] = {
+ "arcrad", .25, 1,
+ "arrowht", .1, 1,
+ "arrowwid", .05, 1,
+ "circlerad", .25, 1,
+ "boxht", .5, 1,
+ "boxwid", .75, 1,
+ "boxrad", 0.0, 1,
+ "dashwid", .05, 1,
+ "ellipseht", .5, 1,
+ "ellipsewid", .75, 1,
+ "moveht", .5, 1,
+ "movewid", .5, 1,
+ "lineht", .5, 1,
+ "linewid", .5, 1,
+ "textht", 0.0, 1,
+ "textwid", 0.0, 1,
+ "scale", 1.0, 0,
+ "linethick", -1.0, 0, // in points
+ "fillval", .5, 0,
+ "arrowhead", 1.0, 0,
+ "maxpswid", 8.5, 0,
+ "maxpsht", 11.0, 0,
+};
+
+place *lookup_label(const char *label)
+{
+ saved_state *state = current_saved_state;
+ PTABLE(place) *tbl = current_table;
+ for (;;) {
+ place *pl = tbl->lookup(label);
+ if (pl)
+ return pl;
+ if (!state)
+ return 0;
+ tbl = state->tbl;
+ state = state->prev;
+ }
+}
+
+void define_label(const char *label, const place *pl)
+{
+ place *p = new place;
+ *p = *pl;
+ current_table->define(label, p);
+}
+
+int lookup_variable(const char *name, double *val)
+{
+ place *pl = lookup_label(name);
+ if (pl) {
+ *val = pl->x;
+ return 1;
+ }
+ return 0;
+}
+
+void define_variable(const char *name, double val)
+{
+ place *p = new place;
+ p->obj = 0;
+ p->x = val;
+ p->y = 0.0;
+ current_table->define(name, p);
+ if (strcmp(name, "scale") == 0) {
+ // When the scale changes, reset all scaled pre-defined variables to
+ // their default values.
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (defaults_table[i].scaled)
+ define_variable(defaults_table[i].name, val*defaults_table[i].val);
+ }
+}
+
+// called once only (not once per parse)
+
+void parse_init()
+{
+ current_direction = RIGHT_DIRECTION;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+ // This resets everything to its default value.
+ reset_all();
+}
+
+void reset(const char *nm)
+{
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (strcmp(nm, defaults_table[i].name) == 0) {
+ double val = defaults_table[i].val;
+ if (defaults_table[i].scaled) {
+ double scale;
+ lookup_variable("scale", &scale);
+ val *= scale;
+ }
+ define_variable(defaults_table[i].name, val);
+ return;
+ }
+ lex_error("`%1' is not a predefined variable", nm);
+}
+
+void reset_all()
+{
+ // We only have to explicitly reset the pre-defined variables that
+ // aren't scaled because `scale' is not scaled, and changing the
+ // value of `scale' will reset all the pre-defined variables that
+ // are scaled.
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (!defaults_table[i].scaled)
+ define_variable(defaults_table[i].name, defaults_table[i].val);
+}
+
+// called after each parse
+
+void parse_cleanup()
+{
+ while (current_saved_state != 0) {
+ delete current_table;
+ current_table = current_saved_state->tbl;
+ saved_state *tem = current_saved_state;
+ current_saved_state = current_saved_state->prev;
+ delete tem;
+ }
+ assert(current_table == &top_table);
+ PTABLE_ITERATOR(place) iter(current_table);
+ const char *key;
+ place *pl;
+ while (iter.next(&key, &pl))
+ if (pl->obj != 0) {
+ position pos = pl->obj->origin();
+ pl->obj = 0;
+ pl->x = pos.x;
+ pl->y = pos.y;
+ }
+ while (olist.head != 0) {
+ object *tem = olist.head;
+ olist.head = olist.head->next;
+ delete tem;
+ }
+ olist.tail = 0;
+ current_direction = RIGHT_DIRECTION;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+}
+
+const char *ordinal_postfix(int n)
+{
+ if (n < 10 || n > 20)
+ switch (n % 10) {
+ case 1:
+ return "st";
+ case 2:
+ return "nd";
+ case 3:
+ return "rd";
+ }
+ return "th";
+}
+
+const char *object_type_name(object_type type)
+{
+ switch (type) {
+ case BOX_OBJECT:
+ return "box";
+ case CIRCLE_OBJECT:
+ return "circle";
+ case ELLIPSE_OBJECT:
+ return "ellipse";
+ case ARC_OBJECT:
+ return "arc";
+ case SPLINE_OBJECT:
+ return "spline";
+ case LINE_OBJECT:
+ return "line";
+ case ARROW_OBJECT:
+ return "arrow";
+ case MOVE_OBJECT:
+ return "move";
+ case TEXT_OBJECT:
+ return "\"\"";
+ case BLOCK_OBJECT:
+ return "[]";
+ case OTHER_OBJECT:
+ case MARK_OBJECT:
+ default:
+ break;
+ }
+ return "object";
+}
+
+static char sprintf_buf[1024];
+
+char *format_number(const char *form, double n)
+{
+ if (form == 0)
+ form = "%g";
+ else {
+ // this is a fairly feeble attempt at validation of the format
+ int nspecs = 0;
+ for (const char *p = form; *p != '\0'; p++)
+ if (*p == '%') {
+ if (p[1] == '%')
+ p++;
+ else
+ nspecs++;
+ }
+ if (nspecs > 1) {
+ lex_error("bad format `%1'", form);
+ return strsave(form);
+ }
+ }
+ sprintf(sprintf_buf, form, n);
+ return strsave(sprintf_buf);
+}
+
+char *do_sprintf(const char *form, const double *v, int nv)
+{
+ string result;
+ int i = 0;
+ string one_format;
+ while (*form) {
+ if (*form == '%') {
+ one_format += *form++;
+ for (; *form != '\0' && strchr("#-+ 0123456789.", *form) != 0; form++)
+ one_format += *form;
+ if (*form == '\0' || strchr("eEfgG%", *form) == 0) {
+ lex_error("bad sprintf format");
+ result += one_format;
+ result += form;
+ break;
+ }
+ if (*form == '%') {
+ one_format += *form++;
+ one_format += '\0';
+ sprintf(sprintf_buf, one_format.contents());
+ }
+ else {
+ if (i >= nv) {
+ lex_error("too few arguments to sprintf");
+ result += one_format;
+ result += form;
+ break;
+ }
+ one_format += *form++;
+ one_format += '\0';
+ sprintf(sprintf_buf, one_format.contents(), v[i++]);
+ }
+ one_format.clear();
+ result += sprintf_buf;
+ }
+ else
+ result += *form++;
+ }
+ result += '\0';
+ return strsave(result.contents());
+}
diff --git a/gnu/usr.bin/groff/pic/position.h b/gnu/usr.bin/groff/pic/position.h
new file mode 100644
index 000000000000..6706fb1dda59
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/position.h
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct place;
+struct position {
+ double x;
+ double y;
+ position(double, double );
+ position();
+ position(const place &);
+ position &operator+=(const position &);
+ position &operator-=(const position &);
+ position &operator*=(double);
+ position &operator/=(double);
+};
+
+position operator-(const position &);
+position operator+(const position &, const position &);
+position operator-(const position &, const position &);
+position operator/(const position &, double);
+position operator*(const position &, double);
+// dot product
+double operator*(const position &, const position &);
+int operator==(const position &, const position &);
+int operator!=(const position &, const position &);
+
+double hypot(const position &a);
+
+typedef position distance;
+
diff --git a/gnu/usr.bin/groff/pic/tex.cc b/gnu/usr.bin/groff/pic/tex.cc
new file mode 100644
index 000000000000..d0fd962a646f
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/tex.cc
@@ -0,0 +1,411 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "pic.h"
+
+#ifdef TEX_SUPPORT
+
+#include "common.h"
+
+class tex_output : public common_output {
+public:
+ tex_output();
+ ~tex_output();
+ void start_picture(double, const position &ll, const position &ur);
+ void finish_picture();
+ void text(const position &, text_piece *, int, double);
+ void line(const position &, const position *, int n,
+ const line_type &);
+ void polygon(const position *, int n,
+ const line_type &, double);
+ void spline(const position &, const position *, int n,
+ const line_type &);
+ void arc(const position &, const position &, const position &,
+ const line_type &);
+ void circle(const position &, double rad, const line_type &, double);
+ void ellipse(const position &, const distance &, const line_type &, double);
+ void command(const char *, const char *, int);
+ int supports_filled_polygons();
+private:
+ position upper_left;
+ double height;
+ double width;
+ double scale;
+ double pen_size;
+
+ void point(const position &);
+ void dot(const position &, const line_type &);
+ void solid_arc(const position &cent, double rad, double start_angle,
+ double end_angle, const line_type &lt);
+ position transform(const position &);
+protected:
+ virtual void set_pen_size(double ps);
+};
+
+// convert inches to milliinches
+
+inline int milliinches(double x)
+{
+ return int(x*1000.0 + .5);
+}
+
+inline position tex_output::transform(const position &pos)
+{
+ return position((pos.x - upper_left.x)/scale,
+ (upper_left.y - pos.y)/scale);
+}
+
+output *make_tex_output()
+{
+ return new tex_output;
+}
+
+tex_output::tex_output()
+{
+}
+
+tex_output::~tex_output()
+{
+}
+
+const int DEFAULT_PEN_SIZE = 8;
+
+void tex_output::set_pen_size(double ps)
+{
+ if (ps < 0.0)
+ ps = -1.0;
+ if (ps != pen_size) {
+ pen_size = ps;
+ printf(" \\special{pn %d}%%\n",
+ ps < 0.0 ? DEFAULT_PEN_SIZE : int(ps*(1000.0/72.0) + .5));
+ }
+}
+
+void tex_output::start_picture(double sc, const position &ll,
+ const position &ur)
+{
+ upper_left.x = ll.x;
+ upper_left.y = ur.y;
+ scale = compute_scale(sc, ll, ur);
+ height = (ur.y - ll.y)/scale;
+ width = (ur.x - ll.x)/scale;
+ /* the point of \vskip 0pt is to ensure that the vtop gets
+ a height of 0 rather than the height of the hbox; this
+ might be non-zero if text from text attributes lies outside pic's
+ idea of the bounding box of the picture. */
+ fputs("\\expandafter\\ifx\\csname graph\\endcsname\\relax \\csname newbox\\endcsname\\graph\\fi\n"
+ "\\expandafter\\ifx\\csname graphtemp\\endcsname\\relax \\csname newdimen\\endcsname\\graphtemp\\fi\n"
+ "\\setbox\\graph=\\vtop{\\vskip 0pt\\hbox{%\n",
+ stdout);
+ pen_size = -2.0;
+}
+
+void tex_output::finish_picture()
+{
+ printf(" \\hbox{\\vrule depth%.3fin width0pt height 0pt}%%\n"
+ " \\kern %.3fin\n"
+ " }%%\n"
+ "}%%\n",
+ height, width);
+}
+
+void tex_output::text(const position &center, text_piece *v, int n, double)
+{
+ position c = transform(center);
+ for (int i = 0; i < n; i++)
+ if (v[i].text != 0 && *v[i].text != '\0') {
+ int j = 2*i - n + 1;
+ if (v[i].adj.v == ABOVE_ADJUST)
+ j--;
+ else if (v[i].adj.v == BELOW_ADJUST)
+ j++;
+ if (j == 0) {
+ printf(" \\graphtemp=.5ex\\advance\\graphtemp by %.3fin\n", c.y);
+ }
+ else {
+ printf(" \\graphtemp=\\baselineskip"
+ "\\multiply\\graphtemp by %d"
+ "\\divide\\graphtemp by 2\n"
+ " \\advance\\graphtemp by .5ex"
+ "\\advance\\graphtemp by %.3fin\n",
+ j, c.y);
+ }
+ printf(" \\rlap{\\kern %.3fin\\lower\\graphtemp", c.x);
+ fputs("\\hbox to 0pt{", stdout);
+ if (v[i].adj.h != LEFT_ADJUST)
+ fputs("\\hss ", stdout);
+ fputs(v[i].text, stdout);
+ if (v[i].adj.h != RIGHT_ADJUST)
+ fputs("\\hss", stdout);
+ fputs("}}%\n", stdout);
+ }
+}
+
+void tex_output::point(const position &pos)
+{
+ position p = transform(pos);
+ printf(" \\special{pa %d %d}%%\n", milliinches(p.x), milliinches(p.y));
+}
+
+void tex_output::line(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ set_pen_size(lt.thickness);
+ point(start);
+ for (int i = 0; i < n; i++)
+ point(v[i]);
+ fputs(" \\special{", stdout);
+ switch(lt.type) {
+ case line_type::invisible:
+ fputs("ip", stdout);
+ break;
+ case line_type::solid:
+ fputs("fp", stdout);
+ break;
+ case line_type::dotted:
+ printf("dt %.3f", lt.dash_width/scale);
+ break;
+ case line_type::dashed:
+ printf("da %.3f", lt.dash_width/scale);
+ break;
+ }
+ fputs("}%\n", stdout);
+}
+
+void tex_output::polygon(const position *v, int n,
+ const line_type &lt, double fill)
+{
+ if (fill >= 0.0) {
+ if (fill > 1.0)
+ fill = 1.0;
+ printf(" \\special{sh %.3f}%%\n", fill);
+ }
+ line(v[n-1], v, n, lt);
+}
+
+void tex_output::spline(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ if (lt.type == line_type::invisible)
+ return;
+ set_pen_size(lt.thickness);
+ point(start);
+ for (int i = 0; i < n; i++)
+ point(v[i]);
+ fputs(" \\special{sp", stdout);
+ switch(lt.type) {
+ case line_type::solid:
+ break;
+ case line_type::dotted:
+ printf(" %.3f", -lt.dash_width/scale);
+ break;
+ case line_type::dashed:
+ printf(" %.3f", lt.dash_width/scale);
+ break;
+ case line_type::invisible:
+ assert(0);
+ }
+ fputs("}%\n", stdout);
+}
+
+void tex_output::solid_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt)
+{
+ set_pen_size(lt.thickness);
+ position c = transform(cent);
+ printf(" \\special{ar %d %d %d %d %f %f}%%\n",
+ milliinches(c.x),
+ milliinches(c.y),
+ milliinches(rad/scale),
+ milliinches(rad/scale),
+ -end_angle,
+ (-end_angle > -start_angle) ? M_PI * 2 - start_angle : -start_angle);
+}
+
+void tex_output::arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_arc(start, cent, end, lt);
+ break;
+ case line_type::dotted:
+ dotted_arc(start, cent, end, lt);
+ break;
+ case line_type::solid:
+ {
+ position c;
+ if (!compute_arc_center(start, cent, end, &c)) {
+ line(start, &end, 1, lt);
+ break;
+ }
+ solid_arc(c,
+ hypot(cent - start),
+ atan2(start.y - c.y, start.x - c.x),
+ atan2(end.y - c.y, end.x - c.x),
+ lt);
+ break;
+ }
+ }
+}
+
+void tex_output::circle(const position &cent, double rad,
+ const line_type &lt, double fill)
+{
+ if (fill >= 0.0 && lt.type != line_type::solid) {
+ if (fill > 1.0)
+ fill = 1.0;
+ line_type ilt;
+ ilt.type = line_type::invisible;
+ ellipse(cent, position(rad*2.0, rad*2.0), ilt, fill);
+ }
+ switch (lt.type) {
+ case line_type::dashed:
+ dashed_circle(cent, rad, lt);
+ break;
+ case line_type::invisible:
+ break;
+ case line_type::solid:
+ ellipse(cent, position(rad*2.0,rad*2.0), lt, fill);
+ break;
+ case line_type::dotted:
+ dotted_circle(cent, rad, lt);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void tex_output::ellipse(const position &cent, const distance &dim,
+ const line_type &lt, double fill)
+{
+ if (lt.type == line_type::invisible) {
+ if (fill < 0.0)
+ return;
+ }
+ else
+ set_pen_size(lt.thickness);
+ if (fill >= 0.0) {
+ if (fill > 1.0)
+ fill = 1.0;
+ printf(" \\special{sh %.3f}%%\n", fill);
+ }
+ position c = transform(cent);
+ printf(" \\special{%s %d %d %d %d 0 6.28319}%%\n",
+ (lt.type == line_type::invisible ? "ia" : "ar"),
+ milliinches(c.x),
+ milliinches(c.y),
+ milliinches(dim.x/(2.0*scale)),
+ milliinches(dim.y/(2.0*scale)));
+}
+
+void tex_output::command(const char *s, const char *, int)
+{
+ fputs(s, stdout);
+ putchar('%'); // avoid unwanted spaces
+ putchar('\n');
+}
+
+int tex_output::supports_filled_polygons()
+{
+ return 1;
+}
+
+void tex_output::dot(const position &pos, const line_type &lt)
+{
+ if (zero_length_line_flag) {
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ line(pos, &pos, 1, slt);
+ }
+ else {
+ int dot_rad = int(lt.thickness*(1000.0/(72.0*2)) + .5);
+ if (dot_rad == 0)
+ dot_rad = 1;
+ position p = transform(pos);
+ printf(" \\special{sh 1}%%\n"
+ " \\special{ia %d %d %d %d 0 6.28319}%%\n",
+ milliinches(p.x), milliinches(p.y), dot_rad, dot_rad);
+ }
+}
+
+class tpic_output : public tex_output {
+public:
+ tpic_output();
+ void command(const char *, const char *, int);
+private:
+ void set_pen_size(double ps);
+ int default_pen_size;
+ int prev_default_pen_size;
+};
+
+tpic_output::tpic_output()
+: default_pen_size(DEFAULT_PEN_SIZE), prev_default_pen_size(DEFAULT_PEN_SIZE)
+{
+}
+
+void tpic_output::command(const char *s, const char *filename, int lineno)
+{
+ assert(s[0] == '.');
+ if (s[1] == 'p' && s[2] == 's' && (s[3] == '\0' || !csalpha(s[3]))) {
+ const char *p = s + 3;
+ while (csspace(*p))
+ p++;
+ if (*p == '\0') {
+ int temp = default_pen_size;
+ default_pen_size = prev_default_pen_size;
+ prev_default_pen_size = temp;
+ }
+ else {
+ char *ptr;
+ int temp = (int)strtol(p, &ptr, 10);
+ if (temp == 0 && ptr == p)
+ error_with_file_and_line(filename, lineno,
+ "argument to `.ps' not an integer");
+ else if (temp < 0)
+ error_with_file_and_line(filename, lineno,
+ "negative pen size");
+ else {
+ prev_default_pen_size = default_pen_size;
+ default_pen_size = temp;
+ }
+ }
+ }
+ else
+ printf("\\%s%%\n", s + 1);
+}
+
+void tpic_output::set_pen_size(double ps)
+{
+ if (ps < 0.0)
+ printf(" \\special{pn %d}%%\n", default_pen_size);
+ else
+ tex_output::set_pen_size(ps);
+}
+
+output *make_tpic_output()
+{
+ return new tpic_output;
+}
+
+#endif
diff --git a/gnu/usr.bin/groff/pic/text.h b/gnu/usr.bin/groff/pic/text.h
new file mode 100644
index 000000000000..f9d34875075f
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/text.h
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+
+enum hadjustment {
+ CENTER_ADJUST,
+ LEFT_ADJUST,
+ RIGHT_ADJUST
+ };
+
+enum vadjustment {
+ NONE_ADJUST,
+ ABOVE_ADJUST,
+ BELOW_ADJUST
+ };
+
+struct adjustment {
+ hadjustment h;
+ vadjustment v;
+};
+
+struct text_piece {
+ char *text;
+ adjustment adj;
+ const char *filename;
+ int lineno;
+
+ text_piece();
+ ~text_piece();
+};
diff --git a/gnu/usr.bin/groff/pic/troff.cc b/gnu/usr.bin/groff/pic/troff.cc
new file mode 100644
index 000000000000..2b6d0d7b8924
--- /dev/null
+++ b/gnu/usr.bin/groff/pic/troff.cc
@@ -0,0 +1,499 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "pic.h"
+#include "common.h"
+
+
+const double RELATIVE_THICKNESS = -1.0;
+const double BAD_THICKNESS = -2.0;
+
+class simple_output : public common_output {
+ virtual void simple_line(const position &, const position &) = 0;
+ virtual void simple_spline(const position &, const position *, int n) = 0;
+ virtual void simple_arc(const position &, const position &,
+ const position &) = 0;
+ virtual void simple_circle(int, const position &, double rad) = 0;
+ virtual void simple_ellipse(int, const position &, const distance &) = 0;
+ virtual void simple_polygon(int, const position *, int) = 0;
+ virtual void line_thickness(double) = 0;
+ virtual void set_fill(double) = 0;
+ void dot(const position &, const line_type &) = 0;
+public:
+ void start_picture(double sc, const position &ll, const position &ur) = 0;
+ void finish_picture() = 0;
+ void text(const position &, text_piece *, int, double) = 0;
+ void line(const position &, const position *, int n,
+ const line_type &);
+ void polygon(const position *, int n,
+ const line_type &, double);
+ void spline(const position &, const position *, int n,
+ const line_type &);
+ void arc(const position &, const position &, const position &,
+ const line_type &);
+ void circle(const position &, double rad, const line_type &, double);
+ void ellipse(const position &, const distance &, const line_type &, double);
+ int supports_filled_polygons();
+};
+
+int simple_output::supports_filled_polygons()
+{
+ return driver_extension_flag != 0;
+}
+
+void simple_output::arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ switch (lt.type) {
+ case line_type::solid:
+ line_thickness(lt.thickness);
+ simple_arc(start, cent, end);
+ break;
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_arc(start, cent, end, lt);
+ break;
+ case line_type::dotted:
+ dotted_arc(start, cent, end, lt);
+ break;
+ }
+}
+
+void simple_output::line(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ position pos = start;
+ line_thickness(lt.thickness);
+ for (int i = 0; i < n; i++) {
+ switch (lt.type) {
+ case line_type::solid:
+ simple_line(pos, v[i]);
+ break;
+ case line_type::dotted:
+ {
+ distance vec(v[i] - pos);
+ double dist = hypot(vec);
+ int ndots = int(dist/lt.dash_width + .5);
+ if (ndots == 0)
+ dot(pos, lt);
+ else {
+ vec /= double(ndots);
+ for (int j = 0; j <= ndots; j++)
+ dot(pos + vec*j, lt);
+ }
+ }
+ break;
+ case line_type::dashed:
+ {
+ distance vec(v[i] - pos);
+ double dist = hypot(vec);
+ if (dist <= lt.dash_width*2.0)
+ simple_line(pos, v[i]);
+ else {
+ int ndashes = int((dist - lt.dash_width)/(lt.dash_width*2.0) + .5);
+ distance dash_vec = vec*(lt.dash_width/dist);
+ double dash_gap = (dist - lt.dash_width)/ndashes;
+ distance dash_gap_vec = vec*(dash_gap/dist);
+ for (int j = 0; j <= ndashes; j++) {
+ position s(pos + dash_gap_vec*j);
+ simple_line(s, s + dash_vec);
+ }
+ }
+ }
+ break;
+ case line_type::invisible:
+ break;
+ default:
+ assert(0);
+ }
+ pos = v[i];
+ }
+}
+
+void simple_output::spline(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ line_thickness(lt.thickness);
+ simple_spline(start, v, n);
+}
+
+void simple_output::polygon(const position *v, int n,
+ const line_type &lt, double fill)
+{
+ if (driver_extension_flag) {
+ if (fill >= 0.0) {
+ set_fill(fill);
+ simple_polygon(1, v, n);
+ }
+ }
+ if (lt.type == line_type::solid && driver_extension_flag) {
+ line_thickness(lt.thickness);
+ simple_polygon(0, v, n);
+ }
+ else if (lt.type != line_type::invisible) {
+ line_thickness(lt.thickness);
+ line(v[n - 1], v, n, lt);
+ }
+}
+
+void simple_output::circle(const position &cent, double rad,
+ const line_type &lt, double fill)
+{
+ if (driver_extension_flag && fill >= 0.0) {
+ set_fill(fill);
+ simple_circle(1, cent, rad);
+ }
+ line_thickness(lt.thickness);
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_circle(cent, rad, lt);
+ break;
+ case line_type::dotted:
+ dotted_circle(cent, rad, lt);
+ break;
+ case line_type::solid:
+ simple_circle(0, cent, rad);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void simple_output::ellipse(const position &cent, const distance &dim,
+ const line_type &lt, double fill)
+{
+ if (driver_extension_flag && fill >= 0.0) {
+ set_fill(fill);
+ simple_ellipse(1, cent, dim);
+ }
+ if (lt.type != line_type::invisible)
+ line_thickness(lt.thickness);
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dotted:
+ case line_type::dashed:
+ case line_type::solid:
+ simple_ellipse(0, cent, dim);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+#define FILL_MAX 1000
+
+class troff_output : public simple_output {
+ const char *last_filename;
+ position upper_left;
+ double height;
+ double scale;
+ double last_line_thickness;
+ double last_fill;
+public:
+ troff_output();
+ ~troff_output();
+ void start_picture(double, const position &ll, const position &ur);
+ void finish_picture();
+ void text(const position &, text_piece *, int, double);
+ void dot(const position &, const line_type &);
+ void command(const char *, const char *, int);
+ void set_location(const char *, int);
+ void simple_line(const position &, const position &);
+ void simple_spline(const position &, const position *, int n);
+ void simple_arc(const position &, const position &, const position &);
+ void simple_circle(int, const position &, double rad);
+ void simple_ellipse(int, const position &, const distance &);
+ void simple_polygon(int, const position *, int);
+ void line_thickness(double p);
+ void set_fill(double);
+ position transform(const position &);
+};
+
+output *make_troff_output()
+{
+ return new troff_output;
+}
+
+troff_output::troff_output()
+: last_filename(0), last_line_thickness(BAD_THICKNESS), last_fill(-1.0)
+{
+}
+
+troff_output::~troff_output()
+{
+}
+
+inline position troff_output::transform(const position &pos)
+{
+ return position((pos.x - upper_left.x)/scale,
+ (upper_left.y - pos.y)/scale);
+}
+
+#define FILL_REG "00"
+
+// If this register > 0, then pic will generate \X'ps: ...' commands
+// if the aligned attribute is used.
+#define GROPS_REG "0p"
+
+// If this register is defined, geqn won't produce `\x's.
+#define EQN_NO_EXTRA_SPACE_REG "0x"
+
+void troff_output::start_picture(double sc,
+ const position &ll, const position &ur)
+{
+ upper_left.x = ll.x;
+ upper_left.y = ur.y;
+ scale = compute_scale(sc, ll, ur);
+ height = (ur.y - ll.y)/scale;
+ double width = (ur.x - ll.x)/scale;
+ printf(".PS %.3fi %.3fi", height, width);
+ if (args)
+ printf(" %s\n", args);
+ else
+ putchar('\n');
+ printf(".\\\" %g %g %g %g\n", ll.x, ll.y, ur.x, ur.y);
+ printf(".\\\" %.3fi %.3fi %.3fi %.3fi\n", 0.0, height, width, 0.0);
+ printf(".nr " FILL_REG " \\n(.u\n.nf\n");
+ printf(".nr " EQN_NO_EXTRA_SPACE_REG " 1\n");
+ // This guarantees that if the picture is used in a diversion it will
+ // have the right width.
+ printf("\\h'%.3fi'\n.sp -1\n", width);
+}
+
+void troff_output::finish_picture()
+{
+ line_thickness(BAD_THICKNESS);
+ last_fill = -1.0; // force it to be reset for each picture
+ if (!flyback_flag)
+ printf(".sp %.3fi+1\n", height);
+ printf(".if \\n(" FILL_REG " .fi\n");
+ printf(".br\n");
+ printf(".nr " EQN_NO_EXTRA_SPACE_REG " 0\n");
+ // this is a little gross
+ set_location(current_filename, current_lineno);
+ fputs(flyback_flag ? ".PF\n" : ".PE\n", stdout);
+}
+
+void troff_output::command(const char *s,
+ const char *filename, int lineno)
+{
+ if (filename != 0)
+ set_location(filename, lineno);
+ fputs(s, stdout);
+ putchar('\n');
+}
+
+void troff_output::simple_circle(int filled, const position &cent, double rad)
+{
+ position c = transform(cent);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'%c%.3fi'"
+ "\n.sp -1\n",
+ c.x - rad/scale,
+ c.y,
+ (filled ? 'C' : 'c'),
+ rad*2.0/scale);
+}
+
+void troff_output::simple_ellipse(int filled, const position &cent,
+ const distance &dim)
+{
+ position c = transform(cent);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'%c%.3fi %.3fi'"
+ "\n.sp -1\n",
+ c.x - dim.x/(2.0*scale),
+ c.y,
+ (filled ? 'E' : 'e'),
+ dim.x/scale, dim.y/scale);
+}
+
+void troff_output::simple_arc(const position &start, const distance &cent,
+ const distance &end)
+{
+ position s = transform(start);
+ position c = transform(cent);
+ distance cv = c - s;
+ distance ev = transform(end) - c;
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'a%.3fi %.3fi %.3fi %.3fi'"
+ "\n.sp -1\n",
+ s.x, s.y, cv.x, cv.y, ev.x, ev.y);
+}
+
+void troff_output::simple_line(const position &start, const position &end)
+{
+ position s = transform(start);
+ distance ev = transform(end) - s;
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'l%.3fi %.3fi'"
+ "\n.sp -1\n",
+ s.x, s.y, ev.x, ev.y);
+}
+
+void troff_output::simple_spline(const position &start,
+ const position *v, int n)
+{
+ position pos = transform(start);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'",
+ pos.x, pos.y);
+ fputs("\\D'~", stdout);
+ for (int i = 0; i < n; i++) {
+ position temp = transform(v[i]);
+ distance d = temp - pos;
+ pos = temp;
+ if (i != 0)
+ putchar(' ');
+ printf("%.3fi %.3fi", d.x, d.y);
+ }
+ printf("'\n.sp -1\n");
+}
+
+// a solid polygon
+
+void troff_output::simple_polygon(int filled, const position *v, int n)
+{
+ position pos = transform(v[0]);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'",
+ pos.x, pos.y);
+ printf("\\D'%c", (filled ? 'P' : 'p'));
+ for (int i = 1; i < n; i++) {
+ position temp = transform(v[i]);
+ distance d = temp - pos;
+ pos = temp;
+ if (i != 1)
+ putchar(' ');
+ printf("%.3fi %.3fi", d.x, d.y);
+ }
+ printf("'\n.sp -1\n");
+}
+
+const double TEXT_AXIS = 0.22; // in ems
+
+static const char *choose_delimiter(const char *text)
+{
+ if (strchr(text, '\'') == 0)
+ return "'";
+ else
+ return "\\(ts";
+}
+
+void troff_output::text(const position &center, text_piece *v, int n,
+ double ang)
+{
+ int rotate_flag = 0;
+ if (driver_extension_flag && ang != 0.0) {
+ rotate_flag = 1;
+ position c = transform(center);
+ printf(".if \\n(" GROPS_REG " \\{\\\n"
+ "\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\X'ps: exec gsave currentpoint 2 copy translate %.4f rotate neg exch neg exch translate'"
+ "\n.sp -1\n"
+ ".\\}\n",
+ c.x, c.y, -ang*180.0/M_PI);
+ }
+ for (int i = 0; i < n; i++)
+ if (v[i].text != 0 && *v[i].text != '\0') {
+ position c = transform(center);
+ if (v[i].filename != 0)
+ set_location(v[i].filename, v[i].lineno);
+ printf("\\h'%.3fi", c.x);
+ const char *delim = choose_delimiter(v[i].text);
+ if (v[i].adj.h == RIGHT_ADJUST)
+ printf("-\\w%s%s%su", delim, v[i].text, delim);
+ else if (v[i].adj.h != LEFT_ADJUST)
+ printf("-(\\w%s%s%su/2u)", delim, v[i].text, delim);
+ putchar('\'');
+ printf("\\v'%.3fi-(%dv/2u)+%dv+%.2fm",
+ c.y,
+ n - 1,
+ i,
+ TEXT_AXIS);
+ if (v[i].adj.v == ABOVE_ADJUST)
+ printf("-.5v");
+ else if (v[i].adj.v == BELOW_ADJUST)
+ printf("+.5v");
+ putchar('\'');
+ fputs(v[i].text, stdout);
+ fputs("\n.sp -1\n", stdout);
+ }
+ if (rotate_flag)
+ printf(".if '\\*(.T'ps' \\{\\\n"
+ "\\X'ps: exec grestore'\n.sp -1\n"
+ ".\\}\n");
+}
+
+void troff_output::line_thickness(double p)
+{
+ if (p < 0.0)
+ p = RELATIVE_THICKNESS;
+ if (driver_extension_flag && p != last_line_thickness) {
+ printf("\\D't %.3fp'\\h'%.3fp'\n.sp -1\n", p, -p);
+ last_line_thickness = p;
+ }
+}
+
+void troff_output::set_fill(double f)
+{
+ if (driver_extension_flag && f != last_fill) {
+ printf("\\D'f %du'\\h'%du'\n.sp -1\n", int(f*FILL_MAX), -int(f*FILL_MAX));
+ last_fill = f;
+ }
+}
+
+const double DOT_AXIS = .044;
+
+void troff_output::dot(const position &cent, const line_type &lt)
+{
+ if (driver_extension_flag) {
+ line_thickness(lt.thickness);
+ simple_line(cent, cent);
+ }
+ else {
+ position c = transform(cent);
+ printf("\\h'%.3fi-(\\w'.'u/2u)'"
+ "\\v'%.3fi+%.2fm'"
+ ".\n.sp -1\n",
+ c.x,
+ c.y,
+ DOT_AXIS);
+ }
+}
+
+void troff_output::set_location(const char *s, int n)
+{
+ if (last_filename != 0 && strcmp(s, last_filename) == 0)
+ printf(".lf %d\n", n);
+ else {
+ printf(".lf %d %s\n", n, s);
+ last_filename = s;
+ }
+}
diff --git a/gnu/usr.bin/groff/psbb/Makefile b/gnu/usr.bin/groff/psbb/Makefile
new file mode 100644
index 000000000000..b382bfbc78c3
--- /dev/null
+++ b/gnu/usr.bin/groff/psbb/Makefile
@@ -0,0 +1,8 @@
+# Makefile for psbb
+
+PROG= psbb
+SRCS= psbb.c
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/psbb/psbb.1 b/gnu/usr.bin/groff/psbb/psbb.1
new file mode 100644
index 000000000000..f5da3eb157d1
--- /dev/null
+++ b/gnu/usr.bin/groff/psbb/psbb.1
@@ -0,0 +1,26 @@
+.\" -*- nroff -*-
+.TH PSBB 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+psbb \- extract bounding box from PostScript document
+.SH SYNOPSIS
+.B psbb
+.I file
+.SH DESCRIPTION
+psbb reads
+.I file
+which should be a PostScript document conforming to
+the Document Structuring conventions
+and looks for a
+.B %%BoundingBox
+comment.
+If it finds one,
+it prints a line
+.IP
+.I
+llx lly urx ury
+.LP
+on the standard output and exits with zero status.
+If it doesn't find such a line or if the line is invalid
+it prints a message and exits with non-zero status.
+.SH "SEE ALSO"
+.BR grops (1)
diff --git a/gnu/usr.bin/groff/psbb/psbb.c b/gnu/usr.bin/groff/psbb/psbb.c
new file mode 100644
index 000000000000..4df15621faf6
--- /dev/null
+++ b/gnu/usr.bin/groff/psbb/psbb.c
@@ -0,0 +1,169 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+struct bounding_box {
+ int llx, lly, urx, ury;
+};
+
+#ifdef __STDC__
+const char *do_file(FILE *, struct bounding_box *);
+int parse_bounding_box(char *, struct bounding_box *);
+#else
+#define const /* as nothing */
+const char *do_file();
+int parse_bounding_box();
+#endif
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ FILE *fp;
+ const char *message;
+ struct bounding_box bb;
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s filename\n", argv[0]);
+ exit(3);
+ }
+ errno = 0;
+ fp = fopen(argv[1], "r");
+ if (fp == NULL) {
+ fprintf(stderr, "%s: can't open `%s': ", argv[0], argv[1]);
+ perror((char *)NULL);
+ exit(2);
+ }
+ message = do_file(fp, &bb);
+ if (message) {
+ fprintf(stderr, "%s: ", argv[0]);
+ fprintf(stderr, message, argv[1]);
+ putc('\n', stderr);
+ exit(1);
+ }
+ printf("%d %d %d %d\n", bb.llx, bb.lly, bb.urx, bb.ury);
+ exit(0);
+}
+
+/* If the bounding box was found return NULL, and store the bounding box
+in bb. If the bounding box was not found return a string suitable for
+giving to printf with the filename as an argument saying why not. */
+
+const char *do_file(fp, bb)
+FILE *fp;
+struct bounding_box *bb;
+{
+ int bb_at_end = 0;
+ char buf[256];
+ if (!fgets(buf, sizeof(buf), fp))
+ return "%s is empty";
+ if (strncmp("%!PS-Adobe-", buf, 11) != 0)
+ return "%s is not conforming";
+ while (fgets(buf, sizeof(buf), fp) != 0) {
+ if (buf[0] != '%' || buf[1] != '%'
+ || strncmp(buf + 2, "EndComments", 11) == 0)
+ break;
+ if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
+ int res = parse_bounding_box(buf + 14, bb);
+ if (res == 1)
+ return NULL;
+ else if (res == 2) {
+ bb_at_end = 1;
+ break;
+ }
+ else
+ return "the arguments to the %%%%BoundingBox comment in %s are bad";
+ }
+ }
+ if (bb_at_end) {
+ long offset;
+ int last_try = 0;
+ /* in the trailer, the last BoundingBox comment is significant */
+ for (offset = 512; !last_try; offset *= 2) {
+ int had_trailer = 0;
+ int got_bb = 0;
+ if (offset > 32768 || fseek(fp, -offset, 2) == -1) {
+ last_try = 1;
+ if (fseek(fp, 0L, 0) == -1)
+ break;
+ }
+ while (fgets(buf, sizeof(buf), fp) != 0) {
+ if (buf[0] == '%' && buf[1] == '%') {
+ if (!had_trailer) {
+ if (strncmp(buf + 2, "Trailer", 7) == 0)
+ had_trailer = 1;
+ }
+ else {
+ if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
+ int res = parse_bounding_box(buf + 14, bb);
+ if (res == 1)
+ got_bb = 1;
+ else if (res == 2)
+ return "`(atend)' not allowed in trailer";
+ else
+ return "the arguments to the %%%%BoundingBox comment in %s are bad";
+ }
+ }
+ }
+ }
+ if (got_bb)
+ return NULL;
+ }
+ }
+ return "%%%%BoundingBox comment not found in %s";
+}
+
+/* Parse the argument to a %%BoundingBox comment. Return 1 if it
+contains 4 numbers, 2 if it contains (atend), 0 otherwise. */
+
+int parse_bounding_box(p, bb)
+char *p;
+struct bounding_box *bb;
+{
+ if (sscanf(p, "%d %d %d %d",
+ &bb->llx, &bb->lly, &bb->urx, &bb->ury) == 4)
+ return 1;
+ else {
+ /* The Document Structuring Conventions say that the numbers
+ should be integers. Unfortunately some broken applications
+ get this wrong. */
+ double x1, x2, x3, x4;
+ if (sscanf(p, "%lf %lf %lf %lf", &x1, &x2, &x3, &x4) == 4) {
+ bb->llx = (int)x1;
+ bb->lly = (int)x2;
+ bb->urx = (int)x3;
+ bb->ury = (int)x4;
+ return 1;
+ }
+ else {
+ for (; *p == ' ' || *p == '\t'; p++)
+ ;
+ if (strncmp(p, "(atend)", 7) == 0) {
+ return 2;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/gnu/usr.bin/groff/refer/Makefile b/gnu/usr.bin/groff/refer/Makefile
new file mode 100644
index 000000000000..af1d242e3f45
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/Makefile
@@ -0,0 +1,15 @@
+# Makefile for refer
+
+PROG= refer
+SRCS= command.cc ref.cc refer.cc token.cc
+OBJS= label.o
+CFLAGS+= -I. -I$(.CURDIR)/../include
+CXXFLAGS+= -I. -I$(.CURDIR)/../include
+LDADD+= $(LIBBIB) $(LIBGROFF) -lm
+DPADD+= $(LIBBIB) $(LIBGROFF) $(LIBMATH)
+
+CLEANFILES+= label.cc label.tab.h
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/refer/command.cc b/gnu/usr.bin/groff/refer/command.cc
new file mode 100644
index 000000000000..93b6cfe95e4b
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/command.cc
@@ -0,0 +1,807 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "refer.h"
+#include "refid.h"
+#include "search.h"
+#include "command.h"
+
+cset cs_field_name = csalpha;
+
+class input_item {
+ input_item *next;
+ char *filename;
+ int first_lineno;
+ string buffer;
+ const char *ptr;
+ const char *end;
+public:
+ input_item(string &, const char *, int = 1);
+ ~input_item();
+ int get_char();
+ int peek_char();
+ void skip_char();
+ int get_location(const char **, int *);
+
+ friend class input_stack;
+};
+
+input_item::input_item(string &s, const char *fn, int ln)
+: filename(strsave(fn)), first_lineno(ln)
+{
+ buffer.move(s);
+ ptr = buffer.contents();
+ end = ptr + buffer.length();
+}
+
+input_item::~input_item()
+{
+ a_delete filename;
+}
+
+inline int input_item::peek_char()
+{
+ if (ptr >= end)
+ return EOF;
+ else
+ return (unsigned char)*ptr;
+}
+
+inline int input_item::get_char()
+{
+ if (ptr >= end)
+ return EOF;
+ else
+ return (unsigned char)*ptr++;
+}
+
+inline void input_item::skip_char()
+{
+ ptr++;
+}
+
+int input_item::get_location(const char **filenamep, int *linenop)
+{
+ *filenamep = filename;
+ if (ptr == buffer.contents())
+ *linenop = first_lineno;
+ else {
+ int ln = first_lineno;
+ const char *e = ptr - 1;
+ for (const char *p = buffer.contents(); p < e; p++)
+ if (*p == '\n')
+ ln++;
+ *linenop = ln;
+ }
+ return 1;
+}
+
+class input_stack {
+ static input_item *top;
+public:
+ static void init();
+ static int get_char();
+ static int peek_char();
+ static void skip_char() { top->skip_char(); }
+ static void push_file(const char *);
+ static void push_string(string &, const char *, int);
+ static void error(const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+};
+
+input_item *input_stack::top = 0;
+
+void input_stack::init()
+{
+ while (top) {
+ input_item *tem = top;
+ top = top->next;
+ delete tem;
+ }
+}
+
+int input_stack::get_char()
+{
+ while (top) {
+ int c = top->get_char();
+ if (c >= 0)
+ return c;
+ input_item *tem = top;
+ top = top->next;
+ delete tem;
+ }
+ return -1;
+}
+
+int input_stack::peek_char()
+{
+ while (top) {
+ int c = top->peek_char();
+ if (c >= 0)
+ return c;
+ input_item *tem = top;
+ top = top->next;
+ delete tem;
+ }
+ return -1;
+}
+
+void input_stack::push_file(const char *fn)
+{
+ FILE *fp;
+ if (strcmp(fn, "-") == 0) {
+ fp = stdin;
+ fn = "<standard input>";
+ }
+ else {
+ errno = 0;
+ fp = fopen(fn, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", fn, strerror(errno));
+ return;
+ }
+ }
+ string buf;
+ int bol = 1;
+ int lineno = 1;
+ for (;;) {
+ int c = getc(fp);
+ if (bol && c == '.') {
+ // replace lines beginning with .R1 or .R2 with a blank line
+ c = getc(fp);
+ if (c == 'R') {
+ c = getc(fp);
+ if (c == '1' || c == '2') {
+ int cc = c;
+ c = getc(fp);
+ if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {
+ while (c != '\n' && c != EOF)
+ c = getc(fp);
+ }
+ else {
+ buf += '.';
+ buf += 'R';
+ buf += cc;
+ }
+ }
+ else {
+ buf += '.';
+ buf += 'R';
+ }
+ }
+ else
+ buf += '.';
+ }
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ error_with_file_and_line(fn, lineno,
+ "illegal input character code %1", int(c));
+ else {
+ buf += c;
+ if (c == '\n') {
+ bol = 1;
+ lineno++;
+ }
+ else
+ bol = 0;
+ }
+ }
+ if (fp != stdin)
+ fclose(fp);
+ if (buf.length() > 0 && buf[buf.length() - 1] != '\n')
+ buf += '\n';
+ input_item *it = new input_item(buf, fn);
+ it->next = top;
+ top = it;
+}
+
+void input_stack::push_string(string &s, const char *filename, int lineno)
+{
+ input_item *it = new input_item(s, filename, lineno);
+ it->next = top;
+ top = it;
+}
+
+void input_stack::error(const char *format, const errarg &arg1,
+ const errarg &arg2, const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ for (input_item *it = top; it; it = it->next)
+ if (it->get_location(&filename, &lineno)) {
+ error_with_file_and_line(filename, lineno, format, arg1, arg2, arg3);
+ return;
+ }
+ ::error(format, arg1, arg2, arg3);
+}
+
+void command_error(const char *format, const errarg &arg1,
+ const errarg &arg2, const errarg &arg3)
+{
+ input_stack::error(format, arg1, arg2, arg3);
+}
+
+// # not recognized in ""
+// \<newline> is recognized in ""
+// # does not conceal newline
+// if missing closing quote, word extends to end of line
+// no special treatment of \ other than before newline
+// \<newline> not recognized after #
+// ; allowed as alternative to newline
+// ; not recognized in ""
+// don't clear word_buffer; just append on
+// return -1 for EOF, 0 for newline, 1 for word
+
+int get_word(string &word_buffer)
+{
+ int c = input_stack::get_char();
+ for (;;) {
+ if (c == '#') {
+ do {
+ c = input_stack::get_char();
+ } while (c != '\n' && c != EOF);
+ break;
+ }
+ if (c == '\\' && input_stack::peek_char() == '\n')
+ input_stack::skip_char();
+ else if (c != ' ' && c != '\t')
+ break;
+ c = input_stack::get_char();
+ }
+ if (c == EOF)
+ return -1;
+ if (c == '\n' || c == ';')
+ return 0;
+ if (c == '"') {
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || c == '\n')
+ break;
+ input_stack::skip_char();
+ if (c == '"') {
+ int d = input_stack::peek_char();
+ if (d == '"')
+ input_stack::skip_char();
+ else
+ break;
+ }
+ else if (c == '\\') {
+ int d = input_stack::peek_char();
+ if (d == '\n')
+ input_stack::skip_char();
+ else
+ word_buffer += '\\';
+ }
+ else
+ word_buffer += c;
+ }
+ return 1;
+ }
+ word_buffer += c;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == ' ' || c == '\t' || c == '\n' || c == '#' || c == ';')
+ break;
+ input_stack::skip_char();
+ if (c == '\\') {
+ int d = input_stack::peek_char();
+ if (d == '\n')
+ input_stack::skip_char();
+ else
+ word_buffer += '\\';
+ }
+ else
+ word_buffer += c;
+ }
+ return 1;
+}
+
+union argument {
+ const char *s;
+ int n;
+};
+
+// This is for debugging.
+
+static void echo_command(int argc, argument *argv)
+{
+ for (int i = 0; i < argc; i++)
+ fprintf(stderr, "%s\n", argv[i].s);
+}
+
+static void include_command(int argc, argument *argv)
+{
+ assert(argc == 1);
+ input_stack::push_file(argv[0].s);
+}
+
+static void capitalize_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ capitalize_fields = argv[0].s;
+ else
+ capitalize_fields.clear();
+}
+
+static void accumulate_command(int, argument *)
+{
+ accumulate = 1;
+}
+
+static void no_accumulate_command(int, argument *)
+{
+ accumulate = 0;
+}
+
+static void move_punctuation_command(int, argument *)
+{
+ move_punctuation = 1;
+}
+
+static void no_move_punctuation_command(int, argument *)
+{
+ move_punctuation = 0;
+}
+
+static void sort_command(int argc, argument *argv)
+{
+ if (argc == 0)
+ sort_fields = "AD";
+ else
+ sort_fields = argv[0].s;
+ accumulate = 1;
+}
+
+static void no_sort_command(int, argument *)
+{
+ sort_fields.clear();
+}
+
+static void articles_command(int argc, argument *argv)
+{
+ articles.clear();
+ int i;
+ for (i = 0; i < argc; i++) {
+ articles += argv[i].s;
+ articles += '\0';
+ }
+ int len = articles.length();
+ for (i = 0; i < len; i++)
+ articles[i] = cmlower(articles[i]);
+}
+
+static void database_command(int argc, argument *argv)
+{
+ for (int i = 0; i < argc; i++)
+ database_list.add_file(argv[i].s);
+}
+
+static void default_database_command(int, argument *)
+{
+ search_default = 1;
+}
+
+static void no_default_database_command(int, argument *)
+{
+ search_default = 0;
+}
+
+static void bibliography_command(int argc, argument *argv)
+{
+ const char *saved_filename = current_filename;
+ int saved_lineno = current_lineno;
+ int saved_label_in_text = label_in_text;
+ label_in_text = 0;
+ if (!accumulate)
+ fputs(".]<\n", stdout);
+ for (int i = 0; i < argc; i++)
+ do_bib(argv[i].s);
+ if (accumulate)
+ output_references();
+ else
+ fputs(".]>\n", stdout);
+ current_filename = saved_filename;
+ current_lineno = saved_lineno;
+ label_in_text = saved_label_in_text;
+}
+
+static void annotate_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ annotation_field = argv[0].s[0];
+ else
+ annotation_field = 'X';
+ if (argc == 2)
+ annotation_macro = argv[1].s;
+ else
+ annotation_macro = "AP";
+}
+
+static void no_annotate_command(int, argument *)
+{
+ annotation_macro.clear();
+ annotation_field = -1;
+}
+
+static void reverse_command(int, argument *argv)
+{
+ reverse_fields = argv[0].s;
+}
+
+static void no_reverse_command(int, argument *)
+{
+ reverse_fields.clear();
+}
+
+static void abbreviate_command(int argc, argument *argv)
+{
+ abbreviate_fields = argv[0].s;
+ period_before_initial = argc > 1 ? argv[1].s : ". ";
+ period_before_last_name = argc > 2 ? argv[2].s : ". ";
+ period_before_other = argc > 3 ? argv[3].s : ". ";
+ period_before_hyphen = argc > 4 ? argv[4].s : ".";
+}
+
+static void no_abbreviate_command(int, argument *)
+{
+ abbreviate_fields.clear();
+}
+
+string search_ignore_fields;
+
+static void search_ignore_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ search_ignore_fields = argv[0].s;
+ else
+ search_ignore_fields = "XYZ";
+ search_ignore_fields += '\0';
+ linear_ignore_fields = search_ignore_fields.contents();
+}
+
+static void no_search_ignore_command(int, argument *)
+{
+ linear_ignore_fields = "";
+}
+
+static void search_truncate_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ linear_truncate_len = argv[0].n;
+ else
+ linear_truncate_len = 6;
+}
+
+static void no_search_truncate_command(int, argument *)
+{
+ linear_truncate_len = -1;
+}
+
+static void discard_command(int argc, argument *argv)
+{
+ if (argc == 0)
+ discard_fields = "XYZ";
+ else
+ discard_fields = argv[0].s;
+ accumulate = 1;
+}
+
+static void no_discard_command(int, argument *)
+{
+ discard_fields.clear();
+}
+
+static void label_command(int, argument *argv)
+{
+ set_label_spec(argv[0].s);
+}
+
+static void abbreviate_label_ranges_command(int argc, argument *argv)
+{
+ abbreviate_label_ranges = 1;
+ label_range_indicator = argc > 0 ? argv[0].s : "-";
+}
+
+static void no_abbreviate_label_ranges_command(int, argument *)
+{
+ abbreviate_label_ranges = 0;
+}
+
+static void label_in_reference_command(int, argument *)
+{
+ label_in_reference = 1;
+}
+
+static void no_label_in_reference_command(int, argument *)
+{
+ label_in_reference = 0;
+}
+
+static void label_in_text_command(int, argument *)
+{
+ label_in_text = 1;
+}
+
+static void no_label_in_text_command(int, argument *)
+{
+ label_in_text = 0;
+}
+
+static void sort_adjacent_labels_command(int, argument *)
+{
+ sort_adjacent_labels = 1;
+}
+
+static void no_sort_adjacent_labels_command(int, argument *)
+{
+ sort_adjacent_labels = 0;
+}
+
+static void date_as_label_command(int argc, argument *argv)
+{
+ if (set_date_label_spec(argc > 0 ? argv[0].s : "D%a*"))
+ date_as_label = 1;
+}
+
+static void no_date_as_label_command(int, argument *)
+{
+ date_as_label = 0;
+}
+
+static void short_label_command(int, argument *argv)
+{
+ if (set_short_label_spec(argv[0].s))
+ short_label_flag = 1;
+}
+
+static void no_short_label_command(int, argument *)
+{
+ short_label_flag = 0;
+}
+
+static void compatible_command(int, argument *)
+{
+ compatible_flag = 1;
+}
+
+static void no_compatible_command(int, argument *)
+{
+ compatible_flag = 0;
+}
+
+static void join_authors_command(int argc, argument *argv)
+{
+ join_authors_exactly_two = argv[0].s;
+ join_authors_default = argc > 1 ? argv[1].s : argv[0].s;
+ join_authors_last_two = argc == 3 ? argv[2].s : argv[0].s;
+}
+
+static void bracket_label_command(int, argument *argv)
+{
+ pre_label = argv[0].s;
+ post_label = argv[1].s;
+ sep_label = argv[2].s;
+}
+
+static void separate_label_second_parts_command(int, argument *argv)
+{
+ separate_label_second_parts = argv[0].s;
+}
+
+static void et_al_command(int argc, argument *argv)
+{
+ et_al = argv[0].s;
+ et_al_min_elide = argv[1].n;
+ if (et_al_min_elide < 1)
+ et_al_min_elide = 1;
+ et_al_min_total = argc >= 3 ? argv[2].n : 0;
+}
+
+static void no_et_al_command(int, argument *)
+{
+ et_al.clear();
+ et_al_min_elide = 0;
+}
+
+typedef void (*command_t)(int, argument *);
+
+/* arg_types is a string describing the numbers and types of arguments.
+s means a string, i means an integer, f is a list of fields, F is
+a single field,
+? means that the previous argument is optional, * means that the
+previous argument can occur any number of times. */
+
+struct {
+ const char *name;
+ command_t func;
+ const char *arg_types;
+} command_table[] = {
+ "include", include_command, "s",
+ "echo", echo_command, "s*",
+ "capitalize", capitalize_command, "f?",
+ "accumulate", accumulate_command, "",
+ "no-accumulate", no_accumulate_command, "",
+ "move-punctuation", move_punctuation_command, "",
+ "no-move-punctuation", no_move_punctuation_command, "",
+ "sort", sort_command, "s?",
+ "no-sort", no_sort_command, "",
+ "articles", articles_command, "s*",
+ "database", database_command, "ss*",
+ "default-database", default_database_command, "",
+ "no-default-database", no_default_database_command, "",
+ "bibliography", bibliography_command, "ss*",
+ "annotate", annotate_command, "F?s?",
+ "no-annotate", no_annotate_command, "",
+ "reverse", reverse_command, "s",
+ "no-reverse", no_reverse_command, "",
+ "abbreviate", abbreviate_command, "ss?s?s?s?",
+ "no-abbreviate", no_abbreviate_command, "",
+ "search-ignore", search_ignore_command, "f?",
+ "no-search-ignore", no_search_ignore_command, "",
+ "search-truncate", search_truncate_command, "i?",
+ "no-search-truncate", no_search_truncate_command, "",
+ "discard", discard_command, "f?",
+ "no-discard", no_discard_command, "",
+ "label", label_command, "s",
+ "abbreviate-label-ranges", abbreviate_label_ranges_command, "s?",
+ "no-abbreviate-label-ranges", no_abbreviate_label_ranges_command, "",
+ "label-in-reference", label_in_reference_command, "",
+ "no-label-in-reference", no_label_in_reference_command, "",
+ "label-in-text", label_in_text_command, "",
+ "no-label-in-text", no_label_in_text_command, "",
+ "sort-adjacent-labels", sort_adjacent_labels_command, "",
+ "no-sort-adjacent-labels", no_sort_adjacent_labels_command, "",
+ "date-as-label", date_as_label_command, "s?",
+ "no-date-as-label", no_date_as_label_command, "",
+ "short-label", short_label_command, "s",
+ "no-short-label", no_short_label_command, "",
+ "compatible", compatible_command, "",
+ "no-compatible", no_compatible_command, "",
+ "join-authors", join_authors_command, "sss?",
+ "bracket-label", bracket_label_command, "sss",
+ "separate-label-second-parts", separate_label_second_parts_command, "s",
+ "et-al", et_al_command, "sii?",
+ "no-et-al", no_et_al_command, "",
+};
+
+static int check_args(const char *types, const char *name,
+ int argc, argument *argv)
+{
+ int argno = 0;
+ while (*types) {
+ if (argc == 0) {
+ if (types[1] == '?')
+ break;
+ else if (types[1] == '*') {
+ assert(types[2] == '\0');
+ break;
+ }
+ else {
+ input_stack::error("missing argument for command `%1'", name);
+ return 0;
+ }
+ }
+ switch (*types) {
+ case 's':
+ break;
+ case 'i':
+ {
+ char *ptr;
+ long n = strtol(argv->s, &ptr, 10);
+ if ((n == 0 && ptr == argv->s)
+ || *ptr != '\0') {
+ input_stack::error("argument %1 for command `%2' must be an integer",
+ argno + 1, name);
+ return 0;
+ }
+ argv->n = (int)n;
+ break;
+ }
+ case 'f':
+ {
+ for (const char *ptr = argv->s; *ptr != '\0'; ptr++)
+ if (!cs_field_name(*ptr)) {
+ input_stack::error("argument %1 for command `%2' must be a list of fields",
+ argno + 1, name);
+ return 0;
+ }
+ break;
+ }
+ case 'F':
+ if (argv->s[0] == '\0' || argv->s[1] != '\0'
+ || !cs_field_name(argv->s[0])) {
+ input_stack::error("argument %1 for command `%2' must be a field name",
+ argno + 1, name);
+ return 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ if (types[1] == '?')
+ types += 2;
+ else if (types[1] != '*')
+ types += 1;
+ --argc;
+ ++argv;
+ ++argno;
+ }
+ if (argc > 0) {
+ input_stack::error("too many arguments for command `%1'", name);
+ return 0;
+ }
+ return 1;
+}
+
+static void execute_command(const char *name, int argc, argument *argv)
+{
+ for (int i = 0; i < sizeof(command_table)/sizeof(command_table[0]); i++)
+ if (strcmp(name, command_table[i].name) == 0) {
+ if (check_args(command_table[i].arg_types, name, argc, argv))
+ (*command_table[i].func)(argc, argv);
+ return;
+ }
+ input_stack::error("unknown command `%1'", name);
+}
+
+static void command_loop()
+{
+ string command;
+ for (;;) {
+ command.clear();
+ int res = get_word(command);
+ if (res != 1) {
+ if (res == 0)
+ continue;
+ break;
+ }
+ int argc = 0;
+ command += '\0';
+ while ((res = get_word(command)) == 1) {
+ argc++;
+ command += '\0';
+ }
+ argument *argv = new argument[argc];
+ const char *ptr = command.contents();
+ for (int i = 0; i < argc; i++)
+ argv[i].s = ptr = strchr(ptr, '\0') + 1;
+ execute_command(command.contents(), argc, argv);
+ a_delete argv;
+ if (res == -1)
+ break;
+ }
+}
+
+void process_commands(const char *file)
+{
+ input_stack::init();
+ input_stack::push_file(file);
+ command_loop();
+}
+
+void process_commands(string &s, const char *file, int lineno)
+{
+ input_stack::init();
+ input_stack::push_string(s, file, lineno);
+ command_loop();
+}
diff --git a/gnu/usr.bin/groff/refer/command.h b/gnu/usr.bin/groff/refer/command.h
new file mode 100644
index 000000000000..2b977eae9a4c
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/command.h
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+void process_commands(const char *file);
+void process_commands(string &s, const char *file, int lineno);
+
+extern int accumulate;
+extern int move_punctuation;
+extern int search_default;
+extern search_list database_list;
+extern int label_in_text;
+extern int label_in_reference;
+extern int sort_adjacent_labels;
+extern string pre_label;
+extern string post_label;
+extern string sep_label;
+
+extern void do_bib(const char *);
+extern void output_references();
diff --git a/gnu/usr.bin/groff/refer/label.y b/gnu/usr.bin/groff/refer/label.y
new file mode 100644
index 000000000000..d18eb89a9887
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/label.y
@@ -0,0 +1,1173 @@
+/* -*- C++ -*-
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+%{
+
+#include "refer.h"
+#include "refid.h"
+#include "ref.h"
+#include "token.h"
+
+int yylex();
+void yyerror(const char *);
+int yyparse();
+
+static const char *format_serial(char c, int n);
+
+struct label_info {
+ int start;
+ int length;
+ int count;
+ int total;
+ label_info(const string &);
+};
+
+label_info *lookup_label(const string &label);
+
+struct expression {
+ enum {
+ // Does the tentative label depend on the reference?
+ CONTAINS_VARIABLE = 01,
+ CONTAINS_STAR = 02,
+ CONTAINS_FORMAT = 04,
+ CONTAINS_AT = 010
+ };
+ virtual ~expression() { }
+ virtual void evaluate(int, const reference &, string &,
+ substring_position &) = 0;
+ virtual unsigned analyze() { return 0; }
+};
+
+class at_expr : public expression {
+public:
+ at_expr() { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_VARIABLE|CONTAINS_AT; }
+};
+
+class format_expr : public expression {
+ char type;
+ int width;
+ int first_number;
+public:
+ format_expr(char c, int w = 0, int f = 1)
+ : type(c), width(w), first_number(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_FORMAT; }
+};
+
+class field_expr : public expression {
+ int number;
+ char name;
+public:
+ field_expr(char nm, int num) : name(nm), number(num) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_VARIABLE; }
+};
+
+class literal_expr : public expression {
+ string s;
+public:
+ literal_expr(const char *ptr, int len) : s(ptr, len) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class unary_expr : public expression {
+protected:
+ expression *expr;
+public:
+ unary_expr(expression *e) : expr(e) { }
+ ~unary_expr() { delete expr; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() { return expr ? expr->analyze() : 0; }
+};
+
+// This caches the analysis of an expression.
+
+class analyzed_expr : public unary_expr {
+ unsigned flags;
+public:
+ analyzed_expr(expression *);
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return flags; }
+};
+
+class star_expr : public unary_expr {
+public:
+ star_expr(expression *e) : unary_expr(e) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() {
+ return ((expr ? (expr->analyze() & ~CONTAINS_VARIABLE) : 0)
+ | CONTAINS_STAR);
+ }
+};
+
+typedef void map_t(const char *, const char *, string &);
+
+class map_expr : public unary_expr {
+ map_t *func;
+public:
+ map_expr(expression *e, map_t *f) : unary_expr(e), func(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+typedef const char *extractor_t(const char *, const char *, const char **);
+
+class extractor_expr : public unary_expr {
+ int part;
+ extractor_t *func;
+public:
+ enum { BEFORE = +1, MATCH = 0, AFTER = -1 };
+ extractor_expr(expression *e, extractor_t *f, int pt)
+ : unary_expr(e), func(f), part(pt) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class truncate_expr : public unary_expr {
+ int n;
+public:
+ truncate_expr(expression *e, int i) : n(i), unary_expr(e) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class separator_expr : public unary_expr {
+public:
+ separator_expr(expression *e) : unary_expr(e) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class binary_expr : public expression {
+protected:
+ expression *expr1;
+ expression *expr2;
+public:
+ binary_expr(expression *e1, expression *e2) : expr1(e1), expr2(e2) { }
+ ~binary_expr() { delete expr1; delete expr2; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() {
+ return (expr1 ? expr1->analyze() : 0) | (expr2 ? expr2->analyze() : 0);
+ }
+};
+
+class alternative_expr : public binary_expr {
+public:
+ alternative_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class list_expr : public binary_expr {
+public:
+ list_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class substitute_expr : public binary_expr {
+public:
+ substitute_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class ternary_expr : public expression {
+protected:
+ expression *expr1;
+ expression *expr2;
+ expression *expr3;
+public:
+ ternary_expr(expression *e1, expression *e2, expression *e3)
+ : expr1(e1), expr2(e2), expr3(e3) { }
+ ~ternary_expr() { delete expr1; delete expr2; delete expr3; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() {
+ return ((expr1 ? expr1->analyze() : 0)
+ | (expr2 ? expr2->analyze() : 0)
+ | (expr3 ? expr3->analyze() : 0));
+ }
+};
+
+class conditional_expr : public ternary_expr {
+public:
+ conditional_expr(expression *e1, expression *e2, expression *e3)
+ : ternary_expr(e1, e2, e3) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+static expression *parsed_label = 0;
+static expression *parsed_date_label = 0;
+static expression *parsed_short_label = 0;
+
+static expression *parse_result;
+
+string literals;
+
+%}
+
+%union {
+ int num;
+ expression *expr;
+ struct { int ndigits; int val; } dig;
+ struct { int start; int len; } str;
+}
+
+/* uppercase or lowercase letter */
+%token <num> TOKEN_LETTER
+/* literal characters */
+%token <str> TOKEN_LITERAL
+/* digit */
+%token <num> TOKEN_DIGIT
+
+%type <expr> conditional
+%type <expr> alternative
+%type <expr> list
+%type <expr> string
+%type <expr> substitute
+%type <expr> optional_conditional
+%type <num> number
+%type <dig> digits
+%type <num> optional_number
+%type <num> flag
+
+%%
+
+expr:
+ optional_conditional
+ { parse_result = ($1 ? new analyzed_expr($1) : 0); }
+ ;
+
+conditional:
+ alternative
+ { $$ = $1; }
+ | alternative '?' optional_conditional ':' conditional
+ { $$ = new conditional_expr($1, $3, $5); }
+ ;
+
+optional_conditional:
+ /* empty */
+ { $$ = 0; }
+ | conditional
+ { $$ = $1; }
+ ;
+
+alternative:
+ list
+ { $$ = $1; }
+ | alternative '|' list
+ { $$ = new alternative_expr($1, $3); }
+ | alternative '&' list
+ { $$ = new conditional_expr($1, $3, 0); }
+ ;
+
+list:
+ substitute
+ { $$ = $1; }
+ | list substitute
+ { $$ = new list_expr($1, $2); }
+ ;
+
+substitute:
+ string
+ { $$ = $1; }
+ | substitute '~' string
+ { $$ = new substitute_expr($1, $3); }
+ ;
+
+string:
+ '@'
+ { $$ = new at_expr; }
+ | TOKEN_LITERAL
+ {
+ $$ = new literal_expr(literals.contents() + $1.start,
+ $1.len);
+ }
+ | TOKEN_LETTER
+ { $$ = new field_expr($1, 0); }
+ | TOKEN_LETTER number
+ { $$ = new field_expr($1, $2 - 1); }
+ | '%' TOKEN_LETTER
+ {
+ switch ($2) {
+ case 'I':
+ case 'i':
+ case 'A':
+ case 'a':
+ $$ = new format_expr($2);
+ break;
+ default:
+ command_error("unrecognized format `%1'", char($2));
+ $$ = new format_expr('a');
+ break;
+ }
+ }
+
+ | '%' digits
+ {
+ $$ = new format_expr('0', $2.ndigits, $2.val);
+ }
+ | string '.' flag TOKEN_LETTER optional_number
+ {
+ switch ($4) {
+ case 'l':
+ $$ = new map_expr($1, lowercase);
+ break;
+ case 'u':
+ $$ = new map_expr($1, uppercase);
+ break;
+ case 'c':
+ $$ = new map_expr($1, capitalize);
+ break;
+ case 'r':
+ $$ = new map_expr($1, reverse_name);
+ break;
+ case 'a':
+ $$ = new map_expr($1, abbreviate_name);
+ break;
+ case 'y':
+ $$ = new extractor_expr($1, find_year, $3);
+ break;
+ case 'n':
+ $$ = new extractor_expr($1, find_last_name, $3);
+ break;
+ default:
+ $$ = $1;
+ command_error("unknown function `%1'", char($4));
+ break;
+ }
+ }
+
+ | string '+' number
+ { $$ = new truncate_expr($1, $3); }
+ | string '-' number
+ { $$ = new truncate_expr($1, -$3); }
+ | string '*'
+ { $$ = new star_expr($1); }
+ | '(' optional_conditional ')'
+ { $$ = $2; }
+ | '<' optional_conditional '>'
+ { $$ = new separator_expr($2); }
+ ;
+
+optional_number:
+ /* empty */
+ { $$ = -1; }
+ | number
+ { $$ = $1; }
+ ;
+
+number:
+ TOKEN_DIGIT
+ { $$ = $1; }
+ | number TOKEN_DIGIT
+ { $$ = $1*10 + $2; }
+ ;
+
+digits:
+ TOKEN_DIGIT
+ { $$.ndigits = 1; $$.val = $1; }
+ | digits TOKEN_DIGIT
+ { $$.ndigits = $1.ndigits + 1; $$.val = $1.val*10 + $2; }
+ ;
+
+
+flag:
+ /* empty */
+ { $$ = 0; }
+ | '+'
+ { $$ = 1; }
+ | '-'
+ { $$ = -1; }
+ ;
+
+%%
+
+/* bison defines const to be empty unless __STDC__ is defined, which it
+isn't under cfront */
+
+#ifdef const
+#undef const
+#endif
+
+const char *spec_ptr;
+const char *spec_end;
+const char *spec_cur;
+
+int yylex()
+{
+ while (spec_ptr < spec_end && csspace(*spec_ptr))
+ spec_ptr++;
+ spec_cur = spec_ptr;
+ if (spec_ptr >= spec_end)
+ return 0;
+ unsigned char c = *spec_ptr++;
+ if (csalpha(c)) {
+ yylval.num = c;
+ return TOKEN_LETTER;
+ }
+ if (csdigit(c)) {
+ yylval.num = c - '0';
+ return TOKEN_DIGIT;
+ }
+ if (c == '\'') {
+ yylval.str.start = literals.length();
+ for (; spec_ptr < spec_end; spec_ptr++) {
+ if (*spec_ptr == '\'') {
+ if (++spec_ptr < spec_end && *spec_ptr == '\'')
+ literals += '\'';
+ else {
+ yylval.str.len = literals.length() - yylval.str.start;
+ return TOKEN_LITERAL;
+ }
+ }
+ else
+ literals += *spec_ptr;
+ }
+ yylval.str.len = literals.length() - yylval.str.start;
+ return TOKEN_LITERAL;
+ }
+ return c;
+}
+
+int set_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_label;
+ parsed_label = parse_result;
+ return 1;
+}
+
+int set_date_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_date_label;
+ parsed_date_label = parse_result;
+ return 1;
+}
+
+int set_short_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_short_label;
+ parsed_short_label = parse_result;
+ return 1;
+}
+
+void yyerror(const char *message)
+{
+ if (spec_cur < spec_end)
+ command_error("label specification %1 before `%2'", message, spec_cur);
+ else
+ command_error("label specification %1 at end of string",
+ message, spec_cur);
+}
+
+void at_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (tentative)
+ ref.canonicalize_authors(result);
+ else {
+ const char *end, *start = ref.get_authors(&end);
+ if (start)
+ result.append(start, end - start);
+ }
+}
+
+void format_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (tentative)
+ return;
+ const label_info *lp = ref.get_label_ptr();
+ int num = lp == 0 ? ref.get_number() : lp->count;
+ if (type != '0')
+ result += format_serial(type, num + 1);
+ else {
+ const char *ptr = itoa(num + first_number);
+ int pad = width - strlen(ptr);
+ while (--pad >= 0)
+ result += '0';
+ result += ptr;
+ }
+}
+
+static const char *format_serial(char c, int n)
+{
+ assert(n > 0);
+ static char buf[128]; // more than enough.
+ switch (c) {
+ case 'i':
+ case 'I':
+ {
+ char *p = buf;
+ // troff uses z and w to represent 10000 and 5000 in Roman
+ // numerals; I can find no historical basis for this usage
+ const char *s = c == 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
+ if (n >= 40000)
+ return itoa(n);
+ while (n >= 10000) {
+ *p++ = s[0];
+ n -= 10000;
+ }
+ for (int i = 1000; i > 0; i /= 10, s += 2) {
+ int m = n/i;
+ n -= m*i;
+ switch (m) {
+ case 3:
+ *p++ = s[2];
+ /* falls through */
+ case 2:
+ *p++ = s[2];
+ /* falls through */
+ case 1:
+ *p++ = s[2];
+ break;
+ case 4:
+ *p++ = s[2];
+ *p++ = s[1];
+ break;
+ case 8:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 7:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 6:
+ *p++ = s[1];
+ *p++ = s[2];
+ break;
+ case 5:
+ *p++ = s[1];
+ break;
+ case 9:
+ *p++ = s[2];
+ *p++ = s[0];
+ }
+ }
+ *p = 0;
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ char *p = buf;
+ // this is derived from troff/reg.c
+ while (n > 0) {
+ int d = n % 26;
+ if (d == 0)
+ d = 26;
+ n -= d;
+ n /= 26;
+ *p++ = c + d - 1; // ASCII dependent
+ }
+ *p-- = 0;
+ // Reverse it.
+ char *q = buf;
+ while (q < p) {
+ char temp = *q;
+ *q = *p;
+ *p = temp;
+ --p;
+ ++q;
+ }
+ break;
+ }
+ default:
+ assert(0);
+ }
+ return buf;
+}
+
+void field_expr::evaluate(int, const reference &ref,
+ string &result, substring_position &)
+{
+ const char *end;
+ const char *start = ref.get_field(name, &end);
+ if (start) {
+ start = nth_field(number, start, &end);
+ if (start)
+ result.append(start, end - start);
+ }
+}
+
+void literal_expr::evaluate(int, const reference &,
+ string &result, substring_position &)
+{
+ result += s;
+}
+
+analyzed_expr::analyzed_expr(expression *e)
+: unary_expr(e), flags(e ? e->analyze() : 0)
+{
+}
+
+void analyzed_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ if (expr)
+ expr->evaluate(tentative, ref, result, pos);
+}
+
+void star_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ const label_info *lp = ref.get_label_ptr();
+ if (!tentative
+ && (lp == 0 || lp->total > 1)
+ && expr)
+ expr->evaluate(tentative, ref, result, pos);
+}
+
+void separator_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ int is_first = pos.start < 0;
+ if (expr)
+ expr->evaluate(tentative, ref, result, pos);
+ if (is_first) {
+ pos.start = start_length;
+ pos.length = result.length() - start_length;
+ }
+}
+
+void map_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ (*func)(temp.contents(), temp.contents() + temp.length(), result);
+ }
+}
+
+void extractor_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ const char *end, *start = (*func)(temp.contents(),
+ temp.contents() + temp.length(),
+ &end);
+ switch (part) {
+ case BEFORE:
+ if (start)
+ result.append(temp.contents(), start - temp.contents());
+ else
+ result += temp;
+ break;
+ case MATCH:
+ if (start)
+ result.append(start, end - start);
+ break;
+ case AFTER:
+ if (start)
+ result.append(end, temp.contents() + temp.length() - end);
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
+static void first_part(int len, const char *ptr, const char *end,
+ string &result)
+{
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ int counts = ti->sortify_non_empty(token_start, ptr);
+ if (counts && --len < 0)
+ break;
+ if (counts || ti->is_accent())
+ result.append(token_start, ptr - token_start);
+ }
+}
+
+static void last_part(int len, const char *ptr, const char *end,
+ string &result)
+{
+ const char *start = ptr;
+ int count = 0;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (ti->sortify_non_empty(token_start, ptr))
+ count++;
+ }
+ ptr = start;
+ int skip = count - len;
+ if (skip > 0) {
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ assert(0);
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (ti->sortify_non_empty(token_start, ptr) && --skip < 0) {
+ ptr = token_start;
+ break;
+ }
+ }
+ }
+ first_part(len, ptr, end, result);
+}
+
+void truncate_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ const char *start = temp.contents();
+ const char *end = start + temp.length();
+ if (n > 0)
+ first_part(n, start, end, result);
+ else if (n < 0)
+ last_part(-n, start, end, result);
+ }
+}
+
+void alternative_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (result.length() == start_length && expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+}
+
+void list_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+}
+
+void substitute_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (result.length() > start_length && result[result.length() - 1] == '-') {
+ // ought to see if pos covers the -
+ result.set_length(result.length() - 1);
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+ }
+}
+
+void conditional_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ string temp;
+ substring_position temp_pos;
+ if (expr1)
+ expr1->evaluate(tentative, ref, temp, temp_pos);
+ if (temp.length() > 0) {
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+ }
+ else {
+ if (expr3)
+ expr3->evaluate(tentative, ref, result, pos);
+ }
+}
+
+void reference::pre_compute_label()
+{
+ if (parsed_label != 0
+ && (parsed_label->analyze() & expression::CONTAINS_VARIABLE)) {
+ label.clear();
+ substring_position temp_pos;
+ parsed_label->evaluate(1, *this, label, temp_pos);
+ label_ptr = lookup_label(label);
+ }
+}
+
+void reference::compute_label()
+{
+ label.clear();
+ if (parsed_label)
+ parsed_label->evaluate(0, *this, label, separator_pos);
+ if (short_label_flag && parsed_short_label)
+ parsed_short_label->evaluate(0, *this, short_label, short_separator_pos);
+ if (date_as_label) {
+ string new_date;
+ if (parsed_date_label) {
+ substring_position temp_pos;
+ parsed_date_label->evaluate(0, *this, new_date, temp_pos);
+ }
+ set_date(new_date);
+ }
+ if (label_ptr)
+ label_ptr->count += 1;
+}
+
+void reference::immediate_compute_label()
+{
+ if (label_ptr)
+ label_ptr->total = 2; // force use of disambiguator
+ compute_label();
+}
+
+int reference::merge_labels(reference **v, int n, label_type type,
+ string &result)
+{
+ if (abbreviate_label_ranges)
+ return merge_labels_by_number(v, n, type, result);
+ else
+ return merge_labels_by_parts(v, n, type, result);
+}
+
+int reference::merge_labels_by_number(reference **v, int n, label_type type,
+ string &result)
+{
+ if (n <= 1)
+ return 0;
+ int num = get_number();
+ // Only merge three or more labels.
+ if (v[0]->get_number() != num + 1
+ || v[1]->get_number() != num + 2)
+ return 0;
+ for (int i = 2; i < n; i++)
+ if (v[i]->get_number() != num + i + 1)
+ break;
+ result = get_label(type);
+ result += label_range_indicator;
+ result += v[i - 1]->get_label(type);
+ return i;
+}
+
+const substring_position &reference::get_separator_pos(label_type type) const
+{
+ if (type == SHORT_LABEL && short_label_flag)
+ return short_separator_pos;
+ else
+ return separator_pos;
+}
+
+const string &reference::get_label(label_type type) const
+{
+ if (type == SHORT_LABEL && short_label_flag)
+ return short_label;
+ else
+ return label;
+}
+
+int reference::merge_labels_by_parts(reference **v, int n, label_type type,
+ string &result)
+{
+ if (n <= 0)
+ return 0;
+ const string &lb = get_label(type);
+ const substring_position &sp = get_separator_pos(type);
+ if (sp.start < 0
+ || sp.start != v[0]->get_separator_pos(type).start
+ || memcmp(lb.contents(), v[0]->get_label(type).contents(),
+ sp.start) != 0)
+ return 0;
+ result = lb;
+ int i = 0;
+ do {
+ result += separate_label_second_parts;
+ const substring_position &s = v[i]->get_separator_pos(type);
+ int sep_end_pos = s.start + s.length;
+ result.append(v[i]->get_label(type).contents() + sep_end_pos,
+ v[i]->get_label(type).length() - sep_end_pos);
+ } while (++i < n
+ && sp.start == v[i]->get_separator_pos(type).start
+ && memcmp(lb.contents(), v[i]->get_label(type).contents(),
+ sp.start) == 0);
+ return i;
+}
+
+string label_pool;
+
+label_info::label_info(const string &s)
+: count(0), total(1), length(s.length()), start(label_pool.length())
+{
+ label_pool += s;
+}
+
+static label_info **label_table = 0;
+static int label_table_size = 0;
+static int label_table_used = 0;
+
+label_info *lookup_label(const string &label)
+{
+ if (label_table == 0) {
+ label_table = new label_info *[17];
+ label_table_size = 17;
+ for (int i = 0; i < 17; i++)
+ label_table[i] = 0;
+ }
+ unsigned h = hash_string(label.contents(), label.length()) % label_table_size;
+ for (label_info **ptr = label_table + h;
+ *ptr != 0;
+ (ptr == label_table)
+ ? (ptr = label_table + label_table_size - 1)
+ : ptr--)
+ if ((*ptr)->length == label.length()
+ && memcmp(label_pool.contents() + (*ptr)->start, label.contents(),
+ label.length()) == 0) {
+ (*ptr)->total += 1;
+ return *ptr;
+ }
+ label_info *result = *ptr = new label_info(label);
+ if (++label_table_used * 2 > label_table_size) {
+ // Rehash the table.
+ label_info **old_table = label_table;
+ int old_size = label_table_size;
+ label_table_size = next_size(label_table_size);
+ label_table = new label_info *[label_table_size];
+ int i;
+ for (i = 0; i < label_table_size; i++)
+ label_table[i] = 0;
+ for (i = 0; i < old_size; i++)
+ if (old_table[i]) {
+ unsigned h = hash_string(label_pool.contents() + old_table[i]->start,
+ old_table[i]->length);
+ for (label_info **p = label_table + (h % label_table_size);
+ *p != 0;
+ (p == label_table)
+ ? (p = label_table + label_table_size - 1)
+ : --p)
+ ;
+ *p = old_table[i];
+ }
+ a_delete old_table;
+ }
+ return result;
+}
+
+void clear_labels()
+{
+ for (int i = 0; i < label_table_size; i++) {
+ delete label_table[i];
+ label_table[i] = 0;
+ }
+ label_table_used = 0;
+ label_pool.clear();
+}
+
+static void consider_authors(reference **start, reference **end, int i);
+
+void compute_labels(reference **v, int n)
+{
+ if (parsed_label
+ && (parsed_label->analyze() & expression::CONTAINS_AT)
+ && sort_fields.length() >= 2
+ && sort_fields[0] == 'A'
+ && sort_fields[1] == '+')
+ consider_authors(v, v + n, 0);
+ for (int i = 0; i < n; i++)
+ v[i]->compute_label();
+}
+
+
+/* A reference with a list of authors <A0,A1,...,AN> _needs_ author i
+where 0 <= i <= N if there exists a reference with a list of authors
+<B0,B1,...,BM> such that <A0,A1,...,AN> != <B0,B1,...,BM> and M >= i
+and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
+A1,...,A(i-1) et al'' because this would match both <A0,A1,...,AN> and
+<B0,B1,...,BM>. If a reference needs author i we only have to call
+need_author(j) for some j >= i such that the reference also needs
+author j. */
+
+/* This function handles 2 tasks:
+determine which authors are needed (cannot be elided with et al.);
+determine which authors can have only last names in the labels.
+
+References >= start and < end have the same first i author names.
+Also they're sorted by A+. */
+
+static void consider_authors(reference **start, reference **end, int i)
+{
+ if (start >= end)
+ return;
+ reference **p = start;
+ if (i >= (*p)->get_nauthors()) {
+ for (++p; p < end && i >= (*p)->get_nauthors(); p++)
+ ;
+ if (p < end && i > 0) {
+ // If we have an author list <A B C> and an author list <A B C D>,
+ // then both lists need C.
+ for (reference **q = start; q < end; q++)
+ (*q)->need_author(i - 1);
+ }
+ start = p;
+ }
+ while (p < end) {
+ reference **last_name_start = p;
+ reference **name_start = p;
+ for (++p;
+ p < end && i < (*p)->get_nauthors()
+ && same_author_last_name(**last_name_start, **p, i);
+ p++) {
+ if (!same_author_name(**name_start, **p, i)) {
+ consider_authors(name_start, p, i + 1);
+ name_start = p;
+ }
+ }
+ consider_authors(name_start, p, i + 1);
+ if (last_name_start == name_start) {
+ for (reference **q = last_name_start; q < p; q++)
+ (*q)->set_last_name_unambiguous(i);
+ }
+ // If we have an author list <A B C D> and <A B C E>, then the lists
+ // need author D and E respectively.
+ if (name_start > start || p < end) {
+ for (reference **q = last_name_start; q < p; q++)
+ (*q)->need_author(i);
+ }
+ }
+}
+
+int same_author_last_name(const reference &r1, const reference &r2, int n)
+{
+ const char *ae1;
+ const char *as1 = r1.get_sort_field(0, n, 0, &ae1);
+ assert(as1 != 0);
+ const char *ae2;
+ const char *as2 = r2.get_sort_field(0, n, 0, &ae2);
+ assert(as2 != 0);
+ return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
+}
+
+int same_author_name(const reference &r1, const reference &r2, int n)
+{
+ const char *ae1;
+ const char *as1 = r1.get_sort_field(0, n, -1, &ae1);
+ assert(as1 != 0);
+ const char *ae2;
+ const char *as2 = r2.get_sort_field(0, n, -1, &ae2);
+ assert(as2 != 0);
+ return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
+}
+
+
+void int_set::set(int i)
+{
+ assert(i >= 0);
+ int bytei = i >> 3;
+ if (bytei >= v.length()) {
+ int old_length = v.length();
+ v.set_length(bytei + 1);
+ for (int j = old_length; j <= bytei; j++)
+ v[j] = 0;
+ }
+ v[bytei] |= 1 << (i & 7);
+}
+
+int int_set::get(int i) const
+{
+ assert(i >= 0);
+ int bytei = i >> 3;
+ return bytei >= v.length() ? 0 : (v[bytei] & (1 << (i & 7))) != 0;
+}
+
+void reference::set_last_name_unambiguous(int i)
+{
+ last_name_unambiguous.set(i);
+}
+
+void reference::need_author(int n)
+{
+ if (n > last_needed_author)
+ last_needed_author = n;
+}
+
+const char *reference::get_authors(const char **end) const
+{
+ if (!computed_authors) {
+ ((reference *)this)->computed_authors = 1;
+ string &result = ((reference *)this)->authors;
+ int na = get_nauthors();
+ result.clear();
+ for (int i = 0; i < na; i++) {
+ if (last_name_unambiguous.get(i)) {
+ const char *e, *start = get_author_last_name(i, &e);
+ assert(start != 0);
+ result.append(start, e - start);
+ }
+ else {
+ const char *e, *start = get_author(i, &e);
+ assert(start != 0);
+ result.append(start, e - start);
+ }
+ if (i == last_needed_author
+ && et_al.length() > 0
+ && et_al_min_elide > 0
+ && last_needed_author + et_al_min_elide < na
+ && na >= et_al_min_total) {
+ result += et_al;
+ break;
+ }
+ if (i < na - 1) {
+ if (na == 2)
+ result += join_authors_exactly_two;
+ else if (i < na - 2)
+ result += join_authors_default;
+ else
+ result += join_authors_last_two;
+ }
+ }
+ }
+ const char *start = authors.contents();
+ *end = start + authors.length();
+ return start;
+}
+
+int reference::get_nauthors() const
+{
+ if (nauthors < 0) {
+ const char *dummy;
+ for (int na = 0; get_author(na, &dummy) != 0; na++)
+ ;
+ ((reference *)this)->nauthors = na;
+ }
+ return nauthors;
+}
diff --git a/gnu/usr.bin/groff/refer/ref.cc b/gnu/usr.bin/groff/refer/ref.cc
new file mode 100644
index 000000000000..0b78813ec190
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/ref.cc
@@ -0,0 +1,1144 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "refer.h"
+#include "refid.h"
+#include "ref.h"
+#include "token.h"
+
+static const char *find_day(const char *, const char *, const char **);
+static int find_month(const char *start, const char *end);
+static void abbreviate_names(string &);
+
+#define DEFAULT_ARTICLES "the\000a\000an"
+
+string articles(DEFAULT_ARTICLES, sizeof(DEFAULT_ARTICLES));
+
+// Multiple occurrences of fields are separated by FIELD_SEPARATOR.
+const char FIELD_SEPARATOR = '\0';
+
+const char MULTI_FIELD_NAMES[] = "AE";
+const char *AUTHOR_FIELDS = "AQ";
+
+enum { OTHER, JOURNAL_ARTICLE, BOOK, ARTICLE_IN_BOOK, TECH_REPORT, BELL_TM };
+
+const char *reference_types[] = {
+ "other",
+ "journal-article",
+ "book",
+ "article-in-book",
+ "tech-report",
+ "bell-tm",
+};
+
+static string temp_fields[256];
+
+reference::reference(const char *start, int len, reference_id *ridp)
+: no(-1), field(0), nfields(0), h(0), merged(0), label_ptr(0),
+ computed_authors(0), last_needed_author(-1), nauthors(-1)
+{
+ for (int i = 0; i < 256; i++)
+ field_index[i] = NULL_FIELD_INDEX;
+ if (ridp)
+ rid = *ridp;
+ if (start == 0)
+ return;
+ if (len <= 0)
+ return;
+ const char *end = start + len;
+ const char *ptr = start;
+ assert(*ptr == '%');
+ while (ptr < end) {
+ if (ptr + 1 < end && ptr[1] != '\0'
+ && ((ptr[1] != '%' && ptr[1] == annotation_field)
+ || (ptr + 2 < end && ptr[1] == '%' && ptr[2] != '\0'
+ && discard_fields.search(ptr[2]) < 0))) {
+ if (ptr[1] == '%')
+ ptr++;
+ string &f = temp_fields[(unsigned char)ptr[1]];
+ ptr += 2;
+ while (ptr < end && csspace(*ptr))
+ ptr++;
+ for (;;) {
+ for (;;) {
+ if (ptr >= end) {
+ f += '\n';
+ break;
+ }
+ f += *ptr;
+ if (*ptr++ == '\n')
+ break;
+ }
+ if (ptr >= end || *ptr == '%')
+ break;
+ }
+ }
+ else if (ptr + 1 < end && ptr[1] != '\0' && ptr[1] != '%'
+ && discard_fields.search(ptr[1]) < 0) {
+ string &f = temp_fields[(unsigned char)ptr[1]];
+ if (f.length() > 0) {
+ if (strchr(MULTI_FIELD_NAMES, ptr[1]) != 0)
+ f += FIELD_SEPARATOR;
+ else
+ f.clear();
+ }
+ ptr += 2;
+ if (ptr < end) {
+ if (*ptr == ' ')
+ ptr++;
+ for (;;) {
+ const char *p = ptr;
+ while (ptr < end && *ptr != '\n')
+ ptr++;
+ // strip trailing white space
+ const char *q = ptr;
+ while (q > p && q[-1] != '\n' && csspace(q[-1]))
+ q--;
+ while (p < q)
+ f += *p++;
+ if (ptr >= end)
+ break;
+ ptr++;
+ if (ptr >= end)
+ break;
+ if (*ptr == '%')
+ break;
+ f += ' ';
+ }
+ }
+ }
+ else {
+ // skip this field
+ for (;;) {
+ while (ptr < end && *ptr++ != '\n')
+ ;
+ if (ptr >= end || *ptr == '%')
+ break;
+ }
+ }
+ }
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0)
+ nfields++;
+ field = new string[nfields];
+ int j = 0;
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0) {
+ field[j].move(temp_fields[i]);
+ if (abbreviate_fields.search(i) >= 0)
+ abbreviate_names(field[j]);
+ field_index[i] = j;
+ j++;
+ }
+}
+
+reference::~reference()
+{
+ if (nfields > 0)
+ ad_delete(nfields) field;
+}
+
+// ref is the inline, this is the database ref
+
+void reference::merge(reference &ref)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ temp_fields[i].move(field[field_index[i]]);
+ for (i = 0; i < 256; i++)
+ if (ref.field_index[i] != NULL_FIELD_INDEX)
+ temp_fields[i].move(ref.field[ref.field_index[i]]);
+ for (i = 0; i < 256; i++)
+ field_index[i] = NULL_FIELD_INDEX;
+ int old_nfields = nfields;
+ nfields = 0;
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0)
+ nfields++;
+ if (nfields != old_nfields) {
+ if (old_nfields > 0)
+ ad_delete(old_nfields) field;
+ field = new string[nfields];
+ }
+ int j = 0;
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0) {
+ field[j].move(temp_fields[i]);
+ field_index[i] = j;
+ j++;
+ }
+ merged = 1;
+}
+
+void reference::insert_field(unsigned char c, string &s)
+{
+ assert(s.length() > 0);
+ if (field_index[c] != NULL_FIELD_INDEX) {
+ field[field_index[c]].move(s);
+ return;
+ }
+ assert(field_index[c] == NULL_FIELD_INDEX);
+ string *old_field = field;
+ field = new string[nfields + 1];
+ int pos = 0;
+ for (int i = 0; i < int(c); i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ pos++;
+ for (i = 0; i < pos; i++)
+ field[i].move(old_field[i]);
+ field[pos].move(s);
+ for (i = pos; i < nfields; i++)
+ field[i + 1].move(old_field[i]);
+ if (nfields > 0)
+ ad_delete(nfields) old_field;
+ nfields++;
+ field_index[c] = pos;
+ for (i = c + 1; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ field_index[i] += 1;
+}
+
+void reference::delete_field(unsigned char c)
+{
+ if (field_index[c] == NULL_FIELD_INDEX)
+ return;
+ string *old_field = field;
+ field = new string[nfields - 1];
+ for (int i = 0; i < int(field_index[c]); i++)
+ field[i].move(old_field[i]);
+ for (i = field_index[c]; i < nfields - 1; i++)
+ field[i].move(old_field[i + 1]);
+ if (nfields > 0)
+ ad_delete(nfields) old_field;
+ nfields--;
+ field_index[c] = NULL_FIELD_INDEX;
+ for (i = c + 1; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ field_index[i] -= 1;
+}
+
+void reference::compute_hash_code()
+{
+ if (!rid.is_null())
+ h = rid.hash();
+ else {
+ h = 0;
+ for (int i = 0; i < nfields; i++)
+ if (field[i].length() > 0) {
+ h <<= 4;
+ h ^= hash_string(field[i].contents(), field[i].length());
+ }
+ }
+}
+
+void reference::set_number(int n)
+{
+ no = n;
+}
+
+const char SORT_SEP = '\001';
+const char SORT_SUB_SEP = '\002';
+const char SORT_SUB_SUB_SEP = '\003';
+
+// sep specifies additional word separators
+
+void sortify_words(const char *s, const char *end, const char *sep,
+ string &result)
+{
+ int non_empty = 0;
+ int need_separator = 0;
+ for (;;) {
+ const char *token_start = s;
+ if (!get_token(&s, end))
+ break;
+ if ((s - token_start == 1
+ && (*token_start == ' '
+ || *token_start == '\n'
+ || (sep && *token_start != '\0'
+ && strchr(sep, *token_start) != 0)))
+ || (s - token_start == 2
+ && token_start[0] == '\\' && token_start[1] == ' ')) {
+ if (non_empty)
+ need_separator = 1;
+ }
+ else {
+ const token_info *ti = lookup_token(token_start, s);
+ if (ti->sortify_non_empty(token_start, s)) {
+ if (need_separator) {
+ result += ' ';
+ need_separator = 0;
+ }
+ ti->sortify(token_start, s, result);
+ non_empty = 1;
+ }
+ }
+ }
+}
+
+void sortify_word(const char *s, const char *end, string &result)
+{
+ for (;;) {
+ const char *token_start = s;
+ if (!get_token(&s, end))
+ break;
+ const token_info *ti = lookup_token(token_start, s);
+ ti->sortify(token_start, s, result);
+ }
+}
+
+void sortify_other(const char *s, int len, string &key)
+{
+ sortify_words(s, s + len, 0, key);
+}
+
+void sortify_title(const char *s, int len, string &key)
+{
+ const char *end = s + len;
+ for (; s < end && (*s == ' ' || *s == '\n'); s++)
+ ;
+ const char *ptr = s;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ if (ptr - token_start == 1
+ && (*token_start == ' ' || *token_start == '\n'))
+ break;
+ }
+ if (ptr < end) {
+ int first_word_len = ptr - s - 1;
+ const char *ae = articles.contents() + articles.length();
+ for (const char *a = articles.contents();
+ a < ae;
+ a = strchr(a, '\0') + 1)
+ if (first_word_len == strlen(a)) {
+ for (int j = 0; j < first_word_len; j++)
+ if (a[j] != cmlower(s[j]))
+ break;
+ if (j >= first_word_len) {
+ s = ptr;
+ for (; s < end && (*s == ' ' || *s == '\n'); s++)
+ ;
+ break;
+ }
+ }
+ }
+ sortify_words(s, end, 0, key);
+}
+
+void sortify_name(const char *s, int len, string &key)
+{
+ const char *last_name_end;
+ const char *last_name = find_last_name(s, s + len, &last_name_end);
+ sortify_word(last_name, last_name_end, key);
+ key += SORT_SUB_SUB_SEP;
+ if (last_name > s)
+ sortify_words(s, last_name, ".", key);
+ key += SORT_SUB_SUB_SEP;
+ if (last_name_end < s + len)
+ sortify_words(last_name_end, s + len, ".,", key);
+}
+
+void sortify_date(const char *s, int len, string &key)
+{
+ const char *year_end;
+ const char *year_start = find_year(s, s + len, &year_end);
+ if (!year_start) {
+ // Things without years are often `forthcoming', so it makes sense
+ // that they sort after things with explicit years.
+ key += 'A';
+ sortify_words(s, s + len, 0, key);
+ return;
+ }
+ int n = year_end - year_start;
+ while (n < 4) {
+ key += '0';
+ n++;
+ }
+ while (year_start < year_end)
+ key += *year_start++;
+ int m = find_month(s, s + len);
+ if (m < 0)
+ return;
+ key += 'A' + m;
+ const char *day_end;
+ const char *day_start = find_day(s, s + len, &day_end);
+ if (!day_start)
+ return;
+ if (day_end - day_start == 1)
+ key += '0';
+ while (day_start < day_end)
+ key += *day_start++;
+}
+
+// SORT_{SUB,SUB_SUB}_SEP can creep in from use of @ in label specification.
+
+void sortify_label(const char *s, int len, string &key)
+{
+ const char *end = s + len;
+ for (;;) {
+ for (const char *ptr = s;
+ ptr < end && *ptr != SORT_SUB_SEP && *ptr != SORT_SUB_SUB_SEP;
+ ptr++)
+ ;
+ if (ptr > s)
+ sortify_words(s, ptr, 0, key);
+ s = ptr;
+ if (s >= end)
+ break;
+ key += *s++;
+ }
+}
+
+void reference::compute_sort_key()
+{
+ if (sort_fields.length() == 0)
+ return;
+ sort_fields += '\0';
+ const char *sf = sort_fields.contents();
+ while (*sf != '\0') {
+ if (sf > sort_fields)
+ sort_key += SORT_SEP;
+ char f = *sf++;
+ int n = 1;
+ if (*sf == '+') {
+ n = INT_MAX;
+ sf++;
+ }
+ else if (csdigit(*sf)) {
+ char *ptr;
+ long l = strtol(sf, &ptr, 10);
+ if (l == 0 && ptr == sf)
+ ;
+ else {
+ sf = ptr;
+ if (l < 0) {
+ n = 1;
+ }
+ else {
+ n = int(l);
+ }
+ }
+ }
+ if (f == '.')
+ sortify_label(label.contents(), label.length(), sort_key);
+ else if (f == AUTHOR_FIELDS[0])
+ sortify_authors(n, sort_key);
+ else
+ sortify_field(f, n, sort_key);
+ }
+ sort_fields.set_length(sort_fields.length() - 1);
+}
+
+void reference::sortify_authors(int n, string &result) const
+{
+ for (const char *p = AUTHOR_FIELDS; *p != '\0'; p++)
+ if (contains_field(*p)) {
+ sortify_field(*p, n, result);
+ return;
+ }
+ sortify_field(AUTHOR_FIELDS[0], n, result);
+}
+
+void reference::canonicalize_authors(string &result) const
+{
+ int len = result.length();
+ sortify_authors(INT_MAX, result);
+ if (result.length() > len)
+ result += SORT_SUB_SEP;
+}
+
+void reference::sortify_field(unsigned char f, int n, string &result) const
+{
+ typedef void (*sortify_t)(const char *, int, string &);
+ sortify_t sortifier = sortify_other;
+ switch (f) {
+ case 'A':
+ case 'E':
+ sortifier = sortify_name;
+ break;
+ case 'D':
+ sortifier = sortify_date;
+ break;
+ case 'B':
+ case 'J':
+ case 'T':
+ sortifier = sortify_title;
+ break;
+ }
+ int fi = field_index[(unsigned char)f];
+ if (fi != NULL_FIELD_INDEX) {
+ string &str = field[fi];
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ for (int i = 0; i < n && start < end; i++) {
+ const char *p = start;
+ while (start < end && *start != FIELD_SEPARATOR)
+ start++;
+ if (i > 0)
+ result += SORT_SUB_SEP;
+ (*sortifier)(p, start - p, result);
+ if (start < end)
+ start++;
+ }
+ }
+}
+
+int compare_reference(const reference &r1, const reference &r2)
+{
+ assert(r1.no >= 0);
+ assert(r2.no >= 0);
+ const char *s1 = r1.sort_key.contents();
+ int n1 = r1.sort_key.length();
+ const char *s2 = r2.sort_key.contents();
+ int n2 = r2.sort_key.length();
+ for (; n1 > 0 && n2 > 0; --n1, --n2, ++s1, ++s2)
+ if (*s1 != *s2)
+ return (int)(unsigned char)*s1 - (int)(unsigned char)*s2;
+ if (n2 > 0)
+ return -1;
+ if (n1 > 0)
+ return 1;
+ return r1.no - r2.no;
+}
+
+int same_reference(const reference &r1, const reference &r2)
+{
+ if (!r1.rid.is_null() && r1.rid == r2.rid)
+ return 1;
+ if (r1.h != r2.h)
+ return 0;
+ if (r1.nfields != r2.nfields)
+ return 0;
+ int i = 0;
+ for (i = 0; i < 256; i++)
+ if (r1.field_index != r2.field_index)
+ return 0;
+ for (i = 0; i < r1.nfields; i++)
+ if (r1.field[i] != r2.field[i])
+ return 0;
+ return 1;
+}
+
+const char *find_last_name(const char *start, const char *end,
+ const char **endp)
+{
+ const char *ptr = start;
+ const char *last_word = start;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ if (ptr - token_start == 1) {
+ if (*token_start == ',') {
+ *endp = token_start;
+ return last_word;
+ }
+ else if (*token_start == ' ' || *token_start == '\n') {
+ if (ptr < end && *ptr != ' ' && *ptr != '\n')
+ last_word = ptr;
+ }
+ }
+ }
+ *endp = end;
+ return last_word;
+}
+
+void abbreviate_name(const char *ptr, const char *end, string &result)
+{
+ const char *last_name_end;
+ const char *last_name_start = find_last_name(ptr, end, &last_name_end);
+ int need_period = 0;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, last_name_start))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (need_period) {
+ if ((ptr - token_start == 1 && *token_start == ' ')
+ || (ptr - token_start == 2 && token_start[0] == '\\'
+ && token_start[1] == ' '))
+ continue;
+ if (ti->is_upper())
+ result += period_before_initial;
+ else
+ result += period_before_other;
+ need_period = 0;
+ }
+ result.append(token_start, ptr - token_start);
+ if (ti->is_upper()) {
+ const char *lower_ptr = ptr;
+ int first_token = 1;
+ for (;;) {
+ token_start = ptr;
+ if (!get_token(&ptr, last_name_start))
+ break;
+ if ((ptr - token_start == 1 && *token_start == ' ')
+ || (ptr - token_start == 2 && token_start[0] == '\\'
+ && token_start[1] == ' '))
+ break;
+ ti = lookup_token(token_start, ptr);
+ if (ti->is_hyphen()) {
+ const char *ptr1 = ptr;
+ if (get_token(&ptr1, last_name_start)) {
+ ti = lookup_token(ptr, ptr1);
+ if (ti->is_upper()) {
+ result += period_before_hyphen;
+ result.append(token_start, ptr1 - token_start);
+ ptr = ptr1;
+ }
+ }
+ }
+ else if (ti->is_upper()) {
+ // MacDougal -> MacD.
+ result.append(lower_ptr, ptr - lower_ptr);
+ lower_ptr = ptr;
+ first_token = 1;
+ }
+ else if (first_token && ti->is_accent()) {
+ result.append(token_start, ptr - token_start);
+ lower_ptr = ptr;
+ }
+ first_token = 0;
+ }
+ need_period = 1;
+ }
+ }
+ if (need_period)
+ result += period_before_last_name;
+ result.append(last_name_start, end - last_name_start);
+}
+
+static void abbreviate_names(string &result)
+{
+ string str;
+ str.move(result);
+ const char *ptr = str.contents();
+ const char *end = ptr + str.length();
+ while (ptr < end) {
+ const char *name_end = (char *)memchr(ptr, FIELD_SEPARATOR, end - ptr);
+ if (name_end == 0)
+ name_end = end;
+ abbreviate_name(ptr, name_end, result);
+ if (name_end >= end)
+ break;
+ ptr = name_end + 1;
+ result += FIELD_SEPARATOR;
+ }
+}
+
+void reverse_name(const char *ptr, const char *name_end, string &result)
+{
+ const char *last_name_end;
+ const char *last_name_start = find_last_name(ptr, name_end, &last_name_end);
+ result.append(last_name_start, last_name_end - last_name_start);
+ while (last_name_start > ptr
+ && (last_name_start[-1] == ' ' || last_name_start[-1] == '\n'))
+ last_name_start--;
+ if (last_name_start > ptr) {
+ result += ", ";
+ result.append(ptr, last_name_start - ptr);
+ }
+ if (last_name_end < name_end)
+ result.append(last_name_end, name_end - last_name_end);
+}
+
+void reverse_names(string &result, int n)
+{
+ if (n <= 0)
+ return;
+ string str;
+ str.move(result);
+ const char *ptr = str.contents();
+ const char *end = ptr + str.length();
+ while (ptr < end) {
+ if (--n < 0) {
+ result.append(ptr, end - ptr);
+ break;
+ }
+ const char *name_end = (char *)memchr(ptr, FIELD_SEPARATOR, end - ptr);
+ if (name_end == 0)
+ name_end = end;
+ reverse_name(ptr, name_end, result);
+ if (name_end >= end)
+ break;
+ ptr = name_end + 1;
+ result += FIELD_SEPARATOR;
+ }
+}
+
+// Return number of field separators.
+
+int join_fields(string &f)
+{
+ const char *ptr = f.contents();
+ int len = f.length();
+ int nfield_seps = 0;
+ for (int j = 0; j < len; j++)
+ if (ptr[j] == FIELD_SEPARATOR)
+ nfield_seps++;
+ if (nfield_seps == 0)
+ return 0;
+ string temp;
+ int field_seps_left = nfield_seps;
+ for (j = 0; j < len; j++) {
+ if (ptr[j] == FIELD_SEPARATOR) {
+ if (nfield_seps == 1)
+ temp += join_authors_exactly_two;
+ else if (--field_seps_left == 0)
+ temp += join_authors_last_two;
+ else
+ temp += join_authors_default;
+ }
+ else
+ temp += ptr[j];
+ }
+ f = temp;
+ return nfield_seps;
+}
+
+void uppercase(const char *start, const char *end, string &result)
+{
+ for (;;) {
+ const char *token_start = start;
+ if (!get_token(&start, end))
+ break;
+ const token_info *ti = lookup_token(token_start, start);
+ ti->upper_case(token_start, start, result);
+ }
+}
+
+void lowercase(const char *start, const char *end, string &result)
+{
+ for (;;) {
+ const char *token_start = start;
+ if (!get_token(&start, end))
+ break;
+ const token_info *ti = lookup_token(token_start, start);
+ ti->lower_case(token_start, start, result);
+ }
+}
+
+void capitalize(const char *ptr, const char *end, string &result)
+{
+ int in_small_point_size = 0;
+ for (;;) {
+ const char *start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(start, ptr);
+ const char *char_end = ptr;
+ int is_lower = ti->is_lower();
+ if ((is_lower || ti->is_upper()) && get_token(&ptr, end)) {
+ const token_info *ti2 = lookup_token(char_end, ptr);
+ if (!ti2->is_accent())
+ ptr = char_end;
+ }
+ if (is_lower) {
+ if (!in_small_point_size) {
+ result += "\\s-2";
+ in_small_point_size = 1;
+ }
+ ti->upper_case(start, char_end, result);
+ result.append(char_end, ptr - char_end);
+ }
+ else {
+ if (in_small_point_size) {
+ result += "\\s+2";
+ in_small_point_size = 0;
+ }
+ result.append(start, ptr - start);
+ }
+ }
+ if (in_small_point_size)
+ result += "\\s+2";
+}
+
+void capitalize_field(string &str)
+{
+ string temp;
+ capitalize(str.contents(), str.contents() + str.length(), temp);
+ str.move(temp);
+}
+
+int is_terminated(const char *ptr, const char *end)
+{
+ const char *last_token = end;
+ for (;;) {
+ const char *p = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ last_token = p;
+ }
+ return end - last_token == 1
+ && (*last_token == '.' || *last_token == '!' || *last_token == '?');
+}
+
+void reference::output(FILE *fp)
+{
+ fputs(".]-\n", fp);
+ for (int i = 0; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX && i != annotation_field) {
+ string &f = field[field_index[i]];
+ if (!csdigit(i)) {
+ int j = reverse_fields.search(i);
+ if (j >= 0) {
+ int n;
+ int len = reverse_fields.length();
+ if (++j < len && csdigit(reverse_fields[j])) {
+ n = reverse_fields[j] - '0';
+ for (++j; j < len && csdigit(reverse_fields[j]); j++)
+ // should check for overflow
+ n = n*10 + reverse_fields[j] - '0';
+ }
+ else
+ n = INT_MAX;
+ reverse_names(f, n);
+ }
+ }
+ int is_multiple = join_fields(f) > 0;
+ if (capitalize_fields.search(i) >= 0)
+ capitalize_field(f);
+ if (memchr(f.contents(), '\n', f.length()) == 0) {
+ fprintf(fp, ".ds [%c ", i);
+ if (f[0] == ' ' || f[0] == '\\' || f[0] == '"')
+ putc('"', fp);
+ put_string(f, fp);
+ putc('\n', fp);
+ }
+ else {
+ fprintf(fp, ".de [%c\n", i);
+ put_string(f, fp);
+ fputs("..\n", fp);
+ }
+ if (i == 'P') {
+ int multiple_pages = 0;
+ if (f.length() > 0 && memchr(f.contents(), '-', f.length()) != 0)
+ multiple_pages = 1;
+ fprintf(fp, ".nr [P %d\n", multiple_pages);
+ }
+ else if (i == 'E')
+ fprintf(fp, ".nr [E %d\n", is_multiple);
+ }
+ for (const char *p = "TAO"; *p; p++) {
+ int fi = field_index[(unsigned char)*p];
+ if (fi != NULL_FIELD_INDEX) {
+ string &f = field[fi];
+ fprintf(fp, ".nr [%c %d\n", *p,
+ is_terminated(f.contents(), f.contents() + f.length()));
+ }
+ }
+ int t = classify();
+ fprintf(fp, ".][ %d %s\n", t, reference_types[t]);
+ if (annotation_macro.length() > 0 && annotation_field >= 0
+ && field_index[annotation_field] != NULL_FIELD_INDEX) {
+ putc('.', fp);
+ put_string(annotation_macro, fp);
+ putc('\n', fp);
+ put_string(field[field_index[annotation_field]], fp);
+ }
+}
+
+void reference::print_sort_key_comment(FILE *fp)
+{
+ fputs(".\\\"", fp);
+ put_string(sort_key, fp);
+ putc('\n', fp);
+}
+
+const char *find_year(const char *start, const char *end, const char **endp)
+{
+ for (;;) {
+ while (start < end && !csdigit(*start))
+ start++;
+ const char *ptr = start;
+ if (start == end)
+ break;
+ while (ptr < end && csdigit(*ptr))
+ ptr++;
+ if (ptr - start == 4 || ptr - start == 3
+ || (ptr - start == 2
+ && (start[0] >= '4' || (start[0] == '3' && start[1] >= '2')))) {
+ *endp = ptr;
+ return start;
+ }
+ start = ptr;
+ }
+ return 0;
+}
+
+static const char *find_day(const char *start, const char *end,
+ const char **endp)
+{
+ for (;;) {
+ while (start < end && !csdigit(*start))
+ start++;
+ const char *ptr = start;
+ if (start == end)
+ break;
+ while (ptr < end && csdigit(*ptr))
+ ptr++;
+ if ((ptr - start == 1 && start[0] != '0')
+ || (ptr - start == 2 &&
+ (start[0] == '1'
+ || start[0] == '2'
+ || (start[0] == '3' && start[1] <= '1')
+ || (start[0] == '0' && start[1] != '0')))) {
+ *endp = ptr;
+ return start;
+ }
+ start = ptr;
+ }
+ return 0;
+}
+
+static int find_month(const char *start, const char *end)
+{
+ static const char *months[] = {
+ "january",
+ "february",
+ "march",
+ "april",
+ "may",
+ "june",
+ "july",
+ "august",
+ "september",
+ "october",
+ "november",
+ "december",
+ };
+ for (;;) {
+ while (start < end && !csalpha(*start))
+ start++;
+ const char *ptr = start;
+ if (start == end)
+ break;
+ while (ptr < end && csalpha(*ptr))
+ ptr++;
+ if (ptr - start >= 3) {
+ for (int i = 0; i < sizeof(months)/sizeof(months[0]); i++) {
+ const char *q = months[i];
+ const char *p = start;
+ for (; p < ptr; p++, q++)
+ if (cmlower(*p) != *q)
+ break;
+ if (p >= ptr)
+ return i;
+ }
+ }
+ start = ptr;
+ }
+ return -1;
+}
+
+int reference::contains_field(char c) const
+{
+ return field_index[(unsigned char)c] != NULL_FIELD_INDEX;
+}
+
+int reference::classify()
+{
+ if (contains_field('J'))
+ return JOURNAL_ARTICLE;
+ if (contains_field('B'))
+ return ARTICLE_IN_BOOK;
+ if (contains_field('G'))
+ return TECH_REPORT;
+ if (contains_field('R'))
+ return TECH_REPORT;
+ if (contains_field('I'))
+ return BOOK;
+ if (contains_field('M'))
+ return BELL_TM;
+ return OTHER;
+}
+
+const char *reference::get_year(const char **endp) const
+{
+ if (field_index['D'] != NULL_FIELD_INDEX) {
+ string &date = field[field_index['D']];
+ const char *start = date.contents();
+ const char *end = start + date.length();
+ return find_year(start, end, endp);
+ }
+ else
+ return 0;
+}
+
+const char *reference::get_field(unsigned char c, const char **endp) const
+{
+ if (field_index[c] != NULL_FIELD_INDEX) {
+ string &f = field[field_index[c]];
+ const char *start = f.contents();
+ *endp = start + f.length();
+ return start;
+ }
+ else
+ return 0;
+}
+
+const char *reference::get_date(const char **endp) const
+{
+ return get_field('D', endp);
+}
+
+const char *nth_field(int i, const char *start, const char **endp)
+{
+ while (--i >= 0) {
+ start = (char *)memchr(start, FIELD_SEPARATOR, *endp - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ const char *e = (char *)memchr(start, FIELD_SEPARATOR, *endp - start);
+ if (e)
+ *endp = e;
+ return start;
+}
+
+const char *reference::get_author(int i, const char **endp) const
+{
+ for (const char *f = AUTHOR_FIELDS; *f != '\0'; f++) {
+ const char *start = get_field(*f, endp);
+ if (start) {
+ if (strchr(MULTI_FIELD_NAMES, *f) != 0)
+ return nth_field(i, start, endp);
+ else if (i == 0)
+ return start;
+ else
+ return 0;
+ }
+ }
+ return 0;
+}
+
+const char *reference::get_author_last_name(int i, const char **endp) const
+{
+ for (const char *f = AUTHOR_FIELDS; *f != '\0'; f++) {
+ const char *start = get_field(*f, endp);
+ if (start) {
+ if (strchr(MULTI_FIELD_NAMES, *f) != 0) {
+ start = nth_field(i, start, endp);
+ if (!start)
+ return 0;
+ }
+ if (*f == 'A')
+ return find_last_name(start, *endp, endp);
+ else
+ return start;
+ }
+ }
+ return 0;
+}
+
+void reference::set_date(string &d)
+{
+ if (d.length() == 0)
+ delete_field('D');
+ else
+ insert_field('D', d);
+}
+
+int same_year(const reference &r1, const reference &r2)
+{
+ const char *ye1;
+ const char *ys1 = r1.get_year(&ye1);
+ const char *ye2;
+ const char *ys2 = r2.get_year(&ye2);
+ if (ys1 == 0) {
+ if (ys2 == 0)
+ return same_date(r1, r2);
+ else
+ return 0;
+ }
+ else if (ys2 == 0)
+ return 0;
+ else if (ye1 - ys1 != ye2 - ys2)
+ return 0;
+ else
+ return memcmp(ys1, ys2, ye1 - ys1) == 0;
+}
+
+int same_date(const reference &r1, const reference &r2)
+{
+ const char *e1;
+ const char *s1 = r1.get_date(&e1);
+ const char *e2;
+ const char *s2 = r2.get_date(&e2);
+ if (s1 == 0)
+ return s2 == 0;
+ else if (s2 == 0)
+ return 0;
+ else if (e1 - s1 != e2 - s2)
+ return 0;
+ else
+ return memcmp(s1, s2, e1 - s1) == 0;
+}
+
+const char *reference::get_sort_field(int i, int si, int ssi,
+ const char **endp) const
+{
+ const char *start = sort_key.contents();
+ const char *end = start + sort_key.length();
+ if (i < 0) {
+ *endp = end;
+ return start;
+ }
+ while (--i >= 0) {
+ start = (char *)memchr(start, SORT_SEP, end - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ const char *e = (char *)memchr(start, SORT_SEP, end - start);
+ if (e)
+ end = e;
+ if (si < 0) {
+ *endp = end;
+ return start;
+ }
+ while (--si >= 0) {
+ start = (char *)memchr(start, SORT_SUB_SEP, end - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ e = (char *)memchr(start, SORT_SUB_SEP, end - start);
+ if (e)
+ end = e;
+ if (ssi < 0) {
+ *endp = end;
+ return start;
+ }
+ while (--ssi >= 0) {
+ start = (char *)memchr(start, SORT_SUB_SUB_SEP, end - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ e = (char *)memchr(start, SORT_SUB_SUB_SEP, end - start);
+ if (e)
+ end = e;
+ *endp = end;
+ return start;
+}
+
diff --git a/gnu/usr.bin/groff/refer/ref.h b/gnu/usr.bin/groff/refer/ref.h
new file mode 100644
index 000000000000..28e498dc5d83
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/ref.h
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct label_info;
+
+enum label_type { NORMAL_LABEL, SHORT_LABEL };
+const int N_LABEL_TYPES = 2;
+
+struct substring_position {
+ int start;
+ int length;
+ substring_position() : start(-1) { }
+};
+
+class int_set {
+ string v;
+public:
+ int_set() { }
+ void set(int i);
+ int get(int i) const;
+};
+
+class reference {
+private:
+ unsigned h;
+ reference_id rid;
+ int merged;
+ string sort_key;
+ int no;
+ string *field;
+ int nfields;
+ unsigned char field_index[256];
+ enum { NULL_FIELD_INDEX = 255 };
+ string label;
+ substring_position separator_pos;
+ string short_label;
+ substring_position short_separator_pos;
+ label_info *label_ptr;
+ string authors;
+ int computed_authors;
+ int last_needed_author;
+ int nauthors;
+ int_set last_name_unambiguous;
+
+ int contains_field(char) const;
+ void insert_field(unsigned char, string &s);
+ void delete_field(unsigned char);
+ void set_date(string &);
+ const char *get_sort_field(int i, int si, int ssi, const char **endp) const;
+ int merge_labels_by_parts(reference **, int, label_type, string &);
+ int merge_labels_by_number(reference **, int, label_type, string &);
+public:
+ reference(const char * = 0, int = -1, reference_id * = 0);
+ ~reference();
+ void output(FILE *);
+ void print_sort_key_comment(FILE *);
+ void set_number(int);
+ int get_number() const { return no; }
+ unsigned hash() const { return h; }
+ const string &get_label(label_type type) const;
+ const substring_position &get_separator_pos(label_type) const;
+ int is_merged() const { return merged; }
+ void compute_sort_key();
+ void compute_hash_code();
+ void pre_compute_label();
+ void compute_label();
+ void immediate_compute_label();
+ int classify();
+ void merge(reference &);
+ int merge_labels(reference **, int, label_type, string &);
+ int get_nauthors() const;
+ void need_author(int);
+ void set_last_name_unambiguous(int);
+ void sortify_authors(int, string &) const;
+ void canonicalize_authors(string &) const;
+ void sortify_field(unsigned char, int, string &) const;
+ const char *get_author(int, const char **) const;
+ const char *get_author_last_name(int, const char **) const;
+ const char *get_date(const char **) const;
+ const char *get_year(const char **) const;
+ const char *get_field(unsigned char, const char **) const;
+ const label_info *get_label_ptr() const { return label_ptr; }
+ const char *get_authors(const char **) const;
+ // for sorting
+ friend int compare_reference(const reference &r1, const reference &r2);
+ // for merging
+ friend int same_reference(const reference &, const reference &);
+ friend int same_year(const reference &, const reference &);
+ friend int same_date(const reference &, const reference &);
+ friend int same_author_last_name(const reference &, const reference &, int);
+ friend int same_author_name(const reference &, const reference &, int);
+};
+
+const char *find_year(const char *, const char *, const char **);
+const char *find_last_name(const char *, const char *, const char **);
+
+const char *nth_field(int i, const char *start, const char **endp);
+
+void capitalize(const char *ptr, const char *end, string &result);
+void reverse_name(const char *ptr, const char *end, string &result);
+void uppercase(const char *ptr, const char *end, string &result);
+void lowercase(const char *ptr, const char *end, string &result);
+void abbreviate_name(const char *ptr, const char *end, string &result);
diff --git a/gnu/usr.bin/groff/refer/refer.1 b/gnu/usr.bin/groff/refer/refer.1
new file mode 100644
index 000000000000..ad367f712408
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/refer.1
@@ -0,0 +1,1282 @@
+.\" -*- nroff -*-
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH REFER 1 "19 February 1993" "Groff Version 1.08"
+.SH NAME
+refer \- preprocess bibliographic references for groff
+.SH SYNOPSIS
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBrefer 'u
+.ti \niu
+.B refer
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-benvCPRS
+.OP \-a n
+.OP \-c fields
+.OP \-f n
+.OP \-i fields
+.OP \-k field
+.OP \-l m,n
+.OP \-p filename
+.OP \-s fields
+.OP \-t n
+.OP \-B field.macro
+.RI [\ filename \|.\|.\|.\ ]
+.br
+.ad \na
+.SH DESCRIPTION
+This file documents the GNU version of
+.BR refer ,
+which is part of the groff document formatting system.
+.B refer
+copies the contents of
+.IR filename \|.\|.\|.
+to the standard output,
+except that lines between
+.B .[
+and
+.B .]
+are interpreted as citations,
+and lines between
+.B .R1
+and
+.B .R2
+are interpreted as commands about how citations are to be processed.
+.LP
+Each citation specifies a reference.
+The citation can specify a reference that is contained in
+a bibliographic database by giving a set of keywords
+that only that reference contains.
+Alternatively it can specify a reference by supplying a database
+record in the citation.
+A combination of these alternatives is also possible.
+.LP
+For each citation,
+.B refer
+can produce a mark in the text.
+This mark consists of some label which can be separated from
+the text and from other labels in various ways.
+For each reference it also outputs
+.B groff
+commands that can be used by a macro package to produce a formatted
+reference for each citation.
+The output of
+.B refer
+must therefore be processed using a suitable macro package.
+The
+.B \-ms
+and
+.B \-me
+macros are both suitable.
+The commands to format a citation's reference can be output immediately after
+the citation,
+or the references may be accumulated,
+and the commands output at some later point.
+If the references are accumulated, then multiple citations of the same
+reference will produce a single formatted reference.
+.LP
+The interpretation of lines between
+.B .R1
+and
+.B .R2
+as commands is a new feature of GNU refer.
+Documents making use of this feature can still be processed by
+Unix refer just by adding the lines
+.RS
+.LP
+.nf
+.ft B
+\&.de R1
+\&.ig R2
+\&..
+.ft
+.fi
+.RE
+to the beginning of the document.
+This will cause
+.B troff
+to ignore everything between
+.B .R1
+and
+.BR .R2 .
+The effect of some commands can also be achieved by options.
+These options are supported mainly for compatibility with Unix refer.
+It is usually more convenient to use commands.
+.LP
+.B refer
+generates
+.B .lf
+lines so that filenames and line numbers in messages produced
+by commands that read
+.B refer
+output will be correct;
+it also interprets lines beginning with
+.B .lf
+so that filenames and line numbers in the messages and
+.B .lf
+lines that it produces will be accurate even if the input has been
+preprocessed by a command such as
+.BR soelim (1).
+.SH OPTIONS
+.LP
+Most options are equivalent to commands
+(for a description of these commands see the
+.B Commands
+subsection):
+.TP
+.B \-b
+.B
+no-label-in-text; no-label-in-reference
+.TP
+.B \-e
+.B accumulate
+.TP
+.B \-n
+.B no-default-database
+.TP
+.B \-C
+.B compatible
+.TP
+.B \-P
+.B move-puntuation
+.TP
+.B \-S
+.B
+label "(A.n|Q) ', ' (D.y|D)"; bracket-label " (" ) "; "
+.TP
+.BI \-a n
+.B reverse
+.BI A n
+.TP
+.BI \-c fields
+.B capitalize
+.I fields
+.TP
+.BI \-f n
+.B label
+.BI % n
+.TP
+.BI \-i fields
+.B search-ignore
+.I fields
+.TP
+.B \-k
+.B label
+.B L\(ti%a
+.TP
+.BI \-k field
+.B label
+.IB field \(ti%a
+.TP
+.B \-l
+.B label
+.BI A.nD.y%a
+.TP
+.BI \-l m
+.B label
+.BI A.n+ m D.y%a
+.TP
+.BI \-l, n
+.B label
+.BI A.nD.y\- n %a
+.TP
+.BI \-l m , n
+.B label
+.BI A.n+ m D.y\- n %a
+.TP
+.BI \-p filename
+.B database
+.I filename
+.TP
+.BI \-s spec
+.B sort
+.I spec
+.TP
+.BI \-t n
+.B search-truncate
+.I n
+.LP
+These options are equivalent to the following commands with the
+addition that the filenames specified on the command line are
+processed as if they were arguments to the
+.B bibliography
+command instead of in the normal way:
+.TP
+.B \-B
+.B
+annotate X AP; no-label-in-reference
+.TP
+.BI \-B field . macro
+.B annotate
+.I field
+.IB macro ;
+.B no-label-in-reference
+.LP
+The following options have no equivalent commands:
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-R
+Don't recognize lines beginning with
+.BR .R1 / .R2 .
+.SH USAGE
+.SS Bibliographic databases
+The bibliographic database is a text file consisting of records
+separated by one or more blank lines.
+Within each record fields start with a
+.B %
+at the beginning of a line.
+Each field has a one character name that immediately follows the
+.BR % .
+It is best to use only upper and lower case letters for the names
+of fields.
+The name of the field should be followed by exactly one space,
+and then by the contents of the field.
+Empty fields are ignored.
+The conventional meaning of each field is as follows:
+.TP
+.B A
+The name of an author.
+If the name contains a title such as
+.B Jr.
+at the end,
+it should be separated from the last name by a comma.
+There can be multiple occurrences of the
+.B A
+field.
+The order is siginificant.
+It is a good idea always to supply an
+.B A
+field or a
+.B Q
+field.
+.TP
+.B B
+For an article that is part of a book, the title of the book
+.TP
+.B C
+The place (city) of publication.
+.TP
+.B D
+The date of publication.
+The year should be specified in full.
+If the month is specified, the name rather than the number of the month
+should be used, but only the first three letters are required.
+It is a good idea always to supply a
+.B D
+field;
+if the date is unknown, a value such as
+.B in press
+or
+.B unknown
+can be used.
+.TP
+.B E
+For an article that is part of a book, the name of an editor of the book.
+Where the work has editors and no authors,
+the names of the editors should be given as
+.B A
+fields and
+.B ,\ (ed)
+or
+.B ,\ (eds)
+should be appended to the last author.
+.TP
+.B G
+US Government ordering number.
+.TP
+.B I
+The publisher (issuer).
+.TP
+.B J
+For an article in a journal, the name of the journal.
+.TP
+.B K
+Keywords to be used for searching.
+.TP
+.B L
+Label.
+.TP
+.B N
+Journal issue number.
+.TP
+.B O
+Other information.
+This is usually printed at the end of the reference.
+.TP
+.B P
+Page number.
+A range of pages can be specified as
+.IB m \- n\fR.
+.TP
+.B Q
+The name of the author, if the author is not a person.
+This will only be used if there are no
+.B A
+fields.
+There can only be one
+.B Q
+field.
+.TP
+.B R
+Technical report number.
+.TP
+.B S
+Series name.
+.TP
+.B T
+Title.
+For an article in a book or journal,
+this should be the title of the article.
+.TP
+.B V
+Volume number of the journal or book.
+.TP
+.B X
+Annotation.
+.LP
+For all fields except
+.B A
+and
+.BR E ,
+if there is more than one occurrence of a particular field in a record,
+only the last such field will be used.
+.LP
+If accent strings are used, they should follow the charater to be accented.
+This means that the
+.B AM
+macro must be used with the
+.B \-ms
+macros.
+Accent strings should not be quoted:
+use one
+.B \e
+rather than two.
+.SS Citations
+The format of a citation is
+.RS
+.BI .[ opening-text
+.br
+.I
+flags keywords
+.br
+.I fields
+.br
+.BI .] closing-text
+.RE
+.LP
+The
+.IR opening-text ,
+.IR closing-text
+and
+.I flags
+components are optional.
+Only one of the
+.I keywords
+and
+.I fields
+components need be specified.
+.LP
+The
+.I keywords
+component says to search the bibliographic databases for a reference
+that contains all the words in
+.IR keywords .
+It is an error if more than one reference if found.
+.LP
+The
+.I fields
+components specifies additional fields to replace or supplement
+those specified in the reference.
+When references are being accumulated and the
+.I keywords
+component is non-empty,
+then additional fields should be specified only on the first
+occasion that a particular reference is cited,
+and will apply to all citations of that reference.
+.LP
+The
+.I opening-text
+and
+.I closing-text
+component specifies strings to be used to bracket the label instead
+of the strings specified in the
+.B bracket-label
+command.
+If either of these components is non-empty,
+the strings specified in the
+.B bracket-label
+command will not be used;
+this behavior can be altered using the
+.B [
+and
+.B ]
+flags.
+Note that leading and trailing spaces are significant for these components.
+.LP
+The
+.I flags
+component is a list of
+non-alphanumeric characters each of which modifies the treatment
+of this particular citation.
+Unix refer will treat these flags as part of the keywords and
+so will ignore them since they are non-alphanumeric.
+The following flags are currently recognized:
+.TP
+.B #
+This says to use the label specified by the
+.B short-label
+command,
+instead of that specified by the
+.B label
+command.
+If no short label has been specified, the normal label will be used.
+Typically the short label is used with author-date labels
+and consists of only the date and possibly a disambiguating letter;
+the
+.B #
+is supposed to be suggestive of a numeric type of label.
+.TP
+.B [
+Precede
+.I opening-text
+with the first string specified in the
+.B bracket-label
+command.
+.TP
+.B ]
+Follow
+.I closing-text
+with the second string specified in the
+.B bracket-label
+command.
+.LP
+One advantages of using the
+.B [
+and
+.B ]
+flags rather than including the brackets in
+.I opening-text
+and
+.I closing-text
+is that
+you can change the style of bracket used in the document just by changing the
+.B bracket-label
+command.
+Another advantage is that sorting and merging of citations
+will not necessarily be inhibited if the flags are used.
+.LP
+If a label is to be inserted into the text,
+it will be attached to the line preceding the
+.B .[
+line.
+If there is no such line, then an extra line will be inserted before the
+.B .[
+line and a warning will be given.
+.LP
+There is no special notation for making a citation to multiple references.
+Just use a sequence of citations, one for each reference.
+Don't put anything between the citations.
+The labels for all the citations will be attached to the line preceding
+the first citation.
+The labels may also be sorted or merged.
+See the description of the
+.B <>
+label expression, and of the
+.B sort-adjacent-labels
+and
+.B abbreviate-label-ranges
+command.
+A label will not be merged if its citation has a non-empty
+.I opening-text
+or
+.IR closing-text .
+However, the labels for a citation using the
+.B ]
+flag and without any
+.I closing-text
+immediately followed by a citation using the
+.B [
+flag and without any
+.I opening-text
+may be sorted and merged
+even though the first citation's
+.I opening-text
+or the second citation's
+.I closing-text
+is non-empty.
+(If you wish to prevent this just make the first citation's
+.I closing-text
+.BR \e& .)
+.SS Commands
+Commands are contained between lines starting with
+.B .R1
+and
+.BR .R2 .
+Recognition of these lines can be prevented by the
+.B \-R
+option.
+When a
+.B .R1
+line is recognized any accumulated references are flushed out.
+Neither
+.B .R1
+nor
+.B .R2
+lines,
+nor anything between them
+is output.
+.LP
+Commands are separated by newlines or
+.BR ; s.
+.B #
+introduces a comment that extends to the end of the line
+(but does not conceal the newline).
+Each command is broken up into words.
+Words are separated by spaces or tabs.
+A word that begins with
+.B \(ts
+extends to the next
+.B \(ts
+that is not followed by another
+.BR \(ts .
+If there is no such
+.B \(ts
+the word extends to the end of the line.
+Pairs of
+.B \(ts
+in a word beginning with
+.B \(ts
+collapse to a single
+.BR \(ts .
+Neither
+.B #
+nor
+.B ;
+are recognized inside
+.BR \(ts s.
+A line can be continued by ending it with
+.BR \e ;
+this works everywhere except after a
+.BR # .
+.LP
+.ds n \fR*
+Each command
+.I name
+that is marked with \*n has an associated negative command
+.BI no- name
+that undoes the effect of
+.IR name .
+For example, the
+.B no-sort
+command specifies that references should not be sorted.
+The negative commands take no arguments.
+.LP
+In the following description each argument must be a single word;
+.I field
+is used for a single upper or lower case letter naming a field;
+.I fields
+is used for a sequence of such letters;
+.I m
+and
+.I n
+are used for a non-negative numbers;
+.I string
+is used for an arbitrary string;
+.I filename
+is used for the name of a file.
+.Tp \w'\fBabbreviate-label-ranges'u+2n
+.BI abbreviate\*n\ fields\ string1\ string2\ string3\ string4
+Abbreviate the first names of
+.IR fields .
+An initial letter will be separated from another initial letter by
+.IR string1 ,
+from the last name by
+.IR string2 ,
+and from anything else
+(such as a
+.B von
+or
+.BR de )
+by
+.IR string3 .
+These default to a period followed by a space.
+In a hyphenated first name,
+the initial of the first part of the name will be separated from the hyphen by
+.IR string4 ;
+this defaults to a period.
+No attempt is made to handle any ambiguities that might
+result from abbreviation.
+Names are abbreviated before sorting and before
+label construction.
+.TP
+.BI abbreviate-label-ranges\*n\ string
+Three or more adjacent labels that refer to consecutive references
+will be abbreviated to a label consisting
+of the first label, followed by
+.I string
+followed by the last label.
+This is mainly useful with numeric labels.
+If
+.I string
+is omitted it defaults to
+.BR \- .
+.TP
+.B accumulate\*n
+Accumulate references instead of writing out each reference
+as it is encountered.
+Accumulated references will be written out whenever a reference
+of the form
+.RS
+.IP
+.B .[
+.br
+.B $LIST$
+.br
+.B .]
+.LP
+is encountered,
+after all input files hve been processed,
+and whenever
+.B .R1
+line is recognized.
+.RE
+.TP
+.BI annotate\*n\ field\ string
+.I field
+is an annotation;
+print it at the end of the reference as a paragraph preceded by the line
+.RS
+.IP
+.BI . string
+.LP
+If
+.I macro
+is omitted it will default to
+.BR AP ;
+if
+.I field
+is also omitted it will default to
+.BR X .
+Only one field can be an annotation.
+.RE
+.TP
+.BI articles\ string \fR\|.\|.\|.
+.IR string \|.\|.\|.
+are definite or indefinite articles, and should be ignored at the beginning of
+.B T
+fields when sorting.
+Initially,
+.BR the ,
+.B a
+and
+.B an
+are recognized as articles.
+.TP
+.BI bibliography\ filename \fR\|.\|.\|.
+Write out all the references contained in the bibliographic databases
+.IR filename \|.\|.\|.
+.TP
+.BI bracket-label\ string1\ string2\ string3
+In the text, bracket each label
+with
+.I string1
+and
+.IR string2 .
+An occurrence of
+.I string2
+immediately followed by
+.I string1
+will be turned into
+.IR string3 .
+The default behavior is
+.RS
+.IP
+.B
+bracket-label \e*([. \e*(.] ", "
+.RE
+.TP
+.BI capitalize\ fields
+Convert
+.I fields
+to caps and small caps.
+.TP
+.B compatible\*n
+Recognize
+.B .R1
+and
+.B .R2
+even when followed by a character other than space or newline.
+.TP
+.BI database\ filename \fR\|.\|.\|.
+Search the bibligraphic databases
+.IR filename \|.\|.\|.
+For each
+.I filename
+if an index
+.IB filename .i
+created by
+.BR indxbib (1)
+exists, then it will be searched instead;
+each index can cover multiple databases.
+.TP
+.BI date-as-label\*n\ string
+.I string
+is a label expression that specifies a string with which to replace the
+.B D
+field after constructing the label.
+See the
+.B "Label expressions"
+subsection for a description of label expressions.
+This command is useful if you do not want explicit labels in the
+reference list, but instead want to handle any necessary
+disambiguation by qualifying the date in some way.
+The label used in the text would typically be some combination of the
+author and date.
+In most cases you should also use the
+.B no-label-in-reference
+command.
+For example,
+.RS
+.IP
+.B
+date-as-label D.+yD.y%a*D.-y
+.LP
+would attach a disambiguating letter to the year part of the
+.B D
+field in the reference.
+.RE
+.TP
+.B default-database\*n
+The default database should be searched.
+This is the default behavior, so the negative version of
+this command is more useful.
+refer determines whether the default database should be searched
+on the first occasion that it needs to do a search.
+Thus a
+.B no-default-database
+command must be given before then,
+in order to be effective.
+.TP
+.BI discard\*n\ fields
+When the reference is read,
+.I fields
+should be discarded;
+no string definitions for
+.I fields
+will be output.
+Initially,
+.I fields
+are
+.BR XYZ .
+.TP
+.BI et-al\*n\ string\ m\ n
+Control use of
+.B
+et al
+in the evaluation of
+.B @
+expressions in label expressions.
+If the number of authors needed to make the author sequence
+unambiguous is
+.I u
+and the total number of authors is
+.I t
+then the last
+.IR t \|\-\| u
+authors will be replaced by
+.I string
+provided that
+.IR t \|\-\| u
+is not less than
+.I m
+and
+.I t
+is not less than
+.IR n .
+The default behavior is
+.RS
+.IP
+.B
+et-al " et al" 2 3
+.RE
+.TP
+.BI include\ filename
+Include
+.I filename
+and interpret the contents as commands.
+.TP
+.BI join-authors\ string1\ string2\ string3
+This says how authors should be joined together.
+When there are exactly two authors, they will be joined with
+.IR string1 .
+When there are more than two authors, all but the last two will
+be joined with
+.IR string2 ,
+and the last two authors will be joined with
+.IR string3 .
+If
+.I string3
+is omitted,
+it will default to
+.IR string1 ;
+if
+.I string2
+is also omitted it will also default to
+.IR string1 .
+For example,
+.RS
+.IP
+.B
+join-authors " and " ", " ", and "
+.LP
+will restore the default method for joining authors.
+.RE
+.TP
+.B label-in-reference\*n
+When outputting the reference,
+define the string
+.B [F
+to be the reference's label.
+This is the default behavior; so the negative version
+of this command is more useful.
+.TP
+.B label-in-text\*n
+For each reference output a label in the text.
+The label will be separated from the surrounding text as described in the
+.B bracket-label
+command.
+This is the default behavior; so the negative version
+of this command is more useful.
+.TP
+.BI label\ string
+.I string
+is a label expression describing how to label each reference.
+.TP
+.BI separate-label-second-parts\ string
+When merging two-part labels, separate the second part of the second
+label from the first label with
+.IR string .
+See the description of the
+.B <>
+label expression.
+.TP
+.B move-punctuation\*n
+In the text, move any punctuation at the end of line past the label.
+It is usually a good idea to give this command unless you are using
+superscripted numbers as labels.
+.TP
+.BI reverse\*n\ string
+Reverse the fields whose names
+are in
+.IR string .
+Each field name can be followed by a number which says
+how many such fields should be reversed.
+If no number is given for a field, all such fields will be reversed.
+.TP
+.BI search-ignore\*n\ fields
+While searching for keys in databases for which no index exists,
+ignore the contents of
+.IR fields .
+Initially, fields
+.B XYZ
+are ignored.
+.TP
+.BI search-truncate\*n\ n
+Only require the first
+.I n
+characters of keys to be given.
+In effect when searching for a given key
+words in the database are truncated to the maximum of
+.I n
+and the length of the key.
+Initially
+.I n
+is 6.
+.TP
+.BI short-label\*n\ string
+.I string
+is a label expression that specifies an alternative (usually shorter)
+style of label.
+This is used when the
+.B #
+flag is given in the citation.
+When using author-date style labels, the identity of the author
+or authors is sometimes clear from the context, and so it
+may be desirable to omit the author or authors from the label.
+The
+.B short-label
+command will typically be used to specify a label containing just
+a date and possibly a disambiguating letter.
+.TP
+.BI sort\*n\ string
+Sort references according to
+.BR string .
+References will automatically be accumulated.
+.I string
+should be a list of field names, each followed by a number,
+indicating how many fields with the name should be used for sorting.
+.B +
+can be used to indicate that all the fields with the name should be used.
+Also
+.B .
+can be used to indicate the references should be sorted using the
+(tentative) label.
+(The
+.B
+Label expressions
+subsection describes the concept of a tentative label.)
+.TP
+.B sort-adjacent-labels\*n
+Sort labels that are adjacent in the text according to their
+position in the reference list.
+This command should usually be given if the
+.B abbreviate-label-ranges
+command has been given,
+or if the label expression contains a
+.B <>
+expression.
+This will have no effect unless references are being accumulated.
+.SS Label expressions
+.LP
+Label expressions can be evaluated both normally and tentatively.
+The result of normal evaluation is used for output.
+The result of tentative evaluation, called the
+.I
+tentative label,
+is used to gather the information
+that normal evaluation needs to disambiguate the label.
+Label expressions specified by the
+.B date-as-label
+and
+.B short-label
+commands are not evaluated tentatively.
+Normal and tentative evaluation are the same for all types
+of expression other than
+.BR @ ,
+.BR * ,
+and
+.B %
+expressions.
+The description below applies to normal evaluation,
+except where otherwise specified.
+.TP
+.I field
+.TQ
+.I field\ n
+The
+.IR n -th
+part of
+.IR field .
+If
+.I n
+is omitted, it defaults to 1.
+.TP
+.BI ' string '
+The characters in
+.I string
+literally.
+.TP
+.B @
+All the authors joined as specified by the
+.B join-authors
+command.
+The whole of each author's name will be used.
+However, if the references are sorted by author
+(that is the sort specification starts with
+.BR A+ ),
+then authors' last names will be used instead, provided that this does
+not introduce ambiguity,
+and also an initial subsequence of the authors may be used
+instead of all the authors, again provided that this does not
+introduce ambiguity.
+The use of only the last name for the
+.IR i -th
+author of some reference
+is considered to be ambiguous if
+there is some other reference,
+such that the first
+.IR i \|-\|1
+authors of the references are the same,
+the
+.IR i -th
+authors are not the same,
+but the
+.IR i -th
+authors' last names are the same.
+A proper initial subsequence of the sequence
+of authors for some reference is considered to be ambiguous if there is
+a reference with some other sequence of authors which also has
+that subsequence as a proper initial subsequence.
+When an initial subsequence of authors is used, the remaining
+authors are replaced by the string specified by the
+.B et-al
+command;
+this command may also specify additional requirements that must be
+met before an initial subsequence can be used.
+.B @
+tentatively evaluates to a canonical representation of the authors,
+such that authors that compare equally for sorting purpose
+will have the same representation.
+.TP
+.BI % n
+.TQ
+.B %a
+.TQ
+.B %A
+.TQ
+.B %i
+.TQ
+.B %I
+The serial number of the reference formatted according to the character
+following the
+.BR % .
+The serial number of a reference is 1 plus the number of earlier references
+with same tentative label as this reference.
+These expressions tentatively evaluate to an empty string.
+.TP
+.IB expr *
+If there is another reference with the same tentative label as
+this reference, then
+.IR expr ,
+otherwise an empty string.
+It tentatively evaluates to an empty string.
+.TP
+.IB expr + n
+.TQ
+.IB expr \- n
+The first
+.RB ( + )
+or last
+.RB ( \- )
+.I n
+upper or lower case letters or digits of
+.IR expr .
+Troff special characters (such as
+.BR \e('a )
+count as a single letter.
+Accent strings are retained but do not count towards the total.
+.TP
+.IB expr .l
+.I expr
+converted to lowercase.
+.TP
+.IB expr .u
+.I expr
+converted to uppercase.
+.TP
+.IB expr .c
+.I expr
+converted to caps and small caps.
+.TP
+.IB expr .r
+.I expr
+reversed so that the last name is first.
+.TP
+.IB expr .a
+.I expr
+with first names abbreviated.
+Note that fields specified in the
+.B abbreviate
+command are abbreviated before any labels are evaluated.
+Thus
+.B .a
+is useful only when you want a field to be abbreviated in a label
+but not in a reference.
+.TP
+.IB expr .y
+The year part of
+.IR expr .
+.TP
+.IB expr .+y
+The part of
+.I expr
+before the year, or the whole of
+.I expr
+if it does not contain a year.
+.TP
+.IB expr .\-y
+The part of
+.I expr
+after the year, or an empty string if
+.I expr
+does not contain a year.
+.TP
+.IB expr .n
+The last name part of
+.IR expr .
+.TP
+.IB expr1 \(ti expr2
+.I expr1
+except that if the last character of
+.I expr1
+is
+.B \-
+then it will be replaced by
+.IR expr2 .
+.TP
+.I expr1\ expr2
+The concatenation of
+.I expr1
+and
+.IR expr2 .
+.TP
+.IB expr1 | expr2
+If
+.I expr1
+is non-empty then
+.I expr1
+otherwise
+.IR expr2 .
+.TP
+.IB expr1 & expr2
+If
+.I expr1
+is non-empty
+then
+.I expr2
+otherwise an empty string.
+.TP
+.IB expr1 ? expr2 : expr3
+If
+.I expr1
+is non-empty
+then
+.I expr2
+otherwise
+.IR expr3 .
+.TP
+.BI < expr >
+The label is in two parts, which are separated by
+.IR expr .
+Two adjacent two-part labels which have the same first part will be
+merged by appending the second part of the second label onto the first
+label separated by the string specified in the
+.B separate-label-second-parts
+command (initially, a comma followed by a space); the resulting label
+will also be a two-part label with the same first part as before
+merging, and so additional labels can be merged into it.
+Note that it is permissible for the first part to be empty;
+this maybe desirable for expressions used in the
+.B short-label
+command.
+.TP
+.BI ( expr )
+The same as
+.IR expr .
+Used for grouping.
+.LP
+The above expressions are listed in order of precedence
+(highest first);
+.B &
+and
+.B |
+have the same precedence.
+.SS Macro interface
+Each reference starts with a call to the macro
+.BR ]- .
+The string
+.B [F
+will be defined to be the label for this reference,
+unless the
+.B no-label-in-reference
+command has been given.
+There then follows a series of string definitions,
+one for each field:
+string
+.BI [ X
+corresponds to field
+.IR X .
+The number register
+.B [P
+is set to 1 if the
+.B P
+field contains a range of pages.
+The
+.BR [T ,
+.B [A
+and
+.B [O
+number registers are set to 1 according as the
+.BR T ,
+.B A
+and
+.B O
+fields end with one of the characters
+.BR .?! .
+The
+.B [E
+number register will be set to 1 if the
+.B [E
+string contains more than one name.
+The reference is followed by a call to the
+.B ][
+macro.
+The first argument to this macro gives a number representing
+the type of the reference.
+If a reference contains a
+.B J
+field, it will be classified as type 1,
+otherwise if it contains a
+.B B
+field, it will type 3,
+otherwise if it contains a
+.B G
+or
+.B R
+field it will be type 4,
+otherwise if contains a
+.B I
+field it will be type 2,
+otherwise it will be type 0.
+The second argument is a symbolic name for the type:
+.BR other ,
+.BR journal-article ,
+.BR book ,
+.B article-in-book
+or
+.BR tech-report .
+Groups of references that have been accumulated
+or are produced by the
+.B bibliography
+command are preceded by a call to the
+.B ]<
+macro and followed by a call to the
+.B ]>
+macro.
+.SH FILES
+.Tp \w'\fB/usr/share/dict/papers/Ind'u+2n
+.B /usr/share/dict/papers/Ind
+Default database.
+.TP
+.IB file .i
+Index files.
+.SH "SEE ALSO"
+.BR indxbib (1),
+.BR lookbib (1),
+.BR lkbib (1)
+.br
+.SH BUGS
+In label expressions,
+.B <>
+expressions are ignored inside
+.BI . char
+expressions.
diff --git a/gnu/usr.bin/groff/refer/refer.cc b/gnu/usr.bin/groff/refer/refer.cc
new file mode 100644
index 000000000000..cb6e218e3ea1
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/refer.cc
@@ -0,0 +1,1221 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "refer.h"
+#include "refid.h"
+#include "ref.h"
+#include "token.h"
+#include "search.h"
+#include "command.h"
+
+const char PRE_LABEL_MARKER = '\013';
+const char POST_LABEL_MARKER = '\014';
+const char LABEL_MARKER = '\015'; // label_type is added on
+
+#define FORCE_LEFT_BRACKET 04
+#define FORCE_RIGHT_BRACKET 010
+
+static FILE *outfp = stdout;
+
+string capitalize_fields;
+string reverse_fields;
+string abbreviate_fields;
+string period_before_last_name = ". ";
+string period_before_initial = ".";
+string period_before_hyphen = "";
+string period_before_other = ". ";
+string sort_fields;
+int annotation_field = -1;
+string annotation_macro;
+string discard_fields = "XYZ";
+string pre_label = "\\*([.";
+string post_label = "\\*(.]";
+string sep_label = ", ";
+int accumulate = 0;
+int move_punctuation = 0;
+int abbreviate_label_ranges = 0;
+string label_range_indicator;
+int label_in_text = 1;
+int label_in_reference = 1;
+int date_as_label = 0;
+int sort_adjacent_labels = 0;
+// Join exactly two authors with this.
+string join_authors_exactly_two = " and ";
+// When there are more than two authors join the last two with this.
+string join_authors_last_two = ", and ";
+// Otherwise join authors with this.
+string join_authors_default = ", ";
+string separate_label_second_parts = ", ";
+// Use this string to represent that there are other authors.
+string et_al = " et al";
+// Use et al only if it can replace at least this many authors.
+int et_al_min_elide = 2;
+// Use et al only if the total number of authors is at least this.
+int et_al_min_total = 3;
+
+
+int compatible_flag = 0;
+
+int short_label_flag = 0;
+
+static int recognize_R1_R2 = 1;
+
+search_list database_list;
+int search_default = 1;
+static int default_database_loaded = 0;
+
+static reference **citation = 0;
+static int ncitations = 0;
+static int citation_max = 0;
+
+static reference **reference_hash_table = 0;
+static int hash_table_size;
+static int nreferences = 0;
+
+static int need_syncing = 0;
+string pending_line;
+string pending_lf_lines;
+
+static void output_pending_line();
+static unsigned immediately_handle_reference(const string &);
+static void immediately_output_references();
+static unsigned store_reference(const string &);
+static void divert_to_temporary_file();
+static reference *make_reference(const string &, unsigned *);
+static void usage();
+static void do_file(const char *);
+static void split_punct(string &line, string &punct);
+static void output_citation_group(reference **v, int n, label_type, FILE *fp);
+static void possibly_load_default_database();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ outfp = stdout;
+ int finished_options = 0;
+ int bib_flag = 0;
+ int done_spec = 0;
+
+ for (--argc, ++argv;
+ !finished_options && argc > 0 && argv[0][0] == '-'
+ && argv[0][1] != '\0';
+ argv++, argc--) {
+ const char *opt = argv[0] + 1;
+ while (opt != 0 && *opt != '\0') {
+ switch (*opt) {
+ case 'C':
+ compatible_flag = 1;
+ opt++;
+ break;
+ case 'B':
+ bib_flag = 1;
+ label_in_reference = 0;
+ label_in_text = 0;
+ ++opt;
+ if (*opt == '\0') {
+ annotation_field = 'X';
+ annotation_macro = "AP";
+ }
+ else if (csalnum(opt[0]) && opt[1] == '.' && opt[2] != '\0') {
+ annotation_field = opt[0];
+ annotation_macro = opt + 2;
+ }
+ opt = 0;
+ break;
+ case 'P':
+ move_punctuation = 1;
+ opt++;
+ break;
+ case 'R':
+ recognize_R1_R2 = 0;
+ opt++;
+ break;
+ case 'S':
+ // Not a very useful spec.
+ set_label_spec("(A.n|Q)', '(D.y|D)");
+ done_spec = 1;
+ pre_label = " (";
+ post_label = ")";
+ sep_label = "; ";
+ opt++;
+ break;
+ case 'V':
+ verify_flag = 1;
+ opt++;
+ break;
+ case 'f':
+ {
+ const char *num = 0;
+ if (*++opt == '\0') {
+ if (argc > 1) {
+ num = *++argv;
+ --argc;
+ }
+ else {
+ error("option `f' requires an argument");
+ usage();
+ }
+ }
+ else {
+ num = opt;
+ opt = 0;
+ }
+ for (const char *ptr = num; *ptr; ptr++)
+ if (!csdigit(*ptr)) {
+ error("bad character `%1' in argument to -f option", *ptr);
+ break;
+ }
+ if (*ptr == '\0') {
+ string spec;
+ spec = '%';
+ spec += num;
+ spec += '\0';
+ set_label_spec(spec.contents());
+ done_spec = 1;
+ }
+ break;
+ }
+ case 'b':
+ label_in_text = 0;
+ label_in_reference = 0;
+ opt++;
+ break;
+ case 'e':
+ accumulate = 1;
+ opt++;
+ break;
+ case 'c':
+ capitalize_fields = ++opt;
+ opt = 0;
+ break;
+ case 'k':
+ {
+ char buf[5];
+ if (csalpha(*++opt))
+ buf[0] = *opt++;
+ else {
+ if (*opt != '\0')
+ error("bad field name `%1'", *opt++);
+ buf[0] = 'L';
+ }
+ buf[1] = '~';
+ buf[2] = '%';
+ buf[3] = 'a';
+ buf[4] = '\0';
+ set_label_spec(buf);
+ done_spec = 1;
+ }
+ break;
+ case 'a':
+ {
+ for (const char *ptr = ++opt; *ptr; ptr++)
+ if (!csdigit(*ptr)) {
+ error("argument to `a' option not a number");
+ break;
+ }
+ if (*ptr == '\0') {
+ reverse_fields = 'A';
+ reverse_fields += opt;
+ }
+ opt = 0;
+ }
+ break;
+ case 'i':
+ linear_ignore_fields = ++opt;
+ opt = 0;
+ break;
+ case 'l':
+ {
+ char buf[INT_DIGITS*2 + 11]; // A.n+2D.y-3%a
+ strcpy(buf, "A.n");
+ if (*++opt != '\0' && *opt != ',') {
+ char *ptr;
+ long n = strtol(opt, &ptr, 10);
+ if (n == 0 && ptr == opt) {
+ error("bad integer `%1' in `l' option", opt);
+ opt = 0;
+ break;
+ }
+ if (n < 0)
+ n = 0;
+ opt = ptr;
+ sprintf(strchr(buf, '\0'), "+%d", n);
+ }
+ strcat(buf, "D.y");
+ if (*opt == ',')
+ opt++;
+ if (*opt != '\0') {
+ char *ptr;
+ long n = strtol(opt, &ptr, 10);
+ if (n == 0 && ptr == opt) {
+ error("bad integer `%1' in `l' option", opt);
+ opt = 0;
+ break;
+ }
+ if (n < 0)
+ n = 0;
+ sprintf(strchr(buf, '\0'), "-%d", n);
+ opt = ptr;
+ if (*opt != '\0')
+ error("argument to `l' option not of form `m,n'");
+ }
+ strcat(buf, "%a");
+ if (!set_label_spec(buf))
+ assert(0);
+ done_spec = 1;
+ }
+ break;
+ case 'n':
+ search_default = 0;
+ opt++;
+ break;
+ case 'p':
+ {
+ const char *filename = 0;
+ if (*++opt == '\0') {
+ if (argc > 1) {
+ filename = *++argv;
+ argc--;
+ }
+ else {
+ error("option `p' requires an argument");
+ usage();
+ }
+ }
+ else {
+ filename = opt;
+ opt = 0;
+ }
+ database_list.add_file(filename);
+ }
+ break;
+ case 's':
+ if (*++opt == '\0')
+ sort_fields = "AD";
+ else {
+ sort_fields = opt;
+ opt = 0;
+ }
+ accumulate = 1;
+ break;
+ case 't':
+ {
+ char *ptr;
+ long n = strtol(opt, &ptr, 10);
+ if (n == 0 && ptr == opt) {
+ error("bad integer `%1' in `t' option", opt);
+ opt = 0;
+ break;
+ }
+ if (n < 1)
+ n = 1;
+ linear_truncate_len = int(n);
+ opt = ptr;
+ break;
+ }
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU refer version %s\n", version_string);
+ fflush(stderr);
+ opt++;
+ break;
+ }
+ case '-':
+ if (opt[1] == '\0') {
+ finished_options = 1;
+ opt++;
+ break;
+ }
+ // fall through
+ default:
+ error("unrecognized option `%1'", *opt);
+ usage();
+ break;
+ }
+ }
+ }
+ if (!done_spec)
+ set_label_spec("%1");
+ if (argc <= 0) {
+ if (bib_flag)
+ do_bib("-");
+ else
+ do_file("-");
+ }
+ else {
+ for (int i = 0; i < argc; i++) {
+ if (bib_flag)
+ do_bib(argv[i]);
+ else
+ do_file(argv[i]);
+ }
+ }
+ if (accumulate)
+ output_references();
+ if (fflush(stdout) < 0)
+ fatal("output error");
+ exit(0);
+}
+
+static void usage()
+{
+ fprintf(stderr,
+"usage: %s [-benvCPRS] [-aN] [-cXYZ] [-fN] [-iXYZ] [-kX] [-lM,N] [-p file]\n"
+" [-sXYZ] [-tN] [-BL.M] [files ...]\n",
+ program_name);
+ exit(1);
+}
+
+static void possibly_load_default_database()
+{
+ if (search_default && !default_database_loaded) {
+ char *filename = getenv("REFER");
+ if (filename)
+ database_list.add_file(filename);
+ else
+ database_list.add_file(DEFAULT_INDEX, 1);
+ default_database_loaded = 1;
+ }
+}
+
+static int is_list(const string &str)
+{
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ while (end > start && csspace(end[-1]))
+ end--;
+ while (start < end && csspace(*start))
+ start++;
+ return end - start == 6 && memcmp(start, "$LIST$", 6) == 0;
+}
+
+static void do_file(const char *filename)
+{
+ FILE *fp;
+ if (strcmp(filename, "-") == 0) {
+ fp = stdin;
+ }
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ current_filename = filename;
+ }
+ fprintf(outfp, ".lf 1 %s\n", filename);
+ string line;
+ current_lineno = 0;
+ for (;;) {
+ line.clear();
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF) {
+ if (line.length() > 0)
+ line += '\n';
+ break;
+ }
+ if (illegal_input_char(c))
+ error("illegal input character code %1", c);
+ else {
+ line += c;
+ if (c == '\n')
+ break;
+ }
+ }
+ int len = line.length();
+ if (len == 0)
+ break;
+ current_lineno++;
+ if (len >= 2 && line[0] == '.' && line[1] == '[') {
+ int start_lineno = current_lineno;
+ int start_of_line = 1;
+ string str;
+ string post;
+ string pre(line.contents() + 2, line.length() - 3);
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF) {
+ error_with_file_and_line(current_filename, start_lineno,
+ "missing `.]' line");
+ break;
+ }
+ if (start_of_line)
+ current_lineno++;
+ if (start_of_line && c == '.') {
+ int d = getc(fp);
+ if (d == ']') {
+ while ((d = getc(fp)) != '\n' && d != EOF) {
+ if (illegal_input_char(d))
+ error("illegal input character code %1", d);
+ else
+ post += d;
+ }
+ break;
+ }
+ if (d != EOF)
+ ungetc(d, fp);
+ }
+ if (illegal_input_char(c))
+ error("illegal input character code %1", c);
+ else
+ str += c;
+ start_of_line = (c == '\n');
+ }
+ if (is_list(str)) {
+ output_pending_line();
+ if (accumulate)
+ output_references();
+ else
+ error("found `$LIST$' but not accumulating references");
+ }
+ else {
+ unsigned flags = (accumulate
+ ? store_reference(str)
+ : immediately_handle_reference(str));
+ if (label_in_text) {
+ if (accumulate && outfp == stdout)
+ divert_to_temporary_file();
+ if (pending_line.length() == 0) {
+ warning("can't attach citation to previous line");
+ }
+ else
+ pending_line.set_length(pending_line.length() - 1);
+ string punct;
+ if (move_punctuation)
+ split_punct(pending_line, punct);
+ int have_text = pre.length() > 0 || post.length() > 0;
+ label_type lt = label_type(flags & ~(FORCE_LEFT_BRACKET
+ |FORCE_RIGHT_BRACKET));
+ if ((flags & FORCE_LEFT_BRACKET) || !have_text)
+ pending_line += PRE_LABEL_MARKER;
+ pending_line += pre;
+ pending_line += LABEL_MARKER + lt;
+ pending_line += post;
+ if ((flags & FORCE_RIGHT_BRACKET) || !have_text)
+ pending_line += POST_LABEL_MARKER;
+ pending_line += punct;
+ pending_line += '\n';
+ }
+ }
+ need_syncing = 1;
+ }
+ else if (len >= 4
+ && line[0] == '.' && line[1] == 'l' && line[2] == 'f'
+ && (compatible_flag || line[3] == '\n' || line[3] == ' ')) {
+ pending_lf_lines += line;
+ line += '\0';
+ if (interpret_lf_args(line.contents() + 3))
+ current_lineno--;
+ }
+ else if (recognize_R1_R2
+ && len >= 4
+ && line[0] == '.' && line[1] == 'R' && line[2] == '1'
+ && (compatible_flag || line[3] == '\n' || line[3] == ' ')) {
+ line.clear();
+ int start_of_line = 1;
+ int start_lineno = current_lineno;
+ for (;;) {
+ int c = getc(fp);
+ if (c != EOF && start_of_line)
+ current_lineno++;
+ if (start_of_line && c == '.') {
+ c = getc(fp);
+ if (c == 'R') {
+ c = getc(fp);
+ if (c == '2') {
+ c = getc(fp);
+ if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {
+ while (c != EOF && c != '\n')
+ c = getc(fp);
+ break;
+ }
+ else {
+ line += '.';
+ line += 'R';
+ line += '2';
+ }
+ }
+ else {
+ line += '.';
+ line += 'R';
+ }
+ }
+ else
+ line += '.';
+ }
+ if (c == EOF) {
+ error_with_file_and_line(current_filename, start_lineno,
+ "missing `.R2' line");
+ break;
+ }
+ if (illegal_input_char(c))
+ error("illegal input character code %1", int(c));
+ else {
+ line += c;
+ start_of_line = c == '\n';
+ }
+ }
+ output_pending_line();
+ if (accumulate)
+ output_references();
+ else
+ nreferences = 0;
+ process_commands(line, current_filename, start_lineno + 1);
+ need_syncing = 1;
+ }
+ else {
+ output_pending_line();
+ pending_line = line;
+ }
+ }
+ need_syncing = 0;
+ output_pending_line();
+ if (fp != stdin)
+ fclose(fp);
+}
+
+class label_processing_state {
+ enum {
+ NORMAL,
+ PENDING_LABEL,
+ PENDING_LABEL_POST,
+ PENDING_LABEL_POST_PRE,
+ PENDING_POST
+ } state;
+ label_type type; // type of pending labels
+ int count; // number of pending labels
+ reference **rptr; // pointer to next reference
+ int rcount; // number of references left
+ FILE *fp;
+ int handle_pending(int c);
+public:
+ label_processing_state(reference **, int, FILE *);
+ ~label_processing_state();
+ void process(int c);
+};
+
+static void output_pending_line()
+{
+ if (label_in_text && !accumulate && ncitations > 0) {
+ label_processing_state state(citation, ncitations, outfp);
+ int len = pending_line.length();
+ for (int i = 0; i < len; i++)
+ state.process((unsigned char)(pending_line[i]));
+ }
+ else
+ put_string(pending_line, outfp);
+ pending_line.clear();
+ if (pending_lf_lines.length() > 0) {
+ put_string(pending_lf_lines, outfp);
+ pending_lf_lines.clear();
+ }
+ if (!accumulate)
+ immediately_output_references();
+ if (need_syncing) {
+ fprintf(outfp, ".lf %d %s\n", current_lineno, current_filename);
+ need_syncing = 0;
+ }
+}
+
+static void split_punct(string &line, string &punct)
+{
+ const char *start = line.contents();
+ const char *end = start + line.length();
+ const char *ptr = start;
+ const char *last_token_start = 0;
+ for (;;) {
+ if (ptr >= end)
+ break;
+ last_token_start = ptr;
+ if (*ptr == PRE_LABEL_MARKER || *ptr == POST_LABEL_MARKER
+ || (*ptr >= LABEL_MARKER && *ptr < LABEL_MARKER + N_LABEL_TYPES))
+ ptr++;
+ else if (!get_token(&ptr, end))
+ break;
+ }
+ if (last_token_start) {
+ const token_info *ti = lookup_token(last_token_start, end);
+ if (ti->is_punct()) {
+ punct.append(last_token_start, end - last_token_start);
+ line.set_length(last_token_start - start);
+ }
+ }
+}
+
+static void divert_to_temporary_file()
+{
+ outfp = xtmpfile();
+}
+
+static void store_citation(reference *ref)
+{
+ if (ncitations >= citation_max) {
+ if (citation == 0)
+ citation = new reference*[citation_max = 100];
+ else {
+ reference **old_citation = citation;
+ citation_max *= 2;
+ citation = new reference *[citation_max];
+ memcpy(citation, old_citation, ncitations*sizeof(reference *));
+ a_delete old_citation;
+ }
+ }
+ citation[ncitations++] = ref;
+}
+
+static unsigned store_reference(const string &str)
+{
+ if (reference_hash_table == 0) {
+ reference_hash_table = new reference *[17];
+ hash_table_size = 17;
+ for (int i = 0; i < hash_table_size; i++)
+ reference_hash_table[i] = 0;
+ }
+ unsigned flags;
+ reference *ref = make_reference(str, &flags);
+ ref->compute_hash_code();
+ unsigned h = ref->hash();
+ for (reference **ptr = reference_hash_table + (h % hash_table_size);
+ *ptr != 0;
+ ((ptr == reference_hash_table)
+ ? (ptr = reference_hash_table + hash_table_size - 1)
+ : --ptr))
+ if (same_reference(**ptr, *ref))
+ break;
+ if (*ptr != 0) {
+ if (ref->is_merged())
+ warning("fields ignored because reference already used");
+ delete ref;
+ ref = *ptr;
+ }
+ else {
+ *ptr = ref;
+ ref->set_number(nreferences);
+ nreferences++;
+ ref->pre_compute_label();
+ ref->compute_sort_key();
+ if (nreferences*2 >= hash_table_size) {
+ // Rehash it.
+ reference **old_table = reference_hash_table;
+ int old_size = hash_table_size;
+ hash_table_size = next_size(hash_table_size);
+ reference_hash_table = new reference*[hash_table_size];
+ int i;
+ for (i = 0; i < hash_table_size; i++)
+ reference_hash_table[i] = 0;
+ for (i = 0; i < old_size; i++)
+ if (old_table[i]) {
+ for (reference **p = (reference_hash_table
+ + (old_table[i]->hash() % hash_table_size));
+ *p;
+ ((p == reference_hash_table)
+ ? (p = reference_hash_table + hash_table_size - 1)
+ : --p))
+ ;
+ *p = old_table[i];
+ }
+ a_delete old_table;
+ }
+ }
+ if (label_in_text)
+ store_citation(ref);
+ return flags;
+}
+
+unsigned immediately_handle_reference(const string &str)
+{
+ unsigned flags;
+ reference *ref = make_reference(str, &flags);
+ ref->set_number(nreferences);
+ if (label_in_text || label_in_reference) {
+ ref->pre_compute_label();
+ ref->immediate_compute_label();
+ }
+ nreferences++;
+ store_citation(ref);
+ return flags;
+}
+
+static void immediately_output_references()
+{
+ for (int i = 0; i < ncitations; i++) {
+ reference *ref = citation[i];
+ if (label_in_reference) {
+ fputs(".ds [F ", outfp);
+ const string &label = ref->get_label(NORMAL_LABEL);
+ if (label.length() > 0
+ && (label[0] == ' ' || label[0] == '\\' || label[0] == '"'))
+ putc('"', outfp);
+ put_string(label, outfp);
+ putc('\n', outfp);
+ }
+ ref->output(outfp);
+ delete ref;
+ }
+ ncitations = 0;
+}
+
+static void output_citation_group(reference **v, int n, label_type type,
+ FILE *fp)
+{
+ if (sort_adjacent_labels) {
+ // Do an insertion sort. Usually n will be very small.
+ for (int i = 1; i < n; i++) {
+ int num = v[i]->get_number();
+ reference *temp = v[i];
+ for (int j = i - 1; j >= 0 && v[j]->get_number() > num; j--)
+ v[j + 1] = v[j];
+ v[j + 1] = temp;
+ }
+ }
+ // This messes up if !accumulate.
+ if (accumulate && n > 1) {
+ // remove duplicates
+ int j = 1;
+ for (int i = 1; i < n; i++)
+ if (v[i]->get_label(type) != v[i - 1]->get_label(type))
+ v[j++] = v[i];
+ n = j;
+ }
+ string merged_label;
+ for (int i = 0; i < n; i++) {
+ int nmerged = v[i]->merge_labels(v + i + 1, n - i - 1, type, merged_label);
+ if (nmerged > 0) {
+ put_string(merged_label, fp);
+ i += nmerged;
+ }
+ else
+ put_string(v[i]->get_label(type), fp);
+ if (i < n - 1)
+ put_string(sep_label, fp);
+ }
+}
+
+
+label_processing_state::label_processing_state(reference **p, int n, FILE *f)
+: state(NORMAL), count(0), rptr(p), rcount(n), fp(f)
+{
+}
+
+label_processing_state::~label_processing_state()
+{
+ int handled = handle_pending(EOF);
+ assert(!handled);
+ assert(rcount == 0);
+}
+
+int label_processing_state::handle_pending(int c)
+{
+ switch (state) {
+ case NORMAL:
+ break;
+ case PENDING_LABEL:
+ if (c == POST_LABEL_MARKER) {
+ state = PENDING_LABEL_POST;
+ return 1;
+ }
+ else {
+ output_citation_group(rptr, count, type, fp);
+ rptr += count ;
+ rcount -= count;
+ state = NORMAL;
+ }
+ break;
+ case PENDING_LABEL_POST:
+ if (c == PRE_LABEL_MARKER) {
+ state = PENDING_LABEL_POST_PRE;
+ return 1;
+ }
+ else {
+ output_citation_group(rptr, count, type, fp);
+ rptr += count;
+ rcount -= count;
+ put_string(post_label, fp);
+ state = NORMAL;
+ }
+ break;
+ case PENDING_LABEL_POST_PRE:
+ if (c >= LABEL_MARKER
+ && c < LABEL_MARKER + N_LABEL_TYPES
+ && c - LABEL_MARKER == type) {
+ count += 1;
+ state = PENDING_LABEL;
+ return 1;
+ }
+ else {
+ output_citation_group(rptr, count, type, fp);
+ rptr += count;
+ rcount -= count;
+ put_string(sep_label, fp);
+ state = NORMAL;
+ }
+ break;
+ case PENDING_POST:
+ if (c == PRE_LABEL_MARKER) {
+ put_string(sep_label, fp);
+ state = NORMAL;
+ return 1;
+ }
+ else {
+ put_string(post_label, fp);
+ state = NORMAL;
+ }
+ break;
+ }
+ return 0;
+}
+
+void label_processing_state::process(int c)
+{
+ if (handle_pending(c))
+ return;
+ assert(state == NORMAL);
+ switch (c) {
+ case PRE_LABEL_MARKER:
+ put_string(pre_label, fp);
+ state = NORMAL;
+ break;
+ case POST_LABEL_MARKER:
+ state = PENDING_POST;
+ break;
+ case LABEL_MARKER:
+ case LABEL_MARKER + 1:
+ count = 1;
+ state = PENDING_LABEL;
+ type = label_type(c - LABEL_MARKER);
+ break;
+ default:
+ state = NORMAL;
+ putc(c, fp);
+ break;
+ }
+}
+
+extern "C" {
+
+static int rcompare(const void *p1, const void *p2)
+{
+ return compare_reference(**(reference **)p1, **(reference **)p2);
+}
+
+}
+
+void output_references()
+{
+ assert(accumulate);
+ if (nreferences > 0) {
+ int j = 0;
+ int i;
+ for (i = 0; i < hash_table_size; i++)
+ if (reference_hash_table[i] != 0)
+ reference_hash_table[j++] = reference_hash_table[i];
+ assert(j == nreferences);
+ for (; j < hash_table_size; j++)
+ reference_hash_table[j] = 0;
+ qsort(reference_hash_table, nreferences, sizeof(reference*), rcompare);
+ for (i = 0; i < nreferences; i++)
+ reference_hash_table[i]->set_number(i);
+ compute_labels(reference_hash_table, nreferences);
+ }
+ if (outfp != stdout) {
+ rewind(outfp);
+ {
+ label_processing_state state(citation, ncitations, stdout);
+ int c;
+ while ((c = getc(outfp)) != EOF)
+ state.process(c);
+ }
+ ncitations = 0;
+ fclose(outfp);
+ outfp = stdout;
+ }
+ if (nreferences > 0) {
+ fputs(".]<\n", outfp);
+ for (int i = 0; i < nreferences; i++) {
+ if (sort_fields.length() > 0)
+ reference_hash_table[i]->print_sort_key_comment(outfp);
+ if (label_in_reference) {
+ fputs(".ds [F ", outfp);
+ const string &label = reference_hash_table[i]->get_label(NORMAL_LABEL);
+ if (label.length() > 0
+ && (label[0] == ' ' || label[0] == '\\' || label[0] == '"'))
+ putc('"', outfp);
+ put_string(label, outfp);
+ putc('\n', outfp);
+ }
+ reference_hash_table[i]->output(outfp);
+ delete reference_hash_table[i];
+ reference_hash_table[i] = 0;
+ }
+ fputs(".]>\n", outfp);
+ nreferences = 0;
+ }
+ clear_labels();
+}
+
+static reference *find_reference(const char *query, int query_len)
+{
+ // This is so that error messages look better.
+ while (query_len > 0 && csspace(query[query_len - 1]))
+ query_len--;
+ string str;
+ for (int i = 0; i < query_len; i++)
+ str += query[i] == '\n' ? ' ' : query[i];
+ str += '\0';
+ possibly_load_default_database();
+ search_list_iterator iter(&database_list, str.contents());
+ reference_id rid;
+ const char *start;
+ int len;
+ if (!iter.next(&start, &len, &rid)) {
+ error("no matches for `%1'", str.contents());
+ return 0;
+ }
+ const char *end = start + len;
+ while (start < end) {
+ if (*start == '%')
+ break;
+ while (start < end && *start++ != '\n')
+ ;
+ }
+ if (start >= end) {
+ error("found a reference for `%1' but it didn't contain any fields",
+ str.contents());
+ return 0;
+ }
+ reference *result = new reference(start, end - start, &rid);
+ if (iter.next(&start, &len, &rid))
+ warning("multiple matches for `%1'", str.contents());
+ return result;
+}
+
+static reference *make_reference(const string &str, unsigned *flagsp)
+{
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ const char *ptr = start;
+ while (ptr < end) {
+ if (*ptr == '%')
+ break;
+ while (ptr < end && *ptr++ != '\n')
+ ;
+ }
+ *flagsp = 0;
+ for (; start < ptr; start++) {
+ if (*start == '#')
+ *flagsp = (SHORT_LABEL | (*flagsp & (FORCE_RIGHT_BRACKET
+ | FORCE_LEFT_BRACKET)));
+ else if (*start == '[')
+ *flagsp |= FORCE_LEFT_BRACKET;
+ else if (*start == ']')
+ *flagsp |= FORCE_RIGHT_BRACKET;
+ else if (!csspace(*start))
+ break;
+ }
+ if (start >= end) {
+ error("empty reference");
+ return new reference;
+ }
+ reference *database_ref = 0;
+ if (start < ptr)
+ database_ref = find_reference(start, ptr - start);
+ reference *inline_ref = 0;
+ if (ptr < end)
+ inline_ref = new reference(ptr, end - ptr);
+ if (inline_ref) {
+ if (database_ref) {
+ database_ref->merge(*inline_ref);
+ delete inline_ref;
+ return database_ref;
+ }
+ else
+ return inline_ref;
+ }
+ else if (database_ref)
+ return database_ref;
+ else
+ return new reference;
+}
+
+static void do_ref(const string &str)
+{
+ if (accumulate)
+ (void)store_reference(str);
+ else {
+ (void)immediately_handle_reference(str);
+ immediately_output_references();
+ }
+}
+
+static void trim_blanks(string &str)
+{
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ while (end > start && end[-1] != '\n' && csspace(end[-1]))
+ --end;
+ str.set_length(end - start);
+}
+
+void do_bib(const char *filename)
+{
+ FILE *fp;
+ if (strcmp(filename, "-") == 0)
+ fp = stdin;
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ current_filename = filename;
+ }
+ enum {
+ START, MIDDLE, BODY, BODY_START, BODY_BLANK, BODY_DOT
+ } state = START;
+ string body;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c)) {
+ error("illegal input character code %1", c);
+ continue;
+ }
+ switch (state) {
+ case START:
+ if (c == '%') {
+ body = c;
+ state = BODY;
+ }
+ else if (c != '\n')
+ state = MIDDLE;
+ break;
+ case MIDDLE:
+ if (c == '\n')
+ state = START;
+ break;
+ case BODY:
+ body += c;
+ if (c == '\n')
+ state = BODY_START;
+ break;
+ case BODY_START:
+ if (c == '\n') {
+ do_ref(body);
+ state = START;
+ }
+ else if (c == '.')
+ state = BODY_DOT;
+ else if (csspace(c)) {
+ state = BODY_BLANK;
+ body += c;
+ }
+ else {
+ body += c;
+ state = BODY;
+ }
+ break;
+ case BODY_BLANK:
+ if (c == '\n') {
+ trim_blanks(body);
+ do_ref(body);
+ state = START;
+ }
+ else if (csspace(c))
+ body += c;
+ else {
+ body += c;
+ state = BODY;
+ }
+ break;
+ case BODY_DOT:
+ if (c == ']') {
+ do_ref(body);
+ state = MIDDLE;
+ }
+ else {
+ body += '.';
+ body += c;
+ state = c == '\n' ? BODY_START : BODY;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ if (c == '\n')
+ current_lineno++;
+ }
+ switch (state) {
+ case START:
+ case MIDDLE:
+ break;
+ case BODY:
+ body += '\n';
+ do_ref(body);
+ break;
+ case BODY_DOT:
+ case BODY_START:
+ do_ref(body);
+ break;
+ case BODY_BLANK:
+ trim_blanks(body);
+ do_ref(body);
+ break;
+ }
+ fclose(fp);
+}
+
+// from the Dragon Book
+
+unsigned hash_string(const char *s, int len)
+{
+ const char *end = s + len;
+ unsigned h = 0, g;
+ while (s < end) {
+ h <<= 4;
+ h += *s++;
+ if ((g = h & 0xf0000000) != 0) {
+ h ^= g >> 24;
+ h ^= g;
+ }
+ }
+ return h;
+}
+
+int next_size(int n)
+{
+ static const int table_sizes[] = {
+ 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009,
+ 80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009,
+ 16000057, 32000011, 64000031, 128000003, 0
+ };
+
+ for (const int *p = table_sizes; *p <= n && *p != 0; p++)
+ ;
+ assert(*p != 0);
+ return *p;
+}
+
diff --git a/gnu/usr.bin/groff/refer/refer.h b/gnu/usr.bin/groff/refer/refer.h
new file mode 100644
index 000000000000..932b85536e62
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/refer.h
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "cmap.h"
+
+#include "defs.h"
+
+unsigned hash_string(const char *, int);
+int next_size(int);
+
+extern string capitalize_fields;
+extern string reverse_fields;
+extern string abbreviate_fields;
+extern string period_before_last_name;
+extern string period_before_initial;
+extern string period_before_hyphen;
+extern string period_before_other;
+extern string sort_fields;
+extern int annotation_field;
+extern string annotation_macro;
+extern string discard_fields;
+extern string articles;
+extern int abbreviate_label_ranges;
+extern string label_range_indicator;
+extern int date_as_label;
+extern string join_authors_exactly_two;
+extern string join_authors_last_two;
+extern string join_authors_default;
+extern string separate_label_second_parts;
+extern string et_al;
+extern int et_al_min_elide;
+extern int et_al_min_total;
+
+extern int compatible_flag;
+
+extern int set_label_spec(const char *);
+extern int set_date_label_spec(const char *);
+extern int set_short_label_spec(const char *);
+
+extern int short_label_flag;
+
+void clear_labels();
+void command_error(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+struct reference;
+
+void compute_labels(reference **, int);
diff --git a/gnu/usr.bin/groff/refer/token.cc b/gnu/usr.bin/groff/refer/token.cc
new file mode 100644
index 000000000000..8847081bd482
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/token.cc
@@ -0,0 +1,370 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "refer.h"
+#include "token.h"
+
+#define TOKEN_TABLE_SIZE 1009
+// I believe in Icelandic thorn sorts after z.
+#define THORN_SORT_KEY "{"
+
+struct token_table_entry {
+ const char *tok;
+ token_info ti;
+ token_table_entry();
+};
+
+token_table_entry token_table[TOKEN_TABLE_SIZE];
+int ntokens = 0;
+
+static void skip_name(const char **ptr, const char *end)
+{
+ if (*ptr < end) {
+ switch (*(*ptr)++) {
+ case '(':
+ if (*ptr < end) {
+ *ptr += 1;
+ if (*ptr < end)
+ *ptr += 1;
+ }
+ break;
+ case '[':
+ while (*ptr < end)
+ if (*(*ptr)++ == ']')
+ break;
+ break;
+ }
+ }
+}
+
+int get_token(const char **ptr, const char *end)
+{
+ if (*ptr >= end)
+ return 0;
+ char c = *(*ptr)++;
+ if (c == '\\' && *ptr < end) {
+ switch (**ptr) {
+ default:
+ *ptr += 1;
+ break;
+ case '(':
+ case '[':
+ skip_name(ptr, end);
+ break;
+ case '*':
+ case 'f':
+ *ptr += 1;
+ skip_name(ptr, end);
+ break;
+ }
+ }
+ return 1;
+}
+
+token_info::token_info()
+: type(TOKEN_OTHER), sort_key(0), other_case(0)
+{
+}
+
+void token_info::set(token_type t, const char *sk, const char *oc)
+{
+ assert(oc == 0 || t == TOKEN_UPPER || t == TOKEN_LOWER);
+ type = t;
+ sort_key = sk;
+ other_case = oc;
+}
+
+void token_info::sortify(const char *start, const char *end, string &result)
+ const
+{
+ if (sort_key)
+ result += sort_key;
+ else if (type == TOKEN_UPPER || type == TOKEN_LOWER) {
+ for (; start < end; start++)
+ if (csalpha(*start))
+ result += cmlower(*start);
+ }
+}
+
+int token_info::sortify_non_empty(const char *start, const char *end) const
+{
+ if (sort_key)
+ return *sort_key != '\0';
+ if (type != TOKEN_UPPER && type != TOKEN_LOWER)
+ return 0;
+ for (; start < end; start++)
+ if (csalpha(*start))
+ return 1;
+ return 0;
+}
+
+
+void token_info::lower_case(const char *start, const char *end,
+ string &result) const
+{
+ if (type != TOKEN_UPPER) {
+ while (start < end)
+ result += *start++;
+ }
+ else if (other_case)
+ result += other_case;
+ else {
+ while (start < end)
+ result += cmlower(*start++);
+ }
+}
+
+void token_info::upper_case(const char *start, const char *end,
+ string &result) const
+{
+ if (type != TOKEN_LOWER) {
+ while (start < end)
+ result += *start++;
+ }
+ else if (other_case)
+ result += other_case;
+ else {
+ while (start < end)
+ result += cmupper(*start++);
+ }
+}
+
+token_table_entry::token_table_entry()
+: tok(0)
+{
+}
+
+static void store_token(const char *tok, token_type typ,
+ const char *sk = 0, const char *oc = 0)
+{
+ unsigned n = hash_string(tok, strlen(tok)) % TOKEN_TABLE_SIZE;
+ while (n >= 0) {
+ if (token_table[n].tok == 0) {
+ if (++ntokens == TOKEN_TABLE_SIZE)
+ assert(0);
+ token_table[n].tok = tok;
+ break;
+ }
+ if (strcmp(tok, token_table[n].tok) == 0)
+ break;
+ if (--n < 0)
+ n = TOKEN_TABLE_SIZE - 1;
+ }
+ token_table[n].ti.set(typ, sk, oc);
+}
+
+
+token_info default_token_info;
+
+const token_info *lookup_token(const char *start, const char *end)
+{
+ unsigned n = hash_string(start, end - start) % TOKEN_TABLE_SIZE;
+ while (n >= 0) {
+ if (token_table[n].tok == 0)
+ break;
+ if (strlen(token_table[n].tok) == end - start
+ && memcmp(token_table[n].tok, start, end - start) == 0)
+ return &(token_table[n].ti);
+ if (--n < 0)
+ n = TOKEN_TABLE_SIZE - 1;
+ }
+ return &default_token_info;
+}
+
+static void init_ascii()
+{
+ for (const char *p = "abcdefghijklmnopqrstuvwxyz"; *p; p++) {
+ char buf[2];
+ buf[0] = *p;
+ buf[1] = '\0';
+ store_token(strsave(buf), TOKEN_LOWER);
+ buf[0] = cmupper(buf[0]);
+ store_token(strsave(buf), TOKEN_UPPER);
+ }
+ for (p = "0123456789"; *p; p++) {
+ char buf[2];
+ buf[0] = *p;
+ buf[1] = '\0';
+ const char *s = strsave(buf);
+ store_token(s, TOKEN_OTHER, s);
+ }
+ for (p = ".,:;?!"; *p; p++) {
+ char buf[2];
+ buf[0] = *p;
+ buf[1] = '\0';
+ store_token(strsave(buf), TOKEN_PUNCT);
+ }
+ store_token("-", TOKEN_HYPHEN);
+}
+
+static void store_letter(const char *lower, const char *upper,
+ const char *sort_key = 0)
+{
+ store_token(lower, TOKEN_LOWER, sort_key, upper);
+ store_token(upper, TOKEN_UPPER, sort_key, lower);
+}
+
+static void init_letter(unsigned char uc_code, unsigned char lc_code,
+ const char *sort_key)
+{
+ char lbuf[2];
+ lbuf[0] = lc_code;
+ lbuf[1] = 0;
+ char ubuf[2];
+ ubuf[0] = uc_code;
+ ubuf[1] = 0;
+ store_letter(strsave(lbuf), strsave(ubuf), sort_key);
+}
+
+static void init_latin1()
+{
+ init_letter(0xc0, 0xe0, "a");
+ init_letter(0xc1, 0xe1, "a");
+ init_letter(0xc2, 0xe2, "a");
+ init_letter(0xc3, 0xe3, "a");
+ init_letter(0xc4, 0xe4, "a");
+ init_letter(0xc5, 0xe5, "a");
+ init_letter(0xc6, 0xe6, "ae");
+ init_letter(0xc7, 0xe7, "c");
+ init_letter(0xc8, 0xe8, "e");
+ init_letter(0xc9, 0xe9, "e");
+ init_letter(0xca, 0xea, "e");
+ init_letter(0xcb, 0xeb, "e");
+ init_letter(0xcc, 0xec, "i");
+ init_letter(0xcd, 0xed, "i");
+ init_letter(0xce, 0xee, "i");
+ init_letter(0xcf, 0xef, "i");
+
+ init_letter(0xd0, 0xf0, "d");
+ init_letter(0xd1, 0xf1, "n");
+ init_letter(0xd2, 0xf2, "o");
+ init_letter(0xd3, 0xf3, "o");
+ init_letter(0xd4, 0xf4, "o");
+ init_letter(0xd5, 0xf5, "o");
+ init_letter(0xd6, 0xf6, "o");
+ init_letter(0xd8, 0xf8, "o");
+ init_letter(0xd9, 0xf9, "u");
+ init_letter(0xda, 0xfa, "u");
+ init_letter(0xdb, 0xfb, "u");
+ init_letter(0xdc, 0xfc, "u");
+ init_letter(0xdd, 0xfd, "y");
+ init_letter(0xde, 0xfe, THORN_SORT_KEY);
+
+ store_token("\337", TOKEN_LOWER, "ss", "SS");
+ store_token("\377", TOKEN_LOWER, "y", "Y");
+}
+
+static void init_two_char_letter(char l1, char l2, char u1, char u2,
+ const char *sk = 0)
+{
+ char buf[6];
+ buf[0] = '\\';
+ buf[1] = '(';
+ buf[2] = l1;
+ buf[3] = l2;
+ buf[4] = '\0';
+ const char *p = strsave(buf);
+ buf[2] = u1;
+ buf[3] = u2;
+ store_letter(p, strsave(buf), sk);
+ buf[1] = '[';
+ buf[4] = ']';
+ buf[5] = '\0';
+ p = strsave(buf);
+ buf[2] = l1;
+ buf[3] = l2;
+ store_letter(strsave(buf), p, sk);
+
+}
+
+static void init_special_chars()
+{
+ for (const char *p = "':^`~"; *p; p++)
+ for (const char *q = "aeiouy"; *q; q++) {
+ // Use a variable to work around bug in gcc 2.0
+ char c = cmupper(*q);
+ init_two_char_letter(*p, *q, *p, c);
+ }
+ for (p = "/l/o~n,coeaeij"; *p; p += 2) {
+ // Use variables to work around bug in gcc 2.0
+ char c0 = cmupper(p[0]);
+ char c1 = cmupper(p[1]);
+ init_two_char_letter(p[0], p[1], c0, c1);
+ }
+ init_two_char_letter('v', 's', 'v', 'S', "s");
+ init_two_char_letter('v', 'z', 'v', 'Z', "z");
+ init_two_char_letter('o', 'a', 'o', 'A', "a");
+ init_two_char_letter('T', 'p', 'T', 'P', THORN_SORT_KEY);
+ init_two_char_letter('-', 'd', '-', 'D');
+
+ store_token("\\(ss", TOKEN_LOWER, 0, "SS");
+ store_token("\\[ss]", TOKEN_LOWER, 0, "SS");
+
+ store_token("\\(Sd", TOKEN_LOWER, "d", "\\(-D");
+ store_token("\\[Sd]", TOKEN_LOWER, "d", "\\[-D]");
+ store_token("\\(hy", TOKEN_HYPHEN);
+ store_token("\\[hy]", TOKEN_HYPHEN);
+}
+
+static void init_strings()
+{
+ char buf[6];
+ buf[0] = '\\';
+ buf[1] = '*';
+ for (const char *p = "'`^^,:~v_o./;"; *p; p++) {
+ buf[2] = *p;
+ buf[3] = '\0';
+ store_token(strsave(buf), TOKEN_ACCENT);
+ buf[2] = '[';
+ buf[3] = *p;
+ buf[4] = ']';
+ buf[5] = '\0';
+ store_token(strsave(buf), TOKEN_ACCENT);
+ }
+
+ // -ms special letters
+ store_letter("\\*(th", "\\*(Th", THORN_SORT_KEY);
+ store_letter("\\*[th]", "\\*[Th]", THORN_SORT_KEY);
+ store_letter("\\*(d-", "\\*(D-");
+ store_letter("\\*[d-]", "\\*[D-]");
+ store_letter("\\*(ae", "\\*(Ae", "ae");
+ store_letter("\\*[ae]", "\\*[Ae]", "ae");
+ store_letter("\\*(oe", "\\*(Oe", "oe");
+ store_letter("\\*[oe]", "\\*[Oe]", "oe");
+
+ store_token("\\*3", TOKEN_LOWER, "y", "Y");
+ store_token("\\*8", TOKEN_LOWER, "ss", "SS");
+ store_token("\\*q", TOKEN_LOWER, "o", "O");
+}
+
+struct token_initer {
+ token_initer();
+};
+
+static token_initer the_token_initer;
+
+token_initer::token_initer()
+{
+ init_ascii();
+ init_latin1();
+ init_special_chars();
+ init_strings();
+ default_token_info.set(TOKEN_OTHER);
+}
diff --git a/gnu/usr.bin/groff/refer/token.h b/gnu/usr.bin/groff/refer/token.h
new file mode 100644
index 000000000000..c6445d230ffc
--- /dev/null
+++ b/gnu/usr.bin/groff/refer/token.h
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+enum token_type {
+ TOKEN_OTHER,
+ TOKEN_UPPER,
+ TOKEN_LOWER,
+ TOKEN_ACCENT,
+ TOKEN_PUNCT,
+ TOKEN_HYPHEN
+};
+
+class token_info {
+private:
+ token_type type;
+ const char *sort_key;
+ const char *other_case;
+public:
+ token_info();
+ void set(token_type, const char *sk = 0, const char *oc = 0);
+ void lower_case(const char *start, const char *end, string &result) const;
+ void upper_case(const char *start, const char *end, string &result) const;
+ void sortify(const char *start, const char *end, string &result) const;
+ int sortify_non_empty(const char *start, const char *end) const;
+ int is_upper() const;
+ int is_lower() const;
+ int is_accent() const;
+ int is_other() const;
+ int is_punct() const;
+ int is_hyphen() const;
+};
+
+inline int token_info::is_upper() const
+{
+ return type == TOKEN_UPPER;
+}
+
+inline int token_info::is_lower() const
+{
+ return type == TOKEN_LOWER;
+}
+
+inline int token_info::is_accent() const
+{
+ return type == TOKEN_ACCENT;
+}
+
+inline int token_info::is_other() const
+{
+ return type == TOKEN_OTHER;
+}
+
+inline int token_info::is_punct() const
+{
+ return type == TOKEN_PUNCT;
+}
+
+inline int token_info::is_hyphen() const
+{
+ return type == TOKEN_HYPHEN;
+}
+
+int get_token(const char **ptr, const char *end);
+const token_info *lookup_token(const char *start, const char *end);
diff --git a/gnu/usr.bin/groff/soelim/Makefile b/gnu/usr.bin/groff/soelim/Makefile
new file mode 100644
index 000000000000..91ededc36fb7
--- /dev/null
+++ b/gnu/usr.bin/groff/soelim/Makefile
@@ -0,0 +1,12 @@
+# Makefile for soelim
+
+PROG= soelim
+SRCS= soelim.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF)
+DPADD+= $(LIBGROFF)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/soelim/soelim.1 b/gnu/usr.bin/groff/soelim/soelim.1
new file mode 100644
index 000000000000..93c0f5f0c308
--- /dev/null
+++ b/gnu/usr.bin/groff/soelim/soelim.1
@@ -0,0 +1,42 @@
+.\" -*- nroff -*-
+.TH SOELIM 1 "15 September 1992" "Groff Version 1.08"
+.SH NAME
+soelim \- interpret .so requests in groff input
+.SH SYNOPSIS
+.B soelim
+[
+.B \-Cv
+]
+[
+.IR files \|.\|.\|.\|
+]
+.SH DESCRIPTION
+.B soelim
+reads
+.I files
+and replaces lines of the form
+.IP
+.BI .so\ file
+.LP
+by the contents of
+.IR file .
+It is useful if files included with
+.B so
+need to be preprocessed.
+Normally,
+.B soelim
+should be invoked with the
+.B \-s
+option of
+.BR groff .
+.SH OPTIONS
+.TP
+.B \-C
+Recognize
+.B .so
+even when followed by a character other than space or newline.
+.TP
+.B \-v
+Print the version number.
+.SH "SEE ALSO"
+.BR groff (1)
diff --git a/gnu/usr.bin/groff/soelim/soelim.cc b/gnu/usr.bin/groff/soelim/soelim.cc
new file mode 100644
index 000000000000..f69baeee8879
--- /dev/null
+++ b/gnu/usr.bin/groff/soelim/soelim.cc
@@ -0,0 +1,278 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+
+int compatible_flag = 0;
+
+extern int interpret_lf_args(const char *);
+
+int do_file(const char *filename);
+
+void usage()
+{
+ fprintf(stderr, "usage: %s [ -vC ] [ files ]\n", program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int opt;
+ while ((opt = getopt(argc, argv, "vC")) != EOF)
+ switch (opt) {
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU soelim version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ int nbad = 0;
+ if (optind >= argc)
+ nbad += !do_file("-");
+ else
+ for (int i = optind; i < argc; i++)
+ nbad += !do_file(argv[i]);
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ exit(nbad != 0);
+}
+
+void set_location()
+{
+ printf(".lf %d %s\n", current_lineno, current_filename);
+}
+
+void do_so(const char *line)
+{
+ const char *p = line;
+ while (*p == ' ')
+ p++;
+ string filename;
+ int success = 1;
+ for (const char *q = p;
+ success && *q != '\0' && *q != '\n' && *q != ' ';
+ q++)
+ if (*q == '\\') {
+ switch (*++q) {
+ case 'e':
+ case '\\':
+ filename += '\\';
+ break;
+ case ' ':
+ filename += ' ';
+ break;
+ default:
+ success = 0;
+ break;
+ }
+ }
+ else
+ filename += char(*q);
+ if (success && filename.length() > 0) {
+ filename += '\0';
+ const char *fn = current_filename;
+ int ln = current_lineno;
+ current_lineno--;
+ if (do_file(filename.contents())) {
+ current_filename = fn;
+ current_lineno = ln;
+ set_location();
+ return;
+ }
+ current_lineno++;
+ }
+ fputs(".so", stdout);
+ fputs(line, stdout);
+}
+
+int do_file(const char *filename)
+{
+ FILE *fp;
+ if (strcmp(filename, "-") == 0)
+ fp = stdin;
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ }
+ current_filename = filename;
+ current_lineno = 1;
+ set_location();
+ enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ switch (state) {
+ case START:
+ if (c == '.')
+ state = HAD_DOT;
+ else {
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ break;
+ case HAD_DOT:
+ if (c == 's')
+ state = HAD_s;
+ else if (c == 'l')
+ state = HAD_l;
+ else {
+ putchar('.');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_s:
+ if (c == 'o')
+ state = HAD_so;
+ else {
+ putchar('.');
+ putchar('s');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_so:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ for (; c != EOF && c != '\n'; c = getc(fp))
+ line += c;
+ current_lineno++;
+ line += '\n';
+ line += '\0';
+ do_so(line.contents());
+ state = START;
+ }
+ else {
+ fputs(".so", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ case HAD_l:
+ if (c == 'f')
+ state = HAD_lf;
+ else {
+ putchar('.');
+ putchar('l');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ for (; c != EOF && c != '\n'; c = getc(fp))
+ line += c;
+ current_lineno++;
+ line += '\n';
+ line += '\0';
+ interpret_lf_args(line.contents());
+ printf(".lf%s", line.contents());
+ state = START;
+ }
+ else {
+ fputs(".lf", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ switch (state) {
+ case HAD_DOT:
+ fputs(".\n", stdout);
+ break;
+ case HAD_l:
+ fputs(".l\n", stdout);
+ break;
+ case HAD_s:
+ fputs(".s\n", stdout);
+ break;
+ case HAD_lf:
+ fputs(".lf\n", stdout);
+ break;
+ case HAD_so:
+ fputs(".so\n", stdout);
+ break;
+ case MIDDLE:
+ putc('\n', stdout);
+ break;
+ case START:
+ break;
+ }
+ if (fp != stdin)
+ fclose(fp);
+ current_filename = 0;
+ return 1;
+}
diff --git a/gnu/usr.bin/groff/tbl/Makefile b/gnu/usr.bin/groff/tbl/Makefile
new file mode 100644
index 000000000000..4d26bc2916bc
--- /dev/null
+++ b/gnu/usr.bin/groff/tbl/Makefile
@@ -0,0 +1,12 @@
+# Makefile for tbl
+
+PROG= tbl
+SRCS= main.cc table.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF) -lm
+DPADD+= $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/tbl/main.cc b/gnu/usr.bin/groff/tbl/main.cc
new file mode 100644
index 000000000000..c99af2b85ea4
--- /dev/null
+++ b/gnu/usr.bin/groff/tbl/main.cc
@@ -0,0 +1,1497 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "table.h"
+
+#define MAX_POINT_SIZE 99
+#define MAX_VERTICAL_SPACING 72
+
+static int compatible_flag = 0;
+
+class table_input {
+ FILE *fp;
+ enum { START, MIDDLE, REREAD_T, REREAD_TE, REREAD_E, END, ERROR } state;
+ string unget_stack;
+public:
+ table_input(FILE *);
+ int get();
+ int ended() { return unget_stack.empty() && state == END; }
+ void unget(char);
+};
+
+table_input::table_input(FILE *p)
+: fp(p), state(START)
+{
+}
+
+void table_input::unget(char c)
+{
+ assert(c != '\0');
+ unget_stack += c;
+ if (c == '\n')
+ current_lineno--;
+}
+
+int table_input::get()
+{
+ int len = unget_stack.length();
+ if (len != 0) {
+ unsigned char c = unget_stack[len - 1];
+ unget_stack.set_length(len - 1);
+ if (c == '\n')
+ current_lineno++;
+ return c;
+ }
+ int c;
+ for (;;) {
+ switch (state) {
+ case START:
+ if ((c = getc(fp)) == '.') {
+ if ((c = getc(fp)) == 'T') {
+ if ((c = getc(fp)) == 'E') {
+ if (compatible_flag) {
+ state = END;
+ return EOF;
+ }
+ else {
+ c = getc(fp);
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == EOF || c == ' ' || c == '\n') {
+ state = END;
+ return EOF;
+ }
+ state = REREAD_TE;
+ return '.';
+ }
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ state = REREAD_T;
+ return '.';
+ }
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ state = MIDDLE;
+ return '.';
+ }
+ }
+ else if (c == EOF) {
+ state = ERROR;
+ return EOF;
+ }
+ else {
+ if (c == '\n')
+ current_lineno++;
+ else {
+ state = MIDDLE;
+ if (c == '\0') {
+ error("illegal input character code 0");
+ break;
+ }
+ }
+ return c;
+ }
+ break;
+ case MIDDLE:
+ // handle line continuation
+ if ((c = getc(fp)) == '\\') {
+ c = getc(fp);
+ if (c == '\n')
+ c = getc(fp); // perhaps state ought to be START now
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ c = '\\';
+ }
+ }
+ if (c == EOF) {
+ state = ERROR;
+ return EOF;
+ }
+ else {
+ if (c == '\n') {
+ state = START;
+ current_lineno++;
+ }
+ else if (c == '\0') {
+ error("illegal input character code 0");
+ break;
+ }
+ return c;
+ }
+ case REREAD_T:
+ state = MIDDLE;
+ return 'T';
+ case REREAD_TE:
+ state = REREAD_E;
+ return 'T';
+ case REREAD_E:
+ state = MIDDLE;
+ return 'E';
+ case END:
+ case ERROR:
+ return EOF;
+ }
+ }
+}
+
+void process_input_file(FILE *);
+void process_table(table_input &in);
+
+void process_input_file(FILE *fp)
+{
+ enum { START, MIDDLE, HAD_DOT, HAD_T, HAD_TS, HAD_l, HAD_lf } state;
+ state = START;
+ int c;
+ while ((c = getc(fp)) != EOF)
+ switch (state) {
+ case START:
+ if (c == '.')
+ state = HAD_DOT;
+ else {
+ if (c == '\n')
+ current_lineno++;
+ else
+ state = MIDDLE;
+ putchar(c);
+ }
+ break;
+ case MIDDLE:
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ putchar(c);
+ break;
+ case HAD_DOT:
+ if (c == 'T')
+ state = HAD_T;
+ else if (c == 'l')
+ state = HAD_l;
+ else {
+ putchar('.');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_T:
+ if (c == 'S')
+ state = HAD_TS;
+ else {
+ putchar('.');
+ putchar('T');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_TS:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ putchar('.');
+ putchar('T');
+ putchar('S');
+ while (c != '\n') {
+ if (c == EOF) {
+ error("end of file at beginning of table");
+ return;
+ }
+ putchar(c);
+ c = getc(fp);
+ }
+ putchar('\n');
+ current_lineno++;
+ {
+ table_input input(fp);
+ process_table(input);
+ set_troff_location(current_filename, current_lineno);
+ if (input.ended()) {
+ fputs(".TE", stdout);
+ while ((c = getc(fp)) != '\n') {
+ if (c == EOF) {
+ putchar('\n');
+ return;
+ }
+ putchar(c);
+ }
+ putchar('\n');
+ current_lineno++;
+ }
+ }
+ state = START;
+ }
+ else {
+ fputs(".TS", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ case HAD_l:
+ if (c == 'f')
+ state = HAD_lf;
+ else {
+ putchar('.');
+ putchar('l');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ while (c != EOF) {
+ line += c;
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ c = getc(fp);
+ }
+ line += '\0';
+ interpret_lf_args(line.contents());
+ printf(".lf%s", line.contents());
+ state = START;
+ }
+ else {
+ fputs(".lf", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ switch(state) {
+ case START:
+ break;
+ case MIDDLE:
+ putchar('\n');
+ break;
+ case HAD_DOT:
+ fputs(".\n", stdout);
+ break;
+ case HAD_l:
+ fputs(".l\n", stdout);
+ break;
+ case HAD_T:
+ fputs(".T\n", stdout);
+ break;
+ case HAD_lf:
+ fputs(".lf\n", stdout);
+ break;
+ case HAD_TS:
+ fputs(".TS\n", stdout);
+ break;
+ }
+ if (fp != stdin)
+ fclose(fp);
+}
+
+struct options {
+ unsigned flags;
+ int linesize;
+ char delim[2];
+ char tab_char;
+ char decimal_point_char;
+
+ options();
+};
+
+options::options()
+: flags(0), tab_char('\t'), decimal_point_char('.'), linesize(0)
+{
+ delim[0] = delim[1] = '\0';
+}
+
+// Return non-zero if p and q are the same ignoring case.
+
+int strieq(const char *p, const char *q)
+{
+ for (; cmlower(*p) == cmlower(*q); p++, q++)
+ if (*p == '\0')
+ return 1;
+ return 0;
+}
+
+// return 0 if we should give up in this table
+
+options *process_options(table_input &in)
+{
+ options *opt = new options;
+ string line;
+ int level = 0;
+ for (;;) {
+ int c = in.get();
+ if (c == EOF) {
+ int i = line.length();
+ while (--i >= 0)
+ in.unget(line[i]);
+ return opt;
+ }
+ if (c == '\n') {
+ in.unget(c);
+ int i = line.length();
+ while (--i >= 0)
+ in.unget(line[i]);
+ return opt;
+ }
+ else if (c == '(')
+ level++;
+ else if (c == ')')
+ level--;
+ else if (c == ';' && level == 0) {
+ line += '\0';
+ break;
+ }
+ line += c;
+ }
+ if (line.empty())
+ return opt;
+ char *p = &line[0];
+ for (;;) {
+ while (csspace(*p) || *p == ',')
+ p++;
+ if (*p == '\0')
+ break;
+ char *q = p;
+ while (*q != ' ' && *q != '\0' && *q != '\t' && *q != ',' && *q != '(')
+ q++;
+ char *arg = 0;
+ if (*q != '(' && *q != '\0')
+ *q++ = '\0';
+ while (csspace(*q))
+ q++;
+ if (*q == '(') {
+ *q++ = '\0';
+ arg = q;
+ while (*q != ')' && *q != '\0')
+ q++;
+ if (*q == '\0')
+ error("missing `)'");
+ else
+ *q++ = '\0';
+ }
+ if (*p == '\0') {
+ if (arg)
+ error("argument without option");
+ }
+ else if (strieq(p, "tab")) {
+ if (!arg)
+ error("`tab' option requires argument in parentheses");
+ else {
+ if (arg[0] == '\0' || arg[1] != '\0')
+ error("argument to `tab' option must be a single character");
+ else
+ opt->tab_char = arg[0];
+ }
+ }
+ else if (strieq(p, "linesize")) {
+ if (!arg)
+ error("`linesize' option requires argument in parentheses");
+ else {
+ if (sscanf(arg, "%d", &opt->linesize) != 1)
+ error("bad linesize `%s'", arg);
+ else if (opt->linesize <= 0) {
+ error("linesize must be positive");
+ opt->linesize = 0;
+ }
+ }
+ }
+ else if (strieq(p, "delim")) {
+ if (!arg)
+ error("`delim' option requires argument in parentheses");
+ else if (arg[0] == '\0' || arg[1] == '\0' || arg[2] != '\0')
+ error("argument to `delim' option must be two characters");
+ else {
+ opt->delim[0] = arg[0];
+ opt->delim[1] = arg[1];
+ }
+ }
+ else if (strieq(p, "center") || strieq(p, "centre")) {
+ if (arg)
+ error("`center' option does not take a argument");
+ opt->flags |= table::CENTER;
+ }
+ else if (strieq(p, "expand")) {
+ if (arg)
+ error("`expand' option does not take a argument");
+ opt->flags |= table::EXPAND;
+ }
+ else if (strieq(p, "box") || strieq(p, "frame")) {
+ if (arg)
+ error("`box' option does not take a argument");
+ opt->flags |= table::BOX;
+ }
+ else if (strieq(p, "doublebox") || strieq(p, "doubleframe")) {
+ if (arg)
+ error("`doublebox' option does not take a argument");
+ opt->flags |= table::DOUBLEBOX;
+ }
+ else if (strieq(p, "allbox")) {
+ if (arg)
+ error("`allbox' option does not take a argument");
+ opt->flags |= table::ALLBOX;
+ }
+ else if (strieq(p, "nokeep")) {
+ if (arg)
+ error("`nokeep' option does not take a argument");
+ opt->flags |= table::NOKEEP;
+ }
+ else if (strieq(p, "decimalpoint")) {
+ if (!arg)
+ error("`decimalpoint' option requires argument in parentheses");
+ else {
+ if (arg[0] == '\0' || arg[1] != '\0')
+ error("argument to `decimalpoint' option must be a single character");
+ else
+ opt->decimal_point_char = arg[0];
+ }
+ }
+ else {
+ error("unrecognised global option `%1'", p);
+ // delete opt;
+ // return 0;
+ }
+ p = q;
+ }
+ return opt;
+}
+
+entry_modifier::entry_modifier()
+: vertical_alignment(CENTER), zero_width(0), stagger(0)
+{
+ vertical_spacing.inc = vertical_spacing.val = 0;
+ point_size.inc = point_size.val = 0;
+}
+
+entry_modifier::~entry_modifier()
+{
+}
+
+entry_format::entry_format() : type(FORMAT_LEFT)
+{
+}
+
+entry_format::entry_format(format_type t) : type(t)
+{
+}
+
+void entry_format::debug_print() const
+{
+ switch (type) {
+ case FORMAT_LEFT:
+ putc('l', stderr);
+ break;
+ case FORMAT_CENTER:
+ putc('c', stderr);
+ break;
+ case FORMAT_RIGHT:
+ putc('r', stderr);
+ break;
+ case FORMAT_NUMERIC:
+ putc('n', stderr);
+ break;
+ case FORMAT_ALPHABETIC:
+ putc('a', stderr);
+ break;
+ case FORMAT_SPAN:
+ putc('s', stderr);
+ break;
+ case FORMAT_VSPAN:
+ putc('^', stderr);
+ break;
+ case FORMAT_HLINE:
+ putc('_', stderr);
+ break;
+ case FORMAT_DOUBLE_HLINE:
+ putc('=', stderr);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (point_size.val != 0) {
+ putc('p', stderr);
+ if (point_size.inc > 0)
+ putc('+', stderr);
+ else if (point_size.inc < 0)
+ putc('-', stderr);
+ fprintf(stderr, "%d ", point_size.val);
+ }
+ if (vertical_spacing.val != 0) {
+ putc('v', stderr);
+ if (vertical_spacing.inc > 0)
+ putc('+', stderr);
+ else if (vertical_spacing.inc < 0)
+ putc('-', stderr);
+ fprintf(stderr, "%d ", vertical_spacing.val);
+ }
+ if (!font.empty()) {
+ putc('f', stderr);
+ put_string(font, stderr);
+ putc(' ', stderr);
+ }
+ switch (vertical_alignment) {
+ case entry_modifier::CENTER:
+ break;
+ case entry_modifier::TOP:
+ putc('t', stderr);
+ break;
+ case entry_modifier::BOTTOM:
+ putc('d', stderr);
+ break;
+ }
+ if (zero_width)
+ putc('z', stderr);
+ if (stagger)
+ putc('u', stderr);
+}
+
+struct format {
+ int nrows;
+ int ncolumns;
+ int *separation;
+ string *width;
+ char *equal;
+ entry_format **entry;
+ char **vline;
+
+ format(int nr, int nc);
+ ~format();
+ void add_rows(int n);
+};
+
+format::format(int nr, int nc) : nrows(nr), ncolumns(nc)
+{
+ int i;
+ separation = ncolumns > 1 ? new int[ncolumns - 1] : 0;
+ for (i = 0; i < ncolumns-1; i++)
+ separation[i] = -1;
+ width = new string[ncolumns];
+ equal = new char[ncolumns];
+ for (i = 0; i < ncolumns; i++)
+ equal[i] = 0;
+ entry = new entry_format *[nrows];
+ for (i = 0; i < nrows; i++)
+ entry[i] = new entry_format[ncolumns];
+ vline = new char*[nrows];
+ for (i = 0; i < nrows; i++) {
+ vline[i] = new char[ncolumns+1];
+ for (int j = 0; j < ncolumns+1; j++)
+ vline[i][j] = 0;
+ }
+}
+
+void format::add_rows(int n)
+{
+ int i;
+ char **old_vline = vline;
+ vline = new char*[nrows + n];
+ for (i = 0; i < nrows; i++)
+ vline[i] = old_vline[i];
+ a_delete old_vline;
+ for (i = 0; i < n; i++) {
+ vline[nrows + i] = new char[ncolumns + 1];
+ for (int j = 0; j < ncolumns + 1; j++)
+ vline[nrows + i][j] = 0;
+ }
+ entry_format **old_entry = entry;
+ entry = new entry_format *[nrows + n];
+ for (i = 0; i < nrows; i++)
+ entry[i] = old_entry[i];
+ a_delete old_entry;
+ for (i = 0; i < n; i++)
+ entry[nrows + i] = new entry_format[ncolumns];
+ nrows += n;
+}
+
+format::~format()
+{
+ a_delete separation;
+ ad_delete(ncolumns) width;
+ a_delete equal;
+ for (int i = 0; i < nrows; i++) {
+ a_delete vline[i];
+ ad_delete(ncolumns) entry[i];
+ }
+ a_delete vline;
+ a_delete entry;
+}
+
+struct input_entry_format : entry_format {
+ input_entry_format *next;
+ string width;
+ int separation;
+ int vline;
+ int pre_vline;
+ int last_column;
+ int equal;
+ input_entry_format(format_type, input_entry_format * = 0);
+ ~input_entry_format();
+ void debug_print();
+};
+
+input_entry_format::input_entry_format(format_type t, input_entry_format *p)
+: entry_format(t), next(p)
+{
+ separation = -1;
+ last_column = 0;
+ vline = 0;
+ pre_vline = 0;
+ equal = 0;
+}
+
+input_entry_format::~input_entry_format()
+{
+}
+
+void free_input_entry_format_list(input_entry_format *list)
+{
+ while (list) {
+ input_entry_format *tem = list;
+ list = list->next;
+ delete tem;
+ }
+}
+
+void input_entry_format::debug_print()
+{
+ for (int i = 0; i < pre_vline; i++)
+ putc('|', stderr);
+ entry_format::debug_print();
+ if (!width.empty()) {
+ putc('w', stderr);
+ putc('(', stderr);
+ put_string(width, stderr);
+ putc(')', stderr);
+ }
+ if (equal)
+ putc('e', stderr);
+ if (separation >= 0)
+ fprintf(stderr, "%d", separation);
+ for (i = 0; i < vline; i++)
+ putc('|', stderr);
+ if (last_column)
+ putc(',', stderr);
+}
+
+// Return zero if we should give up on this table.
+// If this is a continuation format line, current_format will be the current
+// format line.
+
+format *process_format(table_input &in, options *opt,
+ format *current_format = 0)
+{
+ input_entry_format *list = 0;
+ int c = in.get();
+ for (;;) {
+ int pre_vline = 0;
+ int got_format = 0;
+ int got_period = 0;
+ format_type t;
+ for (;;) {
+ if (c == EOF) {
+ error("end of input while processing format");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ switch (c) {
+ case 'n':
+ case 'N':
+ t = FORMAT_NUMERIC;
+ got_format = 1;
+ break;
+ case 'a':
+ case 'A':
+ got_format = 1;
+ t = FORMAT_ALPHABETIC;
+ break;
+ case 'c':
+ case 'C':
+ got_format = 1;
+ t = FORMAT_CENTER;
+ break;
+ case 'l':
+ case 'L':
+ got_format = 1;
+ t = FORMAT_LEFT;
+ break;
+ case 'r':
+ case 'R':
+ got_format = 1;
+ t = FORMAT_RIGHT;
+ break;
+ case 's':
+ case 'S':
+ got_format = 1;
+ t = FORMAT_SPAN;
+ break;
+ case '^':
+ got_format = 1;
+ t = FORMAT_VSPAN;
+ break;
+ case '_':
+ got_format = 1;
+ t = FORMAT_HLINE;
+ break;
+ case '=':
+ got_format = 1;
+ t = FORMAT_DOUBLE_HLINE;
+ break;
+ case '.':
+ got_period = 1;
+ break;
+ case '|':
+ pre_vline++;
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ break;
+ default:
+ if (c == opt->tab_char)
+ break;
+ error("unrecognised format `%1'", char(c));
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ if (got_period)
+ break;
+ c = in.get();
+ if (got_format)
+ break;
+ }
+ if (got_period)
+ break;
+ list = new input_entry_format(t, list);
+ if (pre_vline)
+ list->pre_vline = pre_vline;
+ int success = 1;
+ do {
+ switch (c) {
+ case 't':
+ case 'T':
+ c = in.get();
+ list->vertical_alignment = entry_modifier::TOP;
+ break;
+ case 'd':
+ case 'D':
+ c = in.get();
+ list->vertical_alignment = entry_modifier::BOTTOM;
+ break;
+ case 'u':
+ case 'U':
+ c = in.get();
+ list->stagger = 1;
+ break;
+ case 'z':
+ case 'Z':
+ c = in.get();
+ list->zero_width = 1;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int w = 0;
+ do {
+ w = w*10 + (c - '0');
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ list->separation = w;
+ }
+ break;
+ case 'f':
+ case 'F':
+ do {
+ c = in.get();
+ } while (c == ' ' || c == '\t');
+ if (c == EOF) {
+ error("missing font name");
+ break;
+ }
+ if (c == '(') {
+ for (;;) {
+ c = in.get();
+ if (c == EOF || c == ' ' || c == '\t') {
+ error("missing `)'");
+ break;
+ }
+ if (c == ')') {
+ c = in.get();
+ break;
+ }
+ list->font += char(c);
+ }
+ }
+ else {
+ list->font = c;
+ char cc = c;
+ c = in.get();
+ if (!csdigit(cc)
+ && c != EOF && c != ' ' && c != '\t' && c != '.' && c != '\n') {
+ list->font += char(c);
+ c = in.get();
+ }
+ }
+ break;
+ case 'v':
+ case 'V':
+ c = in.get();
+ list->vertical_spacing.val = 0;
+ list->vertical_spacing.inc = 0;
+ if (c == '+' || c == '-') {
+ list->vertical_spacing.inc = (c == '+' ? 1 : -1);
+ c = in.get();
+ }
+ if (c == EOF || !csdigit(c)) {
+ error("`v' modifier must be followed by number");
+ list->vertical_spacing.inc = 0;
+ }
+ else {
+ do {
+ list->vertical_spacing.val *= 10;
+ list->vertical_spacing.val += c - '0';
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ }
+ if (list->vertical_spacing.val > MAX_VERTICAL_SPACING
+ || list->vertical_spacing.val < -MAX_VERTICAL_SPACING) {
+ error("unreasonable point size");
+ list->vertical_spacing.val = 0;
+ list->vertical_spacing.inc = 0;
+ }
+ break;
+ case 'p':
+ case 'P':
+ c = in.get();
+ list->point_size.val = 0;
+ list->point_size.inc = 0;
+ if (c == '+' || c == '-') {
+ list->point_size.inc = (c == '+' ? 1 : -1);
+ c = in.get();
+ }
+ if (c == EOF || !csdigit(c)) {
+ error("`p' modifier must be followed by number");
+ list->point_size.inc = 0;
+ }
+ else {
+ do {
+ list->point_size.val *= 10;
+ list->point_size.val += c - '0';
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ }
+ if (list->point_size.val > MAX_POINT_SIZE
+ || list->point_size.val < -MAX_POINT_SIZE) {
+ error("unreasonable point size");
+ list->point_size.val = 0;
+ list->point_size.inc = 0;
+ }
+ break;
+ case 'w':
+ case 'W':
+ c = in.get();
+ while (c == ' ' || c == '\t')
+ c = in.get();
+ if (c == '(') {
+ list->width = "";
+ c = in.get();
+ while (c != ')') {
+ if (c == EOF || c == '\n') {
+ error("missing `)'");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ list->width += c;
+ c = in.get();
+ }
+ c = in.get();
+ }
+ else {
+ if (c == '+' || c == '-') {
+ list->width = char(c);
+ c = in.get();
+ }
+ else
+ list->width = "";
+ if (c == EOF || !csdigit(c))
+ error("bad argument for `w' modifier");
+ else {
+ do {
+ list->width += char(c);
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ }
+ }
+ break;
+ case 'e':
+ case 'E':
+ c = in.get();
+ list->equal++;
+ break;
+ case '|':
+ c = in.get();
+ list->vline++;
+ break;
+ case 'B':
+ case 'b':
+ c = in.get();
+ list->font = "B";
+ break;
+ case 'I':
+ case 'i':
+ c = in.get();
+ list->font = "I";
+ break;
+ case ' ':
+ case '\t':
+ c = in.get();
+ break;
+ default:
+ if (c == opt->tab_char)
+ c = in.get();
+ else
+ success = 0;
+ break;
+ }
+ } while (success);
+ if (list->vline > 2) {
+ list->vline = 2;
+ error("more than 2 vertical bars between key letters");
+ }
+ if (c == '\n' || c == ',') {
+ c = in.get();
+ list->last_column = 1;
+ }
+ }
+ if (c == '.') {
+ do {
+ c = in.get();
+ } while (c == ' ' || c == '\t');
+ if (c != '\n') {
+ error("`.' not last character on line");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ }
+ if (!list) {
+ error("no format");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ list->last_column = 1;
+ // now reverse the list so that the first row is at the beginning
+ input_entry_format *rev = 0;
+ while (list != 0) {
+ input_entry_format *tem = list->next;
+ list->next = rev;
+ rev = list;
+ list = tem;
+ }
+ list = rev;
+ input_entry_format *tem;
+
+#if 0
+ for (tem = list; tem; tem = tem->next)
+ tem->debug_print();
+ putc('\n', stderr);
+#endif
+ // compute number of columns and rows
+ int ncolumns = 0;
+ int nrows = 0;
+ int col = 0;
+ for (tem = list; tem; tem = tem->next) {
+ if (tem->last_column) {
+ if (col >= ncolumns)
+ ncolumns = col + 1;
+ col = 0;
+ nrows++;
+ }
+ else
+ col++;
+ }
+ int row;
+ format *f;
+ if (current_format) {
+ if (ncolumns > current_format->ncolumns) {
+ error("cannot increase the number of columns in a continued format");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ f = current_format;
+ row = f->nrows;
+ f->add_rows(nrows);
+ }
+ else {
+ f = new format(nrows, ncolumns);
+ row = 0;
+ }
+ col = 0;
+ for (tem = list; tem; tem = tem->next) {
+ f->entry[row][col] = *tem;
+ if (col < ncolumns-1) {
+ // use the greatest separation
+ if (tem->separation > f->separation[col]) {
+ if (current_format)
+ error("cannot change column separation in continued format");
+ else
+ f->separation[col] = tem->separation;
+ }
+ }
+ else if (tem->separation >= 0)
+ error("column separation specified for last column");
+ if (tem->equal && !f->equal[col]) {
+ if (current_format)
+ error("cannot change which columns are equal in continued format");
+ else
+ f->equal[col] = 1;
+ }
+ if (!tem->width.empty()) {
+ // use the last width
+ if (!f->width[col].empty() && f->width[col] != tem->width)
+ error("multiple widths for column %1", col+1);
+ f->width[col] = tem->width;
+ }
+ if (tem->pre_vline) {
+ assert(col == 0);
+ f->vline[row][col] = tem->pre_vline;
+ }
+ f->vline[row][col+1] = tem->vline;
+ if (tem->last_column) {
+ row++;
+ col = 0;
+ }
+ else
+ col++;
+ }
+ free_input_entry_format_list(list);
+ for (col = 0; col < ncolumns; col++) {
+ entry_format *e = f->entry[f->nrows-1] + col;
+ if (e->type != FORMAT_HLINE
+ && e->type != FORMAT_DOUBLE_HLINE
+ && e->type != FORMAT_SPAN)
+ break;
+ }
+ if (col >= ncolumns) {
+ error("last row of format is all lines");
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+table *process_data(table_input &in, format *f, options *opt)
+{
+ char tab_char = opt->tab_char;
+ int ncolumns = f->ncolumns;
+ int current_row = 0;
+ int format_index = 0;
+ int give_up = 0;
+ enum { DATA_INPUT_LINE, TROFF_INPUT_LINE, SINGLE_HLINE, DOUBLE_HLINE } type;
+ table *tbl = new table(ncolumns, opt->flags, opt->linesize,
+ opt->decimal_point_char);
+ if (opt->delim[0] != '\0')
+ tbl->set_delim(opt->delim[0], opt->delim[1]);
+ for (;;) {
+ // first determine what type of line this is
+ int c = in.get();
+ if (c == EOF)
+ break;
+ if (c == '.') {
+ int d = in.get();
+ if (d != EOF && csdigit(d)) {
+ in.unget(d);
+ type = DATA_INPUT_LINE;
+ }
+ else {
+ in.unget(d);
+ type = TROFF_INPUT_LINE;
+ }
+ }
+ else if (c == '_' || c == '=') {
+ int d = in.get();
+ if (d == '\n') {
+ if (c == '_')
+ type = SINGLE_HLINE;
+ else
+ type = DOUBLE_HLINE;
+ }
+ else {
+ in.unget(d);
+ type = DATA_INPUT_LINE;
+ }
+ }
+ else {
+ type = DATA_INPUT_LINE;
+ }
+ switch (type) {
+ case DATA_INPUT_LINE:
+ {
+ string input_entry;
+ if (format_index >= f->nrows)
+ format_index = f->nrows - 1;
+ // A format row that is all lines doesn't use up a data line.
+ while (format_index < f->nrows - 1) {
+ for (int c = 0; c < ncolumns; c++) {
+ entry_format *e = f->entry[format_index] + c;
+ if (e->type != FORMAT_HLINE
+ && e->type != FORMAT_DOUBLE_HLINE
+ // Unfortunately tbl treats a span as needing data.
+ // && e->type != FORMAT_SPAN
+ )
+ break;
+ }
+ if (c < ncolumns)
+ break;
+ for (c = 0; c < ncolumns; c++)
+ tbl->add_entry(current_row, c, input_entry,
+ f->entry[format_index] + c, current_filename,
+ current_lineno);
+ tbl->add_vlines(current_row, f->vline[format_index]);
+ format_index++;
+ current_row++;
+ }
+ entry_format *line_format = f->entry[format_index];
+ int col = 0;
+ for (;;) {
+ if (c == tab_char || c == '\n') {
+ int ln = current_lineno;
+ if (c == '\n')
+ --ln;
+ while (col < ncolumns
+ && line_format[col].type == FORMAT_SPAN) {
+ tbl->add_entry(current_row, col, "", &line_format[col],
+ current_filename, ln);
+ col++;
+ }
+ if (c == '\n' && input_entry.length() == 2
+ && input_entry[0] == 'T' && input_entry[1] == '{') {
+ input_entry = "";
+ ln++;
+ enum {
+ START, MIDDLE, GOT_T, GOT_RIGHT_BRACE, GOT_DOT,
+ GOT_l, GOT_lf, END
+ } state = START;
+ while (state != END) {
+ c = in.get();
+ if (c == EOF)
+ break;
+ switch (state) {
+ case START:
+ if (c == 'T')
+ state = GOT_T;
+ else if (c == '.')
+ state = GOT_DOT;
+ else {
+ input_entry += c;
+ if (c != '\n')
+ state = MIDDLE;
+ }
+ break;
+ case GOT_T:
+ if (c == '}')
+ state = GOT_RIGHT_BRACE;
+ else {
+ input_entry += 'T';
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case GOT_DOT:
+ if (c == 'l')
+ state = GOT_l;
+ else {
+ input_entry += '.';
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case GOT_l:
+ if (c == 'f')
+ state = GOT_lf;
+ else {
+ input_entry += ".l";
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case GOT_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string args;
+ input_entry += ".lf";
+ while (c != EOF) {
+ args += c;
+ if (c == '\n')
+ break;
+ c = in.get();
+ }
+ args += '\0';
+ interpret_lf_args(args.contents());
+ // remove the '\0'
+ args.set_length(args.length() - 1);
+ input_entry += args;
+ state = START;
+ }
+ else {
+ input_entry += ".lf";
+ input_entry += c;
+ state = MIDDLE;
+ }
+ break;
+ case GOT_RIGHT_BRACE:
+ if (c == '\n' || c == tab_char)
+ state = END;
+ else {
+ input_entry += 'T';
+ input_entry += '}';
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ if (c == '\n')
+ state = START;
+ input_entry += c;
+ break;
+ case END:
+ default:
+ assert(0);
+ }
+ }
+ if (c == EOF) {
+ error("end of data in middle of text block");
+ give_up = 1;
+ break;
+ }
+ }
+ if (col >= ncolumns) {
+ if (!input_entry.empty()) {
+ if (c == '\n')
+ in.unget(c);
+ input_entry += '\0';
+ error("excess data entry `%1' discarded",
+ input_entry.contents());
+ if (c == '\n')
+ (void)in.get();
+ }
+ }
+ else
+ tbl->add_entry(current_row, col, input_entry,
+ &line_format[col], current_filename, ln);
+ col++;
+ if (c == '\n')
+ break;
+ input_entry = "";
+ }
+ else
+ input_entry += c;
+ c = in.get();
+ if (c == EOF)
+ break;
+ }
+ if (give_up)
+ break;
+ input_entry = "";
+ for (; col < ncolumns; col++)
+ tbl->add_entry(current_row, col, input_entry, &line_format[col],
+ current_filename, current_lineno - 1);
+ tbl->add_vlines(current_row, f->vline[format_index]);
+ current_row++;
+ format_index++;
+ }
+ break;
+ case TROFF_INPUT_LINE:
+ {
+ string line;
+ int ln = current_lineno;
+ for (;;) {
+ line += c;
+ if (c == '\n')
+ break;
+ c = in.get();
+ if (c == EOF) {
+ break;
+ }
+ }
+ tbl->add_text_line(current_row, line, current_filename, ln);
+ if (line.length() >= 4
+ && line[0] == '.' && line[1] == 'T' && line[2] == '&') {
+ format *newf = process_format(in, opt, f);
+ if (newf == 0)
+ give_up = 1;
+ else
+ f = newf;
+ }
+ if (line.length() >= 3
+ && line[0] == '.' && line[1] == 'f' && line[2] == 'f') {
+ line += '\0';
+ interpret_lf_args(line.contents() + 3);
+ }
+ }
+ break;
+ case SINGLE_HLINE:
+ tbl->add_single_hline(current_row);
+ break;
+ case DOUBLE_HLINE:
+ tbl->add_double_hline(current_row);
+ break;
+ default:
+ assert(0);
+ }
+ if (give_up)
+ break;
+ }
+ if (!give_up && current_row == 0) {
+ error("no real data");
+ give_up = 1;
+ }
+ if (give_up) {
+ delete tbl;
+ return 0;
+ }
+ // Do this here rather than at the beginning in case continued formats
+ // change it.
+ for (int i = 0; i < ncolumns - 1; i++)
+ if (f->separation[i] >= 0)
+ tbl->set_column_separation(i, f->separation[i]);
+ for (i = 0; i < ncolumns; i++)
+ if (!f->width[i].empty())
+ tbl->set_minimum_width(i, f->width[i]);
+ for (i = 0; i < ncolumns; i++)
+ if (f->equal[i])
+ tbl->set_equal_column(i);
+ return tbl;
+}
+
+void process_table(table_input &in)
+{
+ int c;
+ options *opt = 0;
+ format *form = 0;
+ table *tbl = 0;
+ if ((opt = process_options(in)) != 0
+ && (form = process_format(in, opt)) != 0
+ && (tbl = process_data(in, form, opt)) != 0) {
+ tbl->print();
+ delete tbl;
+ }
+ else {
+ error("giving up on this table");
+ while ((c = in.get()) != EOF)
+ ;
+ }
+ delete opt;
+ delete form;
+ if (!in.ended())
+ error("premature end of file");
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [ -vC ] [ files... ]\n", program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ while ((opt = getopt(argc, argv, "vC")) != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU tbl version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ printf(".if !\\n(.g .ab GNU tbl requires GNU troff.\n"
+ ".if !dTS .ds TS\n"
+ ".if !dTE .ds TE\n");
+ if (argc > optind) {
+ for (int i = optind; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == '\0') {
+ current_filename = "-";
+ current_lineno = 1;
+ printf(".lf 1 -\n");
+ process_input_file(stdin);
+ }
+ else {
+ errno = 0;
+ FILE *fp = fopen(argv[i], "r");
+ if (fp == 0) {
+ current_lineno = -1;
+ error("can't open `%1': %2", argv[i], strerror(errno));
+ }
+ else {
+ current_lineno = 1;
+ current_filename = argv[i];
+ printf(".lf 1 %s\n", current_filename);
+ process_input_file(fp);
+ }
+ }
+ }
+ else {
+ current_filename = "-";
+ current_lineno = 1;
+ printf(".lf 1 -\n");
+ process_input_file(stdin);
+ }
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ exit(0);
+}
+
diff --git a/gnu/usr.bin/groff/tbl/table.cc b/gnu/usr.bin/groff/tbl/table.cc
new file mode 100644
index 000000000000..76c7cd74a9c6
--- /dev/null
+++ b/gnu/usr.bin/groff/tbl/table.cc
@@ -0,0 +1,2764 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "table.h"
+
+#define BAR_HEIGHT ".25m"
+#define DOUBLE_LINE_SEP "2p"
+#define HALF_DOUBLE_LINE_SEP "1p"
+#define LINE_SEP "2p"
+#define BODY_DEPTH ".25m"
+
+const int DEFAULT_COLUMN_SEPARATION = 3;
+
+#define DELIMITER_CHAR "\\[tbl]"
+#define PREFIX "3"
+#define SEPARATION_FACTOR_REG PREFIX "sep"
+#define BOTTOM_REG PREFIX "bot"
+#define RESET_MACRO_NAME PREFIX "init"
+#define LINESIZE_REG PREFIX "lps"
+#define TOP_REG PREFIX "top"
+#define CURRENT_ROW_REG PREFIX "crow"
+#define LAST_PASSED_ROW_REG PREFIX "passed"
+#define TRANSPARENT_STRING_NAME PREFIX "trans"
+#define QUOTE_STRING_NAME PREFIX "quote"
+#define SECTION_DIVERSION_NAME PREFIX "section"
+#define SECTION_DIVERSION_FLAG_REG PREFIX "sflag"
+#define SAVED_VERTICAL_POS_REG PREFIX "vert"
+#define NEED_BOTTOM_RULE_REG PREFIX "brule"
+#define KEEP_MACRO_NAME PREFIX "keep"
+#define RELEASE_MACRO_NAME PREFIX "release"
+#define SAVED_FONT_REG PREFIX "fnt"
+#define SAVED_SIZE_REG PREFIX "sz"
+#define SAVED_FILL_REG PREFIX "fll"
+#define SAVED_INDENT_REG PREFIX "ind"
+#define SAVED_CENTER_REG PREFIX "cent"
+#define TABLE_DIVERSION_NAME PREFIX "table"
+#define TABLE_DIVERSION_FLAG_REG PREFIX "tflag"
+#define TABLE_KEEP_MACRO_NAME PREFIX "tkeep"
+#define TABLE_RELEASE_MACRO_NAME PREFIX "trelease"
+#define NEEDED_REG PREFIX "needed"
+#define REPEATED_MARK_MACRO PREFIX "rmk"
+#define REPEATED_VPT_MACRO PREFIX "rvpt"
+#define SUPPRESS_BOTTOM_REG PREFIX "supbot"
+#define SAVED_DN_REG PREFIX "dn"
+
+// this must be one character
+#define COMPATIBLE_REG PREFIX "c"
+
+#define BLOCK_WIDTH_PREFIX PREFIX "tbw"
+#define BLOCK_DIVERSION_PREFIX PREFIX "tbd"
+#define BLOCK_HEIGHT_PREFIX PREFIX "tbh"
+#define SPAN_WIDTH_PREFIX PREFIX "w"
+#define SPAN_LEFT_NUMERIC_WIDTH_PREFIX PREFIX "lnw"
+#define SPAN_RIGHT_NUMERIC_WIDTH_PREFIX PREFIX "rnw"
+#define SPAN_ALPHABETIC_WIDTH_PREFIX PREFIX "aw"
+#define COLUMN_SEPARATION_PREFIX PREFIX "cs"
+#define ROW_START_PREFIX PREFIX "rs"
+#define COLUMN_START_PREFIX PREFIX "cl"
+#define COLUMN_END_PREFIX PREFIX "ce"
+#define COLUMN_DIVIDE_PREFIX PREFIX "cd"
+#define ROW_TOP_PREFIX PREFIX "rt"
+
+string block_width_reg(int r, int c);
+string block_diversion_name(int r, int c);
+string block_height_reg(int r, int c);
+string span_width_reg(int start_col, int end_col);
+string span_left_numeric_width_reg(int start_col, int end_col);
+string span_right_numeric_width_reg(int start_col, int end_col);
+string span_alphabetic_width_reg(int start_col, int end_col);
+string column_separation_reg(int col);
+string row_start_reg(int r);
+string column_start_reg(int c);
+string column_end_reg(int c);
+string column_divide_reg(int c);
+string row_top_reg(int r);
+
+void set_inline_modifier(const entry_modifier *);
+void restore_inline_modifier(const entry_modifier *m);
+void set_modifier(const entry_modifier *);
+int find_decimal_point(const char *s, char decimal_point_char,
+ const char *delim);
+
+string an_empty_string;
+int location_force_filename = 0;
+
+void printfs(const char *,
+ const string &arg1 = an_empty_string,
+ const string &arg2 = an_empty_string,
+ const string &arg3 = an_empty_string,
+ const string &arg4 = an_empty_string,
+ const string &arg5 = an_empty_string);
+
+void prints(const string &);
+
+inline void prints(char c)
+{
+ putchar(c);
+}
+
+inline void prints(const char *s)
+{
+ fputs(s, stdout);
+}
+
+void prints(const string &s)
+{
+ if (!s.empty())
+ fwrite(s.contents(), 1, s.length(), stdout);
+}
+
+struct horizontal_span {
+ horizontal_span *next;
+ short start_col;
+ short end_col;
+ horizontal_span(int, int, horizontal_span *);
+};
+
+struct single_line_entry;
+struct double_line_entry;
+struct simple_entry;
+
+class table_entry {
+friend class table;
+ table_entry *next;
+ int input_lineno;
+ const char *input_filename;
+protected:
+ short start_row;
+ short start_col;
+ short end_row;
+ short end_col;
+ const entry_modifier *mod;
+public:
+ void set_location();
+ table_entry(const entry_modifier *);
+ virtual ~table_entry();
+ virtual int divert(int ncols, const string *mw, int *sep);
+ virtual void do_width();
+ virtual void do_depth();
+ virtual void print() = 0;
+ virtual void position_vertically() = 0;
+ virtual single_line_entry *to_single_line_entry();
+ virtual double_line_entry *to_double_line_entry();
+ virtual simple_entry *to_simple_entry();
+ virtual int line_type();
+ virtual void note_double_vrule_on_right(int);
+ virtual void note_double_vrule_on_left(int);
+};
+
+class simple_entry : public table_entry {
+public:
+ simple_entry(const entry_modifier *);
+ void print();
+ void position_vertically();
+ simple_entry *to_simple_entry();
+ virtual void add_tab();
+ virtual void simple_print(int);
+};
+
+class empty_entry : public simple_entry {
+public:
+ empty_entry(const entry_modifier *);
+ int line_type();
+};
+
+class text_entry : public simple_entry {
+protected:
+ char *contents;
+ void print_contents();
+public:
+ text_entry(char *, const entry_modifier *);
+ ~text_entry();
+};
+
+void text_entry::print_contents()
+{
+ set_inline_modifier(mod);
+ prints(contents);
+ restore_inline_modifier(mod);
+}
+
+class repeated_char_entry : public text_entry {
+public:
+ repeated_char_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+};
+
+class simple_text_entry : public text_entry {
+public:
+ simple_text_entry(char *s, const entry_modifier *m);
+ void do_width();
+};
+
+class left_text_entry : public simple_text_entry {
+public:
+ left_text_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+ void add_tab();
+};
+
+class right_text_entry : public simple_text_entry {
+public:
+ right_text_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+ void add_tab();
+};
+
+class center_text_entry : public simple_text_entry {
+public:
+ center_text_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+ void add_tab();
+};
+
+class numeric_text_entry : public text_entry {
+ int dot_pos;
+public:
+ numeric_text_entry(char *s, const entry_modifier *m, int pos);
+ void do_width();
+ void simple_print(int);
+};
+
+class alphabetic_text_entry : public text_entry {
+public:
+ alphabetic_text_entry(char *s, const entry_modifier *m);
+ void do_width();
+ void simple_print(int);
+ void add_tab();
+};
+
+class line_entry : public simple_entry {
+protected:
+ char double_vrule_on_right;
+ char double_vrule_on_left;
+public:
+ line_entry(const entry_modifier *);
+ void note_double_vrule_on_right(int);
+ void note_double_vrule_on_left(int);
+ void simple_print(int) = 0;
+};
+
+class single_line_entry : public line_entry {
+public:
+ single_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ single_line_entry *to_single_line_entry();
+ int line_type();
+};
+
+class double_line_entry : public line_entry {
+public:
+ double_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ double_line_entry *to_double_line_entry();
+ int line_type();
+};
+
+class short_line_entry : public simple_entry {
+public:
+ short_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ int line_type();
+};
+
+class short_double_line_entry : public simple_entry {
+public:
+ short_double_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ int line_type();
+};
+
+class block_entry : public table_entry {
+ char *contents;
+protected:
+ void do_divert(int alphabetic, int ncols, const string *mw, int *sep);
+public:
+ block_entry(char *s, const entry_modifier *m);
+ ~block_entry();
+ int divert(int ncols, const string *mw, int *sep);
+ void do_width();
+ void do_depth();
+ void position_vertically();
+ void print() = 0;
+};
+
+class left_block_entry : public block_entry {
+public:
+ left_block_entry(char *s, const entry_modifier *m);
+ void print();
+};
+
+class right_block_entry : public block_entry {
+public:
+ right_block_entry(char *s, const entry_modifier *m);
+ void print();
+};
+
+class center_block_entry : public block_entry {
+public:
+ center_block_entry(char *s, const entry_modifier *m);
+ void print();
+};
+
+class alphabetic_block_entry : public block_entry {
+public:
+ alphabetic_block_entry(char *s, const entry_modifier *m);
+ void print();
+ int divert(int ncols, const string *mw, int *sep);
+};
+
+table_entry::table_entry(const entry_modifier *m)
+: next(0), start_row(-1), end_row(-1), start_col(-1), end_col(-1), mod(m),
+ input_lineno(-1), input_filename(0)
+{
+}
+
+table_entry::~table_entry()
+{
+}
+
+int table_entry::divert(int, const string *, int *)
+{
+ return 0;
+}
+
+void table_entry::do_width()
+{
+}
+
+single_line_entry *table_entry::to_single_line_entry()
+{
+ return 0;
+}
+
+double_line_entry *table_entry::to_double_line_entry()
+{
+ return 0;
+}
+
+simple_entry *table_entry::to_simple_entry()
+{
+ return 0;
+}
+
+void table_entry::do_depth()
+{
+}
+
+void table_entry::set_location()
+{
+ set_troff_location(input_filename, input_lineno);
+}
+
+int table_entry::line_type()
+{
+ return -1;
+}
+
+void table_entry::note_double_vrule_on_right(int)
+{
+}
+
+void table_entry::note_double_vrule_on_left(int)
+{
+}
+
+simple_entry::simple_entry(const entry_modifier *m) : table_entry(m)
+{
+}
+
+void simple_entry::add_tab()
+{
+ // do nothing
+}
+
+void simple_entry::simple_print(int)
+{
+ // do nothing
+}
+
+void simple_entry::position_vertically()
+{
+ if (start_row != end_row)
+ switch (mod->vertical_alignment) {
+ case entry_modifier::TOP:
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ break;
+ case entry_modifier::CENTER:
+ // Peform the motion in two stages so that the center is rounded
+ // vertically upwards even if net vertical motion is upwards.
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-1v/2u\n",
+ row_start_reg(start_row));
+ break;
+ case entry_modifier::BOTTOM:
+ printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-1v\n",
+ row_start_reg(start_row));
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void simple_entry::print()
+{
+ prints(".ta");
+ add_tab();
+ prints('\n');
+ set_location();
+ prints("\\&");
+ simple_print(0);
+ prints('\n');
+}
+
+simple_entry *simple_entry::to_simple_entry()
+{
+ return this;
+}
+
+empty_entry::empty_entry(const entry_modifier *m)
+: simple_entry(m)
+{
+}
+
+int empty_entry::line_type()
+{
+ return 0;
+}
+
+text_entry::text_entry(char *s, const entry_modifier *m)
+: contents(s), simple_entry(m)
+{
+}
+
+text_entry::~text_entry()
+{
+ a_delete contents;
+}
+
+
+repeated_char_entry::repeated_char_entry(char *s, const entry_modifier *m)
+: text_entry(s, m)
+{
+}
+
+void repeated_char_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ set_inline_modifier(mod);
+ printfs("\\l" DELIMITER_CHAR "\\n[%1]u\\&",
+ span_width_reg(start_col, end_col));
+ prints(contents);
+ prints(DELIMITER_CHAR);
+ restore_inline_modifier(mod);
+}
+
+simple_text_entry::simple_text_entry(char *s, const entry_modifier *m)
+: text_entry(s, m)
+{
+}
+
+void simple_text_entry::do_width()
+{
+ set_location();
+ printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
+ span_width_reg(start_col, end_col));
+ print_contents();
+ prints(DELIMITER_CHAR "\n");
+}
+
+left_text_entry::left_text_entry(char *s, const entry_modifier *m)
+: simple_text_entry(s, m)
+{
+}
+
+void left_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ print_contents();
+}
+
+// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr.
+
+void left_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+right_text_entry::right_text_entry(char *s, const entry_modifier *m)
+: simple_text_entry(s, m)
+{
+}
+
+void right_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ prints("\002\003");
+ print_contents();
+ prints("\002");
+}
+
+void right_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+center_text_entry::center_text_entry(char *s, const entry_modifier *m)
+: simple_text_entry(s, m)
+{
+}
+
+void center_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ prints("\002\003");
+ print_contents();
+ prints("\003\002");
+}
+
+void center_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+numeric_text_entry::numeric_text_entry(char *s, const entry_modifier *m, int pos)
+: text_entry(s, m), dot_pos(pos)
+{
+}
+
+void numeric_text_entry::do_width()
+{
+ if (dot_pos != 0) {
+ set_location();
+ printfs(".nr %1 0\\w" DELIMITER_CHAR,
+ block_width_reg(start_row, start_col));
+ set_inline_modifier(mod);
+ for (int i = 0; i < dot_pos; i++)
+ prints(contents[i]);
+ restore_inline_modifier(mod);
+ prints(DELIMITER_CHAR "\n");
+ printfs(".nr %1 \\n[%1]>?\\n[%2]\n",
+ span_left_numeric_width_reg(start_col, end_col),
+ block_width_reg(start_row, start_col));
+ }
+ else
+ printfs(".nr %1 0\n", block_width_reg(start_row, start_col));
+ if (contents[dot_pos] != '\0') {
+ set_location();
+ printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
+ span_right_numeric_width_reg(start_col, end_col));
+ set_inline_modifier(mod);
+ prints(contents + dot_pos);
+ restore_inline_modifier(mod);
+ prints(DELIMITER_CHAR "\n");
+ }
+}
+
+void numeric_text_entry::simple_print(int)
+{
+ printfs("\\h'|(\\n[%1]u-\\n[%2]u-\\n[%3]u/2u+\\n[%2]u+\\n[%4]u-\\n[%5]u)'",
+ span_width_reg(start_col, end_col),
+ span_left_numeric_width_reg(start_col, end_col),
+ span_right_numeric_width_reg(start_col, end_col),
+ column_start_reg(start_col),
+ block_width_reg(start_row, start_col));
+ print_contents();
+}
+
+alphabetic_text_entry::alphabetic_text_entry(char *s, const entry_modifier *m)
+: text_entry(s, m)
+{
+}
+
+void alphabetic_text_entry::do_width()
+{
+ set_location();
+ printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
+ span_alphabetic_width_reg(start_col, end_col));
+ print_contents();
+ prints(DELIMITER_CHAR "\n");
+}
+
+void alphabetic_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ printfs("\\h'\\n[%1]u-\\n[%2]u/2u'",
+ span_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col));
+ print_contents();
+}
+
+// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr.
+
+void alphabetic_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+block_entry::block_entry(char *s, const entry_modifier *m)
+: table_entry(m), contents(s)
+{
+}
+
+block_entry::~block_entry()
+{
+ a_delete contents;
+}
+
+void block_entry::position_vertically()
+{
+ if (start_row != end_row)
+ switch(mod->vertical_alignment) {
+ case entry_modifier::TOP:
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ break;
+ case entry_modifier::CENTER:
+ // Peform the motion in two stages so that the center is rounded
+ // vertically upwards even if net vertical motion is upwards.
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u/2u\n",
+ row_start_reg(start_row),
+ block_height_reg(start_row, start_col));
+ break;
+ case entry_modifier::BOTTOM:
+ printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u\n",
+ row_start_reg(start_row),
+ block_height_reg(start_row, start_col));
+ break;
+ default:
+ assert(0);
+ }
+ if (mod->stagger)
+ prints(".sp -.5v\n");
+}
+
+int block_entry::divert(int ncols, const string *mw, int *sep)
+{
+ do_divert(0, ncols, mw, sep);
+ return 1;
+}
+
+void block_entry::do_divert(int alphabetic, int ncols, const string *mw,
+ int *sep)
+{
+ printfs(".di %1\n", block_diversion_name(start_row, start_col));
+ prints(".if \\n[" SAVED_FILL_REG "] .fi\n"
+ ".in 0\n");
+ prints(".ll ");
+ for (int i = start_col; i <= end_col; i++)
+ if (mw[i].empty())
+ break;
+ if (i > end_col) {
+ // Every column spanned by this entry has a minimum width.
+ for (int i = start_col; i <= end_col; i++) {
+ if (i > start_col) {
+ if (sep)
+ printfs("+%1n", as_string(sep[i - 1]));
+ prints('+');
+ }
+ printfs("(n;%1)", mw[i]);
+ }
+ printfs(">?\\n[%1]u", span_width_reg(start_col, end_col));
+ }
+ else
+ printfs("(u;\\n[%1]>?(\\n[.l]*%2/%3))",
+ span_width_reg(start_col, end_col),
+ as_string(end_col - start_col + 1),
+ as_string(ncols + 1));
+ if (alphabetic)
+ prints("-2n");
+ prints("\n");
+ set_modifier(mod);
+ prints(".cp \\n(" COMPATIBLE_REG "\n");
+ set_location();
+ prints(contents);
+ prints(".br\n.di\n.cp 0\n");
+ if (!mod->zero_width) {
+ if (alphabetic) {
+ printfs(".nr %1 \\n[%1]>?(\\n[dl]+2n)\n",
+ span_width_reg(start_col, end_col));
+ printfs(".nr %1 \\n[%1]>?\\n[dl]\n",
+ span_alphabetic_width_reg(start_col, end_col));
+ }
+ else
+ printfs(".nr %1 \\n[%1]>?\\n[dl]\n", span_width_reg(start_col, end_col));
+ }
+ printfs(".nr %1 \\n[dn]\n", block_height_reg(start_row, start_col));
+ printfs(".nr %1 \\n[dl]\n", block_width_reg(start_row, start_col));
+ prints("." RESET_MACRO_NAME "\n"
+ ".in \\n[" SAVED_INDENT_REG "]u\n"
+ ".nf\n");
+ // the block might have contained .lf commands
+ location_force_filename = 1;
+}
+
+void block_entry::do_width()
+{
+ // do nothing; the action happens in divert
+}
+
+void block_entry::do_depth()
+{
+ printfs(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?(\\n[%1]+\\n[%2])\n",
+ row_start_reg(start_row),
+ block_height_reg(start_row, start_col));
+}
+
+left_block_entry::left_block_entry(char *s, const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+void left_block_entry::print()
+{
+ printfs(".in +\\n[%1]u\n", column_start_reg(start_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+
+
+right_block_entry::right_block_entry(char *s, const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+void right_block_entry::print()
+{
+ printfs(".in +\\n[%1]u+\\n[%2]u-\\n[%3]u\n",
+ column_start_reg(start_col),
+ span_width_reg(start_col, end_col),
+ block_width_reg(start_row, start_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+center_block_entry::center_block_entry(char *s, const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+void center_block_entry::print()
+{
+ printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n",
+ column_start_reg(start_col),
+ span_width_reg(start_col, end_col),
+ block_width_reg(start_row, start_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+alphabetic_block_entry::alphabetic_block_entry(char *s,
+ const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+int alphabetic_block_entry::divert(int ncols, const string *mw, int *sep)
+{
+ do_divert(1, ncols, mw, sep);
+ return 1;
+}
+
+void alphabetic_block_entry::print()
+{
+ printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n",
+ column_start_reg(start_col),
+ span_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+line_entry::line_entry(const entry_modifier *m)
+: simple_entry(m), double_vrule_on_right(0), double_vrule_on_left(0)
+{
+}
+
+void line_entry::note_double_vrule_on_right(int is_corner)
+{
+ double_vrule_on_right = is_corner ? 1 : 2;
+}
+
+void line_entry::note_double_vrule_on_left(int is_corner)
+{
+ double_vrule_on_left = is_corner ? 1 : 2;
+}
+
+
+single_line_entry::single_line_entry(const entry_modifier *m)
+: line_entry(m)
+{
+}
+
+int single_line_entry::line_type()
+{
+ return 1;
+}
+
+void single_line_entry::simple_print(int dont_move)
+{
+ printfs("\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (double_vrule_on_left) {
+ prints(double_vrule_on_left == 1 ? "-" : "+");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints("'");
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\s[\\n[" LINESIZE_REG "]]" "\\D'l |\\n[%1]u",
+ column_divide_reg(end_col+1));
+ if (double_vrule_on_right) {
+ prints(double_vrule_on_left == 1 ? "+" : "-");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints("0'\\s0");
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+}
+
+single_line_entry *single_line_entry::to_single_line_entry()
+{
+ return this;
+}
+
+double_line_entry::double_line_entry(const entry_modifier *m)
+: line_entry(m)
+{
+}
+
+int double_line_entry::line_type()
+{
+ return 2;
+}
+
+void double_line_entry::simple_print(int dont_move)
+{
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (double_vrule_on_left) {
+ prints(double_vrule_on_left == 1 ? "-" : "+");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints("'");
+ printfs("\\v'-" HALF_DOUBLE_LINE_SEP "'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l |\\n[%1]u",
+ column_divide_reg(end_col+1));
+ if (double_vrule_on_right)
+ prints("-" HALF_DOUBLE_LINE_SEP);
+ prints(" 0'");
+ printfs("\\v'" DOUBLE_LINE_SEP "'"
+ "\\D'l |\\n[%1]u",
+ column_divide_reg(start_col));
+ if (double_vrule_on_right) {
+ prints(double_vrule_on_left == 1 ? "+" : "-");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints(" 0'");
+ prints("\\s0"
+ "\\v'-" HALF_DOUBLE_LINE_SEP "'");
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+}
+
+double_line_entry *double_line_entry::to_double_line_entry()
+{
+ return this;
+}
+
+short_line_entry::short_line_entry(const entry_modifier *m)
+: simple_entry(m)
+{
+}
+
+int short_line_entry::line_type()
+{
+ return 1;
+}
+
+void short_line_entry::simple_print(int dont_move)
+{
+ if (mod->stagger)
+ prints("\\v'-.5v'");
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ printfs("\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l \\n[%1]u 0'"
+ "\\s0",
+ span_width_reg(start_col, end_col));
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+ if (mod->stagger)
+ prints("\\v'.5v'");
+}
+
+short_double_line_entry::short_double_line_entry(const entry_modifier *m)
+: simple_entry(m)
+{
+}
+
+int short_double_line_entry::line_type()
+{
+ return 2;
+}
+
+void short_double_line_entry::simple_print(int dont_move)
+{
+ if (mod->stagger)
+ prints("\\v'-.5v'");
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\h'|\\n[%2]u'"
+ "\\v'-" HALF_DOUBLE_LINE_SEP "'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l \\n[%1]u 0'"
+ "\\v'" DOUBLE_LINE_SEP "'"
+ "\\D'l |\\n[%2]u 0'"
+ "\\s0"
+ "\\v'-" HALF_DOUBLE_LINE_SEP "'",
+ span_width_reg(start_col, end_col),
+ column_start_reg(start_col));
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+ if (mod->stagger)
+ prints("\\v'.5v'");
+}
+
+void set_modifier(const entry_modifier *m)
+{
+ if (!m->font.empty())
+ printfs(".ft %1\n", m->font);
+ if (m->point_size.val != 0) {
+ prints(".ps ");
+ if (m->point_size.inc > 0)
+ prints('+');
+ else if (m->point_size.inc < 0)
+ prints('-');
+ printfs("%1\n", as_string(m->point_size.val));
+ }
+ if (m->vertical_spacing.val != 0) {
+ prints(".vs ");
+ if (m->vertical_spacing.inc > 0)
+ prints('+');
+ else if (m->vertical_spacing.inc < 0)
+ prints('-');
+ printfs("%1\n", as_string(m->vertical_spacing.val));
+ }
+}
+
+void set_inline_modifier(const entry_modifier *m)
+{
+ if (!m->font.empty())
+ printfs("\\f[%1]", m->font);
+ if (m->point_size.val != 0) {
+ prints("\\s[");
+ if (m->point_size.inc > 0)
+ prints('+');
+ else if (m->point_size.inc < 0)
+ prints('-');
+ printfs("%1]", as_string(m->point_size.val));
+ }
+ if (m->stagger)
+ prints("\\v'-.5v'");
+}
+
+void restore_inline_modifier(const entry_modifier *m)
+{
+ if (!m->font.empty())
+ prints("\\f[\\n[" SAVED_FONT_REG "]]");
+ if (m->point_size.val != 0)
+ prints("\\s[\\n[" SAVED_SIZE_REG "]]");
+ if (m->stagger)
+ prints("\\v'.5v'");
+}
+
+
+struct stuff {
+ stuff *next;
+ int row; // occurs before row `row'
+ char printed; // has it been printed?
+
+ stuff(int);
+ virtual void print(table *) = 0;
+ virtual ~stuff();
+ virtual int is_single_line() { return 0; };
+ virtual int is_double_line() { return 0; };
+};
+
+stuff::stuff(int r) : row(r), next(0), printed(0)
+{
+}
+
+stuff::~stuff()
+{
+}
+
+struct text_stuff : stuff {
+ string contents;
+ const char *filename;
+ int lineno;
+
+ text_stuff(const string &, int r, const char *fn, int ln);
+ ~text_stuff();
+ void print(table *);
+};
+
+
+text_stuff::text_stuff(const string &s, int r, const char *fn, int ln)
+: contents(s), stuff(r), filename(fn), lineno(ln)
+{
+}
+
+text_stuff::~text_stuff()
+{
+}
+
+void text_stuff::print(table *)
+{
+ printed = 1;
+ prints(".cp \\n(" COMPATIBLE_REG "\n");
+ set_troff_location(filename, lineno);
+ prints(contents);
+ prints(".cp 0\n");
+ location_force_filename = 1; // it might have been a .lf command
+}
+
+struct single_hline_stuff : stuff {
+ single_hline_stuff(int r);
+ void print(table *);
+ int is_single_line();
+};
+
+single_hline_stuff::single_hline_stuff(int r) : stuff(r)
+{
+}
+
+void single_hline_stuff::print(table *tbl)
+{
+ printed = 1;
+ tbl->print_single_hline(row);
+}
+
+int single_hline_stuff::is_single_line()
+{
+ return 1;
+}
+
+struct double_hline_stuff : stuff {
+ double_hline_stuff(int r);
+ void print(table *);
+ int is_double_line();
+};
+
+double_hline_stuff::double_hline_stuff(int r) : stuff(r)
+{
+}
+
+void double_hline_stuff::print(table *tbl)
+{
+ printed = 1;
+ tbl->print_double_hline(row);
+}
+
+int double_hline_stuff::is_double_line()
+{
+ return 1;
+}
+
+struct vertical_rule {
+ vertical_rule *next;
+ short start_row;
+ short end_row;
+ short col;
+ char is_double;
+ string top_adjust;
+ string bot_adjust;
+
+ vertical_rule(int sr, int er, int c, int dbl, vertical_rule *);
+ ~vertical_rule();
+ void contribute_to_bottom_macro(table *);
+ void print();
+};
+
+vertical_rule::vertical_rule(int sr, int er, int c, int dbl, vertical_rule *p)
+: start_row(sr), end_row(er), col(c), is_double(dbl), next(p)
+{
+}
+
+vertical_rule::~vertical_rule()
+{
+}
+
+void vertical_rule::contribute_to_bottom_macro(table *tbl)
+{
+ printfs(".if \\n[" CURRENT_ROW_REG "]>=%1",
+ as_string(start_row));
+ if (end_row != tbl->get_nrows() - 1)
+ printfs("&(\\n[" CURRENT_ROW_REG "]<%1)",
+ as_string(end_row));
+ prints(" \\{");
+ printfs(".if %1<=\\n[" LAST_PASSED_ROW_REG "] .nr %2 \\n[#T]\n",
+ as_string(start_row),
+ row_top_reg(start_row));
+ const char *offset_table[3];
+ if (is_double) {
+ offset_table[0] = "-" HALF_DOUBLE_LINE_SEP;
+ offset_table[1] = "+" HALF_DOUBLE_LINE_SEP;
+ offset_table[2] = 0;
+ }
+ else {
+ offset_table[0] = "";
+ offset_table[1] = 0;
+ }
+ for (const char **offsetp = offset_table; *offsetp; offsetp++) {
+ prints(".sp -1\n"
+ "\\v'" BODY_DEPTH);
+ if (!bot_adjust.empty())
+ printfs("+%1", bot_adjust);
+ prints("'");
+ printfs("\\h'\\n[%1]u%3'\\s[\\n[" LINESIZE_REG "]]\\D'l 0 |\\n[%2]u-1v",
+ column_divide_reg(col),
+ row_top_reg(start_row),
+ *offsetp);
+ if (!bot_adjust.empty())
+ printfs("-(%1)", bot_adjust);
+ // don't perform the top adjustment if the top is actually #T
+ if (!top_adjust.empty())
+ printfs("+((%1)*(%2>\\n[" LAST_PASSED_ROW_REG "]))",
+ top_adjust,
+ as_string(start_row));
+ prints("'\\s0\n");
+ }
+ prints(".\\}\n");
+}
+
+void vertical_rule::print()
+{
+ printfs("\\*[" TRANSPARENT_STRING_NAME "]"
+ ".if %1<=\\*[" QUOTE_STRING_NAME "]\\n[" LAST_PASSED_ROW_REG "] "
+ ".nr %2 \\*[" QUOTE_STRING_NAME "]\\n[#T]\n",
+ as_string(start_row),
+ row_top_reg(start_row));
+ const char *offset_table[3];
+ if (is_double) {
+ offset_table[0] = "-" HALF_DOUBLE_LINE_SEP;
+ offset_table[1] = "+" HALF_DOUBLE_LINE_SEP;
+ offset_table[2] = 0;
+ }
+ else {
+ offset_table[0] = "";
+ offset_table[1] = 0;
+ }
+ for (const char **offsetp = offset_table; *offsetp; offsetp++) {
+ prints("\\*[" TRANSPARENT_STRING_NAME "].sp -1\n"
+ "\\*[" TRANSPARENT_STRING_NAME "]\\v'" BODY_DEPTH);
+ if (!bot_adjust.empty())
+ printfs("+%1", bot_adjust);
+ prints("'");
+ printfs("\\h'\\n[%1]u%3'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l 0 |\\*[" QUOTE_STRING_NAME "]\\n[%2]u-1v",
+ column_divide_reg(col),
+ row_top_reg(start_row),
+ *offsetp);
+ if (!bot_adjust.empty())
+ printfs("-(%1)", bot_adjust);
+ // don't perform the top adjustment if the top is actually #T
+ if (!top_adjust.empty())
+ printfs("+((%1)*(%2>\\*[" QUOTE_STRING_NAME "]\\n["
+ LAST_PASSED_ROW_REG "]))",
+ top_adjust,
+ as_string(start_row));
+ prints("'"
+ "\\s0\n");
+ }
+}
+
+table::table(int nc, unsigned f, int ls, char dpc)
+: ncolumns(nc), flags(f), linesize(ls), decimal_point_char(dpc),
+ nrows(0), allocated_rows(0), entry(0), entry_list(0),
+ left_separation(0), right_separation(0), stuff_list(0), vline(0),
+ vrule_list(0), row_is_all_lines(0), span_list(0)
+{
+ minimum_width = new string[ncolumns];
+ column_separation = ncolumns > 1 ? new int[ncolumns - 1] : 0;
+ equal = new char[ncolumns];
+ int i;
+ for (i = 0; i < ncolumns; i++)
+ equal[i] = 0;
+ for (i = 0; i < ncolumns-1; i++)
+ column_separation[i] = DEFAULT_COLUMN_SEPARATION;
+ delim[0] = delim[1] = '\0';
+}
+
+table::~table()
+{
+ for (int i = 0; i < nrows; i++) {
+ a_delete entry[i];
+ a_delete vline[i];
+ }
+ a_delete entry;
+ a_delete vline;
+ while (entry_list) {
+ table_entry *tem = entry_list;
+ entry_list = entry_list->next;
+ delete tem;
+ }
+ ad_delete(ncolumns) minimum_width;
+ a_delete column_separation;
+ a_delete equal;
+ while (stuff_list) {
+ stuff *tem = stuff_list;
+ stuff_list = stuff_list->next;
+ delete tem;
+ }
+ while (vrule_list) {
+ vertical_rule *tem = vrule_list;
+ vrule_list = vrule_list->next;
+ delete tem;
+ }
+ a_delete row_is_all_lines;
+ while (span_list) {
+ horizontal_span *tem = span_list;
+ span_list = span_list->next;
+ delete tem;
+ }
+}
+
+void table::set_delim(char c1, char c2)
+{
+ delim[0] = c1;
+ delim[1] = c2;
+}
+
+void table::set_minimum_width(int c, const string &w)
+{
+ assert(c >= 0 && c < ncolumns);
+ minimum_width[c] = w;
+}
+
+void table::set_column_separation(int c, int n)
+{
+ assert(c >= 0 && c < ncolumns - 1);
+ column_separation[c] = n;
+}
+
+void table::set_equal_column(int c)
+{
+ assert(c >= 0 && c < ncolumns);
+ equal[c] = 1;
+}
+
+void table::add_stuff(stuff *p)
+{
+ for (stuff **pp = &stuff_list; *pp; pp = &(*pp)->next)
+ ;
+ *pp = p;
+}
+
+void table::add_text_line(int r, const string &s, const char *filename, int lineno)
+{
+ add_stuff(new text_stuff(s, r, filename, lineno));
+}
+
+void table::add_single_hline(int r)
+{
+ add_stuff(new single_hline_stuff(r));
+}
+
+void table::add_double_hline(int r)
+{
+ add_stuff(new double_hline_stuff(r));
+}
+
+void table::allocate(int r)
+{
+ if (r >= nrows) {
+ typedef table_entry **PPtable_entry; // work around g++ 1.36.1 bug
+ if (r >= allocated_rows) {
+ if (allocated_rows == 0) {
+ allocated_rows = 16;
+ if (allocated_rows <= r)
+ allocated_rows = r + 1;
+ entry = new PPtable_entry[allocated_rows];
+ vline = new char*[allocated_rows];
+ }
+ else {
+ table_entry ***old_entry = entry;
+ int old_allocated_rows = allocated_rows;
+ allocated_rows *= 2;
+ if (allocated_rows <= r)
+ allocated_rows = r + 1;
+ entry = new PPtable_entry[allocated_rows];
+ memcpy(entry, old_entry, sizeof(table_entry**)*old_allocated_rows);
+ a_delete old_entry;
+ char **old_vline = vline;
+ vline = new char*[allocated_rows];
+ memcpy(vline, old_vline, sizeof(char*)*old_allocated_rows);
+ a_delete old_vline;
+ }
+ }
+ assert(allocated_rows > r);
+ while (nrows <= r) {
+ entry[nrows] = new table_entry*[ncolumns];
+ for (int i = 0; i < ncolumns; i++)
+ entry[nrows][i] = 0;
+ vline[nrows] = new char[ncolumns+1];
+ for (i = 0; i < ncolumns+1; i++)
+ vline[nrows][i] = 0;
+ nrows++;
+ }
+ }
+}
+
+void table::do_hspan(int r, int c)
+{
+ assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns);
+ if (c == 0) {
+ error("first column cannot be horizontally spanned");
+ return;
+ }
+ table_entry *e = entry[r][c];
+ if (e) {
+ assert(e->start_row <= r && r <= e->end_row
+ && e->start_col <= c && c <= e->end_col
+ && e->end_row - e->start_row > 0
+ && e->end_col - e->start_col > 0);
+ return;
+ }
+ e = entry[r][c-1];
+ // e can be 0 if we had an empty entry or an error
+ if (e == 0)
+ return;
+ if (e->start_row != r) {
+ /*
+ l l
+ ^ s */
+ error("impossible horizontal span at row %1, column %2", r + 1, c + 1);
+ }
+ else {
+ e->end_col = c;
+ entry[r][c] = e;
+ }
+}
+
+void table::do_vspan(int r, int c)
+{
+ assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns);
+ if (r == 0) {
+ error("first row cannot be vertically spanned");
+ return;
+ }
+ table_entry *e = entry[r][c];
+ if (e) {
+ assert(e->start_row <= r && r <= e->end_row
+ && e->start_col <= c && c <= e->end_col
+ && e->end_row - e->start_row > 0
+ && e->end_col - e->start_col > 0);
+ return;
+ }
+ e = entry[r-1][c];
+ // e can be 0 if we had an empty entry or an error
+ if (e == 0)
+ return;
+ if (e->start_col != c) {
+ /* l s
+ l ^ */
+ error("impossible vertical span at row %1, column %2", r + 1, c + 1);
+ }
+ else {
+ for (int i = c; i <= e->end_col; i++) {
+ assert(entry[r][i] == 0);
+ entry[r][i] = e;
+ }
+ e->end_row = r;
+ }
+}
+
+int find_decimal_point(const char *s, char decimal_point_char,
+ const char *delim)
+{
+ if (s == 0 || *s == '\0')
+ return -1;
+ const char *p;
+ int in_delim = 0; // is p within eqn delimiters?
+ // tbl recognises \& even within eqn delimiters; I don't
+ for (p = s; *p; p++)
+ if (in_delim) {
+ if (*p == delim[1])
+ in_delim = 0;
+ }
+ else if (*p == delim[0])
+ in_delim = 1;
+ else if (p[0] == '\\' && p[1] == '&')
+ return p - s;
+ int possible_pos = -1;
+ in_delim = 0;
+ for (p = s; *p; p++)
+ if (in_delim) {
+ if (*p == delim[1])
+ in_delim = 0;
+ }
+ else if (*p == delim[0])
+ in_delim = 1;
+ else if (p[0] == decimal_point_char && csdigit(p[1]))
+ possible_pos = p - s;
+ if (possible_pos >= 0)
+ return possible_pos;
+ in_delim = 0;
+ for (p = s; *p; p++)
+ if (in_delim) {
+ if (*p == delim[1])
+ in_delim = 0;
+ }
+ else if (*p == delim[0])
+ in_delim = 1;
+ else if (csdigit(*p))
+ possible_pos = p + 1 - s;
+ return possible_pos;
+}
+
+void table::add_entry(int r, int c, const string &str, const entry_format *f,
+ const char *fn, int ln)
+{
+ allocate(r);
+ table_entry *e = 0;
+ if (str == "\\_") {
+ e = new short_line_entry(f);
+ }
+ else if (str == "\\=") {
+ e = new short_double_line_entry(f);
+ }
+ else if (str == "_") {
+ single_line_entry *lefte;
+ if (c > 0 && entry[r][c-1] != 0 &&
+ (lefte = entry[r][c-1]->to_single_line_entry()) != 0
+ && lefte->start_row == r
+ && lefte->mod->stagger == f->stagger) {
+ lefte->end_col = c;
+ entry[r][c] = lefte;
+ }
+ else
+ e = new single_line_entry(f);
+ }
+ else if (str == "=") {
+ double_line_entry *lefte;
+ if (c > 0 && entry[r][c-1] != 0 &&
+ (lefte = entry[r][c-1]->to_double_line_entry()) != 0
+ && lefte->start_row == r
+ && lefte->mod->stagger == f->stagger) {
+ lefte->end_col = c;
+ entry[r][c] = lefte;
+ }
+ else
+ e = new double_line_entry(f);
+ }
+ else if (str == "\\^") {
+ do_vspan(r, c);
+ }
+ else if (str.length() > 2 && str[0] == '\\' && str[1] == 'R') {
+ if (str.search('\n') >= 0)
+ error_with_file_and_line(fn, ln, "bad repeated character");
+ else {
+ char *s = str.substring(2, str.length() - 2).extract();
+ e = new repeated_char_entry(s, f);
+ }
+ }
+ else {
+ int is_block = str.search('\n') >= 0;
+ char *s;
+ switch (f->type) {
+ case FORMAT_SPAN:
+ assert(str.empty());
+ do_hspan(r, c);
+ break;
+ case FORMAT_LEFT:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new left_block_entry(s, f);
+ else
+ e = new left_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_CENTER:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new center_block_entry(s, f);
+ else
+ e = new center_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_RIGHT:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new right_block_entry(s, f);
+ else
+ e = new right_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_NUMERIC:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block) {
+ error_with_file_and_line(fn, ln, "can't have numeric text block");
+ e = new left_block_entry(s, f);
+ }
+ else {
+ int pos = find_decimal_point(s, decimal_point_char, delim);
+ if (pos < 0)
+ e = new center_text_entry(s, f);
+ else
+ e = new numeric_text_entry(s, f, pos);
+ }
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_ALPHABETIC:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new alphabetic_block_entry(s, f);
+ else
+ e = new alphabetic_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_VSPAN:
+ do_vspan(r, c);
+ break;
+ case FORMAT_HLINE:
+ if (str.length() != 0)
+ error_with_file_and_line(fn, ln,
+ "non-empty data entry for `_' format ignored");
+ e = new single_line_entry(f);
+ break;
+ case FORMAT_DOUBLE_HLINE:
+ if (str.length() != 0)
+ error_with_file_and_line(fn, ln,
+ "non-empty data entry for `=' format ignored");
+ e = new double_line_entry(f);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ if (e) {
+ table_entry *preve = entry[r][c];
+ if (preve) {
+ /* c s
+ ^ l */
+ error_with_file_and_line(fn, ln, "row %1, column %2 already spanned",
+ r + 1, c + 1);
+ delete e;
+ }
+ else {
+ e->input_lineno = ln;
+ e->input_filename = fn;
+ e->start_row = e->end_row = r;
+ e->start_col = e->end_col = c;
+ for (table_entry **p = &entry_list; *p; p = &(*p)->next)
+ ;
+ *p = e;
+ entry[r][c] = e;
+ }
+ }
+}
+
+// add vertical lines for row r
+
+void table::add_vlines(int r, const char *v)
+{
+ allocate(r);
+ for (int i = 0; i < ncolumns+1; i++)
+ vline[r][i] = v[i];
+}
+
+void table::check()
+{
+ table_entry *p = entry_list;
+ int i, j;
+ while (p) {
+ for (i = p->start_row; i <= p->end_row; i++)
+ for (j = p->start_col; j <= p->end_col; j++)
+ assert(entry[i][j] == p);
+ p = p->next;
+ }
+}
+
+void table::print()
+{
+ location_force_filename = 1;
+ check();
+ init_output();
+ determine_row_type();
+ compute_widths();
+ if (!(flags & CENTER))
+ prints(".if \\n[" SAVED_CENTER_REG "] \\{");
+ prints(".in +(u;\\n[.l]-\\n[.i]-\\n[TW]/2)\n"
+ ".nr " SAVED_INDENT_REG " \\n[.i]\n");
+ if (!(flags & CENTER))
+ prints(".\\}\n");
+ build_vrule_list();
+ define_bottom_macro();
+ do_top();
+ for (int i = 0; i < nrows; i++)
+ do_row(i);
+ do_bottom();
+}
+
+void table::determine_row_type()
+{
+ row_is_all_lines = new char[nrows];
+ for (int i = 0; i < nrows; i++) {
+ int had_single = 0;
+ int had_double = 0;
+ int had_non_line = 0;
+ for (int c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[i][c];
+ if (e != 0) {
+ if (e->start_row == e->end_row) {
+ int t = e->line_type();
+ switch (t) {
+ case -1:
+ had_non_line = 1;
+ break;
+ case 0:
+ // empty
+ break;
+ case 1:
+ had_single = 1;
+ break;
+ case 2:
+ had_double = 1;
+ break;
+ default:
+ assert(0);
+ }
+ if (had_non_line)
+ break;
+ }
+ c = e->end_col;
+ }
+ }
+ if (had_non_line)
+ row_is_all_lines[i] = 0;
+ else if (had_double)
+ row_is_all_lines[i] = 2;
+ else if (had_single)
+ row_is_all_lines[i] = 1;
+ else
+ row_is_all_lines[i] = 0;
+ }
+}
+
+
+void table::init_output()
+{
+ prints(".nr " COMPATIBLE_REG " \\n(.C\n"
+ ".cp 0\n");
+ if (linesize > 0)
+ printfs(".nr " LINESIZE_REG " %1\n", as_string(linesize));
+ else
+ prints(".nr " LINESIZE_REG " \\n[.s]\n");
+ if (!(flags & CENTER))
+ prints(".nr " SAVED_CENTER_REG " \\n[.ce]\n");
+ prints(".de " RESET_MACRO_NAME "\n"
+ ".ft \\n[.f]\n"
+ ".ps \\n[.s]\n"
+ ".vs \\n[.v]u\n"
+ ".in \\n[.i]u\n"
+ ".ll \\n[.l]u\n"
+ ".ls \\n[.L]\n"
+ ".ad \\n[.j]\n"
+ ".ie \\n[.u] .fi\n"
+ ".el .nf\n"
+ ".ce \\n[.ce]\n"
+ "..\n"
+ ".nr " SAVED_INDENT_REG " \\n[.i]\n"
+ ".nr " SAVED_FONT_REG " \\n[.f]\n"
+ ".nr " SAVED_SIZE_REG " \\n[.s]\n"
+ ".nr " SAVED_FILL_REG " \\n[.u]\n"
+ ".nr T. 0\n"
+ ".nr " CURRENT_ROW_REG " 0-1\n"
+ ".nr " LAST_PASSED_ROW_REG " 0-1\n"
+ ".nr " SECTION_DIVERSION_FLAG_REG " 0\n"
+ ".ds " TRANSPARENT_STRING_NAME "\n"
+ ".ds " QUOTE_STRING_NAME "\n"
+ ".nr " NEED_BOTTOM_RULE_REG " 1\n"
+ ".nr " SUPPRESS_BOTTOM_REG " 0\n"
+ ".eo\n"
+ ".de " REPEATED_MARK_MACRO "\n"
+ ".mk \\$1\n"
+ ".if !'\\n(.z'' \\!." REPEATED_MARK_MACRO " \"\\$1\"\n"
+ "..\n"
+ ".de " REPEATED_VPT_MACRO "\n"
+ ".vpt \\$1\n"
+ ".if !'\\n(.z'' \\!." REPEATED_VPT_MACRO " \"\\$1\"\n"
+ "..\n");
+ if (!(flags & NOKEEP))
+ prints(".de " KEEP_MACRO_NAME "\n"
+ ".if '\\n[.z]'' \\{.ds " QUOTE_STRING_NAME " \\\\\n"
+ ".ds " TRANSPARENT_STRING_NAME " \\!\n"
+ ".di " SECTION_DIVERSION_NAME "\n"
+ ".nr " SECTION_DIVERSION_FLAG_REG " 1\n"
+ ".in 0\n"
+ ".\\}\n"
+ "..\n"
+ ".de " RELEASE_MACRO_NAME "\n"
+ ".if \\n[" SECTION_DIVERSION_FLAG_REG "] \\{"
+ ".di\n"
+ ".in \\n[" SAVED_INDENT_REG "]u\n"
+ ".nr " SAVED_DN_REG " \\n[dn]\n"
+ ".ds " QUOTE_STRING_NAME "\n"
+ ".ds " TRANSPARENT_STRING_NAME "\n"
+ ".nr " SECTION_DIVERSION_FLAG_REG " 0\n"
+ ".if \\n[.t]<=\\n[dn] \\{"
+ ".nr T. 1\n"
+ ".T#\n"
+ ".nr " SUPPRESS_BOTTOM_REG " 1\n"
+ ".sp \\n[.t]u\n"
+ ".nr " SUPPRESS_BOTTOM_REG " 0\n"
+ ".mk #T\n"
+ ".\\}\n"
+ ".if \\n[.t]<=\\n[" SAVED_DN_REG "] "
+ /* Since we turn off traps, it won't get into an infinite loop
+ when we try and print it; it will just go off the bottom of the
+ page. */
+ ".tm warning: page \\n%: table text block will not fit on one page\n"
+ ".nf\n"
+ ".ls 1\n"
+ "." SECTION_DIVERSION_NAME "\n"
+ ".ls\n"
+ ".rm " SECTION_DIVERSION_NAME "\n"
+ ".\\}\n"
+ "..\n"
+ ".nr " TABLE_DIVERSION_FLAG_REG " 0\n"
+ ".de " TABLE_KEEP_MACRO_NAME "\n"
+ ".if '\\n[.z]'' \\{"
+ ".di " TABLE_DIVERSION_NAME "\n"
+ ".nr " TABLE_DIVERSION_FLAG_REG " 1\n"
+ ".\\}\n"
+ "..\n"
+ ".de " TABLE_RELEASE_MACRO_NAME "\n"
+ ".if \\n[" TABLE_DIVERSION_FLAG_REG "] \\{.br\n"
+ ".di\n"
+ ".nr " SAVED_DN_REG " \\n[dn]\n"
+ ".ne \\n[dn]u+\\n[.V]u\n"
+ ".ie \\n[.t]<=\\n[" SAVED_DN_REG "] "
+ ".tm error: page \\n%: table will not fit on one page; use .TS H/.TH with a supporting macro package\n"
+ ".el \\{"
+ ".in 0\n"
+ ".ls 1\n"
+ ".nf\n"
+ "." TABLE_DIVERSION_NAME "\n"
+ ".\\}\n"
+ ".rm " TABLE_DIVERSION_NAME "\n"
+ ".\\}\n"
+ "..\n");
+ prints(".ec\n"
+ ".ce 0\n"
+ ".nf\n");
+}
+
+string block_width_reg(int r, int c)
+{
+ static char name[sizeof(BLOCK_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, BLOCK_WIDTH_PREFIX "%d,%d", r, c);
+ return string(name);
+}
+
+string block_diversion_name(int r, int c)
+{
+ static char name[sizeof(BLOCK_DIVERSION_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, BLOCK_DIVERSION_PREFIX "%d,%d", r, c);
+ return string(name);
+}
+
+string block_height_reg(int r, int c)
+{
+ static char name[sizeof(BLOCK_HEIGHT_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, BLOCK_HEIGHT_PREFIX "%d,%d", r, c);
+ return string(name);
+}
+
+string span_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+string span_left_numeric_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_LEFT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_LEFT_NUMERIC_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+string span_right_numeric_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_RIGHT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_RIGHT_NUMERIC_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+string span_alphabetic_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_ALPHABETIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_ALPHABETIC_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+
+string column_separation_reg(int col)
+{
+ static char name[sizeof(COLUMN_SEPARATION_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_SEPARATION_PREFIX "%d", col);
+ return string(name);
+}
+
+string row_start_reg(int row)
+{
+ static char name[sizeof(ROW_START_PREFIX)+INT_DIGITS];
+ sprintf(name, ROW_START_PREFIX "%d", row);
+ return string(name);
+}
+
+string column_start_reg(int col)
+{
+ static char name[sizeof(COLUMN_START_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_START_PREFIX "%d", col);
+ return string(name);
+}
+
+string column_end_reg(int col)
+{
+ static char name[sizeof(COLUMN_END_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_END_PREFIX "%d", col);
+ return string(name);
+}
+
+string column_divide_reg(int col)
+{
+ static char name[sizeof(COLUMN_DIVIDE_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_DIVIDE_PREFIX "%d", col);
+ return string(name);
+}
+
+string row_top_reg(int row)
+{
+ static char name[sizeof(ROW_TOP_PREFIX)+INT_DIGITS];
+ sprintf(name, ROW_TOP_PREFIX "%d", row);
+ return string(name);
+}
+
+void init_span_reg(int start_col, int end_col)
+{
+ printfs(".nr %1 \\n(.H\n.nr %2 0\n.nr %3 0\n.nr %4 0\n",
+ span_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col),
+ span_left_numeric_width_reg(start_col, end_col),
+ span_right_numeric_width_reg(start_col, end_col));
+}
+
+void compute_span_width(int start_col, int end_col)
+{
+ printfs(".nr %1 \\n[%1]>?(\\n[%2]+\\n[%3])\n"
+ ".if \\n[%4] .nr %1 \\n[%1]>?(\\n[%4]+2n)\n",
+ span_width_reg(start_col, end_col),
+ span_left_numeric_width_reg(start_col, end_col),
+ span_right_numeric_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col));
+
+}
+
+// Increase the widths of columns so that the width of any spanning entry
+// is no greater than the sum of the widths of the columns that it spans.
+// Ensure that the widths of columns remain equal.
+
+void table::divide_span(int start_col, int end_col)
+{
+ assert(end_col > start_col);
+ printfs(".nr " NEEDED_REG " \\n[%1]-(\\n[%2]",
+ span_width_reg(start_col, end_col),
+ span_width_reg(start_col, start_col));
+ for (int i = start_col + 1; i <= end_col; i++) {
+ // The column separation may shrink with the expand option.
+ if (!(flags & EXPAND))
+ printfs("+%1n", as_string(column_separation[i - 1]));
+ printfs("+\\n[%1]", span_width_reg(i, i));
+ }
+ prints(")\n");
+ printfs(".nr " NEEDED_REG " \\n[" NEEDED_REG "]/%1\n",
+ as_string(end_col - start_col + 1));
+ prints(".if \\n[" NEEDED_REG "] \\{");
+ for (i = start_col; i <= end_col; i++)
+ printfs(".nr %1 +\\n[" NEEDED_REG "]\n",
+ span_width_reg(i, i));
+ int equal_flag = 0;
+ for (i = start_col; i <= end_col && !equal_flag; i++)
+ if (equal[i])
+ equal_flag = 1;
+ if (equal_flag) {
+ for (i = 0; i < ncolumns; i++)
+ if (i < start_col || i > end_col)
+ printfs(".nr %1 +\\n[" NEEDED_REG "]\n",
+ span_width_reg(i, i));
+ }
+ prints(".\\}\n");
+}
+
+
+void table::sum_columns(int start_col, int end_col)
+{
+ assert(end_col > start_col);
+ printfs(".nr %1 \\n[%2]",
+ span_width_reg(start_col, end_col),
+ span_width_reg(start_col, start_col));
+ for (int i = start_col + 1; i <= end_col; i++)
+ printfs("+(%1*\\n[" SEPARATION_FACTOR_REG "])+\\n[%2]",
+ as_string(column_separation[i - 1]),
+ span_width_reg(i, i));
+ prints('\n');
+}
+
+horizontal_span::horizontal_span(int sc, int ec, horizontal_span *p)
+: start_col(sc), end_col(ec), next(p)
+{
+}
+
+void table::build_span_list()
+{
+ span_list = 0;
+ table_entry *p = entry_list;
+ while (p) {
+ if (p->end_col != p->start_col) {
+ for (horizontal_span *q = span_list; q; q = q->next)
+ if (q->start_col == p->start_col
+ && q->end_col == p->end_col)
+ break;
+ if (!q)
+ span_list = new horizontal_span(p->start_col, p->end_col, span_list);
+ }
+ p = p->next;
+ }
+ // Now sort span_list primarily by order of end_row, and secondarily
+ // by reverse order of start_row. This ensures that if we divide
+ // spans using the order in span_list, we will get reasonable results.
+ horizontal_span *unsorted = span_list;
+ span_list = 0;
+ while (unsorted) {
+ for (horizontal_span **pp = &span_list; *pp; pp = &(*pp)->next)
+ if (unsorted->end_col < (*pp)->end_col
+ || (unsorted->end_col == (*pp)->end_col
+ && (unsorted->start_col > (*pp)->start_col)))
+ break;
+ horizontal_span *tem = unsorted->next;
+ unsorted->next = *pp;
+ *pp = unsorted;
+ unsorted = tem;
+ }
+}
+
+
+void table::compute_separation_factor()
+{
+ if (flags & (ALLBOX|BOX|DOUBLEBOX))
+ left_separation = right_separation = 1;
+ else {
+ for (int i = 0; i < nrows; i++) {
+ if (vline[i][0] > 0)
+ left_separation = 1;
+ if (vline[i][ncolumns] > 0)
+ right_separation = 1;
+ }
+ }
+ if (flags & EXPAND) {
+ int total_sep = left_separation + right_separation;
+ for (int i = 0; i < ncolumns - 1; i++)
+ total_sep += column_separation[i];
+ if (total_sep != 0) {
+ // Don't let the separation factor be negative.
+ prints(".nr " SEPARATION_FACTOR_REG " \\n[.l]-\\n[.i]");
+ for (i = 0; i < ncolumns; i++)
+ printfs("-\\n[%1]", span_width_reg(i, i));
+ printfs("/%1>?0\n", as_string(total_sep));
+ }
+ }
+}
+
+void table::compute_column_positions()
+{
+ printfs(".nr %1 0\n", column_divide_reg(0));
+ printfs(".nr %1 %2*\\n[" SEPARATION_FACTOR_REG "]\n",
+ column_start_reg(0),
+ as_string(left_separation));
+ for (int i = 1;; i++) {
+ printfs(".nr %1 \\n[%2]+\\n[%3]\n",
+ column_end_reg(i-1),
+ column_start_reg(i-1),
+ span_width_reg(i-1, i-1));
+ if (i >= ncolumns)
+ break;
+ printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n",
+ column_start_reg(i),
+ column_end_reg(i-1),
+ as_string(column_separation[i-1]));
+ printfs(".nr %1 \\n[%2]+\\n[%3]/2\n",
+ column_divide_reg(i),
+ column_end_reg(i-1),
+ column_start_reg(i));
+ }
+ printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n",
+ column_divide_reg(ncolumns),
+ column_end_reg(i-1),
+ as_string(right_separation));
+ printfs(".nr TW \\n[%1]\n",
+ column_divide_reg(ncolumns));
+ if (flags & DOUBLEBOX) {
+ printfs(".nr %1 +" DOUBLE_LINE_SEP "\n", column_divide_reg(0));
+ printfs(".nr %1 -" DOUBLE_LINE_SEP "\n", column_divide_reg(ncolumns));
+ }
+}
+
+void table::make_columns_equal()
+{
+ int first = -1; // index of first equal column
+ for (int i = 0; i < ncolumns; i++)
+ if (equal[i]) {
+ if (first < 0) {
+ printfs(".nr %1 \\n[%1]", span_width_reg(i, i));
+ first = i;
+ }
+ else
+ printfs(">?\\n[%1]", span_width_reg(i, i));
+ }
+ if (first >= 0) {
+ prints('\n');
+ for (i = first + 1; i < ncolumns; i++)
+ if (equal[i])
+ printfs(".nr %1 \\n[%2]\n",
+ span_width_reg(i, i),
+ span_width_reg(first, first));
+ }
+}
+
+void table::compute_widths()
+{
+ build_span_list();
+ int i;
+ horizontal_span *p;
+ prints(".nr " SEPARATION_FACTOR_REG " 1n\n");
+ for (i = 0; i < ncolumns; i++) {
+ init_span_reg(i, i);
+ if (!minimum_width[i].empty())
+ printfs(".nr %1 %2\n", span_width_reg(i, i), minimum_width[i]);
+ }
+ for (p = span_list; p; p = p->next)
+ init_span_reg(p->start_col, p->end_col);
+ table_entry *q;
+ for (q = entry_list; q; q = q->next)
+ if (!q->mod->zero_width)
+ q->do_width();
+ for (i = 0; i < ncolumns; i++)
+ compute_span_width(i, i);
+ for (p = span_list; p; p = p->next)
+ compute_span_width(p->start_col, p->end_col);
+ make_columns_equal();
+ // Note that divide_span keeps equal width columns equal.
+ for (p = span_list; p; p = p->next)
+ divide_span(p->start_col, p->end_col);
+ for (p = span_list; p; p = p->next)
+ sum_columns(p->start_col, p->end_col);
+ int had_spanning_block = 0;
+ int had_equal_block = 0;
+ for (q = entry_list; q; q = q->next)
+ if (q->divert(ncolumns, minimum_width,
+ (flags & EXPAND) ? column_separation : 0)) {
+ if (q->end_col > q->start_col)
+ had_spanning_block = 1;
+ for (i = q->start_col; i <= q->end_col && !had_equal_block; i++)
+ if (equal[i])
+ had_equal_block = 1;
+ }
+ if (had_equal_block)
+ make_columns_equal();
+ if (had_spanning_block)
+ for (p = span_list; p; p = p->next)
+ divide_span(p->start_col, p->end_col);
+ compute_separation_factor();
+ for (p = span_list; p; p = p->next)
+ sum_columns(p->start_col, p->end_col);
+ compute_column_positions();
+}
+
+void table::print_single_hline(int r)
+{
+ prints(".vs " LINE_SEP ">?\\n[.V]u\n"
+ ".ls 1\n"
+ "\\v'" BODY_DEPTH "'"
+ "\\s[\\n[" LINESIZE_REG "]]");
+ if (r > nrows - 1)
+ prints("\\D'l |\\n[TW]u 0'");
+ else {
+ int start_col = 0;
+ for (;;) {
+ while (start_col < ncolumns
+ && entry[r][start_col] != 0
+ && entry[r][start_col]->start_row != r)
+ start_col++;
+ for (int end_col = start_col;
+ end_col < ncolumns
+ && (entry[r][end_col] == 0
+ || entry[r][end_col]->start_row == r);
+ end_col++)
+ ;
+ if (end_col <= start_col)
+ break;
+ printfs("\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if ((r > 0 && vline[r-1][start_col] == 2)
+ || (r < nrows && vline[r][start_col] == 2))
+ prints("-" HALF_DOUBLE_LINE_SEP);
+ prints("'");
+ printfs("\\D'l |\\n[%1]u",
+ column_divide_reg(end_col));
+ if ((r > 0 && vline[r-1][end_col] == 2)
+ || (r < nrows && vline[r][end_col] == 2))
+ prints("+" HALF_DOUBLE_LINE_SEP);
+ prints(" 0'");
+ start_col = end_col;
+ }
+ }
+ prints("\\s0\n");
+ prints(".ls\n"
+ ".vs\n");
+}
+
+void table::print_double_hline(int r)
+{
+ prints(".vs " LINE_SEP "+" DOUBLE_LINE_SEP
+ ">?\\n[.V]u\n"
+ ".ls 1\n"
+ "\\v'" BODY_DEPTH "'"
+ "\\s[\\n[" LINESIZE_REG "]]");
+ if (r > nrows - 1)
+ prints("\\v'-" DOUBLE_LINE_SEP "'"
+ "\\D'l |\\n[TW]u 0'"
+ "\\v'" DOUBLE_LINE_SEP "'"
+ "\\h'|0'"
+ "\\D'l |\\n[TW]u 0'");
+ else {
+ int start_col = 0;
+ for (;;) {
+ while (start_col < ncolumns
+ && entry[r][start_col] != 0
+ && entry[r][start_col]->start_row != r)
+ start_col++;
+ for (int end_col = start_col;
+ end_col < ncolumns
+ && (entry[r][end_col] == 0
+ || entry[r][end_col]->start_row == r);
+ end_col++)
+ ;
+ if (end_col <= start_col)
+ break;
+ const char *left_adjust = 0;
+ if ((r > 0 && vline[r-1][start_col] == 2)
+ || (r < nrows && vline[r][start_col] == 2))
+ left_adjust = "-" HALF_DOUBLE_LINE_SEP;
+ const char *right_adjust = 0;
+ if ((r > 0 && vline[r-1][end_col] == 2)
+ || (r < nrows && vline[r][end_col] == 2))
+ right_adjust = "+" HALF_DOUBLE_LINE_SEP;
+ printfs("\\v'-" DOUBLE_LINE_SEP "'"
+ "\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (left_adjust)
+ prints(left_adjust);
+ prints("'");
+ printfs("\\D'l |\\n[%1]u",
+ column_divide_reg(end_col));
+ if (right_adjust)
+ prints(right_adjust);
+ prints(" 0'");
+ printfs("\\v'" DOUBLE_LINE_SEP "'"
+ "\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (left_adjust)
+ prints(left_adjust);
+ prints("'");
+ printfs("\\D'l |\\n[%1]u",
+ column_divide_reg(end_col));
+ if (right_adjust)
+ prints(right_adjust);
+ prints(" 0'");
+ start_col = end_col;
+ }
+ }
+ prints("\\s0\n"
+ ".ls\n"
+ ".vs\n");
+}
+
+void table::compute_vrule_top_adjust(int start_row, int col, string &result)
+{
+ if (row_is_all_lines[start_row] && start_row < nrows - 1) {
+ if (row_is_all_lines[start_row] == 2)
+ result = LINE_SEP ">?\\n[.V]u" "+" DOUBLE_LINE_SEP;
+ else
+ result = LINE_SEP ">?\\n[.V]u";
+ start_row++;
+ }
+ else {
+ result = "";
+ if (start_row == 0)
+ return;
+ for (stuff *p = stuff_list; p && p->row <= start_row; p = p->next)
+ if (p->row == start_row
+ && (p->is_single_line() || p->is_double_line()))
+ return;
+ }
+ int left = 0;
+ if (col > 0) {
+ table_entry *e = entry[start_row-1][col-1];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ left = 2;
+ else if (e->to_single_line_entry() != 0)
+ left = 1;
+ }
+ }
+ int right = 0;
+ if (col < ncolumns) {
+ table_entry *e = entry[start_row-1][col];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ right = 2;
+ else if (e->to_single_line_entry() != 0)
+ right = 1;
+ }
+ }
+ if (row_is_all_lines[start_row-1] == 0) {
+ if (left > 0 || right > 0) {
+ result += "-" BODY_DEPTH "-" BAR_HEIGHT;
+ if ((left == 2 && right != 2) || (right == 2 && left != 2))
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ else if (left == 2 && right == 2)
+ result += "+" HALF_DOUBLE_LINE_SEP;
+ }
+ }
+ else if (row_is_all_lines[start_row-1] == 2) {
+ if ((left == 2 && right != 2) || (right == 2 && left != 2))
+ result += "-" DOUBLE_LINE_SEP;
+ else if (left == 1 || right == 1)
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ }
+}
+
+void table::compute_vrule_bot_adjust(int end_row, int col, string &result)
+{
+ if (row_is_all_lines[end_row] && end_row > 0) {
+ end_row--;
+ result = "";
+ }
+ else {
+ for (stuff *p = stuff_list; p && p->row < end_row + 1; p = p->next)
+ ;
+ if (p && p->row == end_row + 1 && p->is_double_line()) {
+ result = "-" DOUBLE_LINE_SEP;
+ return;
+ }
+ if ((p != 0 && p->row == end_row + 1)
+ || end_row == nrows - 1) {
+ result = "";
+ return;
+ }
+ if (row_is_all_lines[end_row+1] == 1)
+ result = LINE_SEP;
+ else if (row_is_all_lines[end_row+1] == 2)
+ result = LINE_SEP "+" DOUBLE_LINE_SEP;
+ else
+ result = "";
+ }
+ int left = 0;
+ if (col > 0) {
+ table_entry *e = entry[end_row+1][col-1];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ left = 2;
+ else if (e->to_single_line_entry() != 0)
+ left = 1;
+ }
+ }
+ int right = 0;
+ if (col < ncolumns) {
+ table_entry *e = entry[end_row+1][col];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ right = 2;
+ else if (e->to_single_line_entry() != 0)
+ right = 1;
+ }
+ }
+ if (row_is_all_lines[end_row+1] == 0) {
+ if (left > 0 || right > 0) {
+ result = "1v-" BODY_DEPTH "-" BAR_HEIGHT;
+ if ((left == 2 && right != 2) || (right == 2 && left != 2))
+ result += "+" HALF_DOUBLE_LINE_SEP;
+ else if (left == 2 && right == 2)
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ }
+ }
+ else if (row_is_all_lines[end_row+1] == 2) {
+ if (left == 2 && right == 2)
+ result += "-" DOUBLE_LINE_SEP;
+ else if (left != 2 && right != 2 && (left == 1 || right == 1))
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ }
+}
+
+void table::add_vertical_rule(int start_row, int end_row, int col, int is_double)
+{
+ vrule_list = new vertical_rule(start_row, end_row, col, is_double,
+ vrule_list);
+ compute_vrule_top_adjust(start_row, col, vrule_list->top_adjust);
+ compute_vrule_bot_adjust(end_row, col, vrule_list->bot_adjust);
+}
+
+void table::build_vrule_list()
+{
+ int col;
+ if (flags & ALLBOX) {
+ for (col = 1; col < ncolumns; col++) {
+ int start_row = 0;
+ for (;;) {
+ while (start_row < nrows && vline_spanned(start_row, col))
+ start_row++;
+ if (start_row >= nrows)
+ break;
+ int end_row = start_row;
+ while (end_row < nrows && !vline_spanned(end_row, col))
+ end_row++;
+ end_row--;
+ add_vertical_rule(start_row, end_row, col, 0);
+ start_row = end_row + 1;
+ }
+ }
+ }
+ if (flags & (BOX|ALLBOX|DOUBLEBOX)) {
+ add_vertical_rule(0, nrows - 1, 0, 0);
+ add_vertical_rule(0, nrows - 1, ncolumns, 0);
+ }
+ for (int end_row = 0; end_row < nrows; end_row++)
+ for (col = 0; col < ncolumns+1; col++)
+ if (vline[end_row][col] > 0
+ && !vline_spanned(end_row, col)
+ && (end_row == nrows - 1
+ || vline[end_row+1][col] != vline[end_row][col]
+ || vline_spanned(end_row+1, col))) {
+ for (int start_row = end_row - 1;
+ start_row >= 0
+ && vline[start_row][col] == vline[end_row][col]
+ && !vline_spanned(start_row, col);
+ start_row--)
+ ;
+ start_row++;
+ add_vertical_rule(start_row, end_row, col, vline[end_row][col] > 1);
+ }
+ for (vertical_rule *p = vrule_list; p; p = p->next)
+ if (p->is_double)
+ for (int r = p->start_row; r <= p->end_row; r++) {
+ if (p->col > 0 && entry[r][p->col-1] != 0
+ && entry[r][p->col-1]->end_col == p->col-1) {
+ int is_corner = r == p->start_row || r == p->end_row;
+ entry[r][p->col-1]->note_double_vrule_on_right(is_corner);
+ }
+ if (p->col < ncolumns && entry[r][p->col] != 0
+ && entry[r][p->col]->start_col == p->col) {
+ int is_corner = r == p->start_row || r == p->end_row;
+ entry[r][p->col]->note_double_vrule_on_left(is_corner);
+ }
+ }
+}
+
+void table::define_bottom_macro()
+{
+ prints(".eo\n"
+ ".de T#\n"
+ ".if !\\n[" SUPPRESS_BOTTOM_REG "] \\{"
+ "." REPEATED_VPT_MACRO " 0\n"
+ ".mk " SAVED_VERTICAL_POS_REG "\n");
+ if (flags & (BOX|ALLBOX|DOUBLEBOX)) {
+ prints(".if \\n[T.]&\\n[" NEED_BOTTOM_RULE_REG "] \\{");
+ print_single_hline(0);
+ prints(".\\}\n");
+ }
+ prints(".ls 1\n");
+ for (vertical_rule *p = vrule_list; p; p = p->next)
+ p->contribute_to_bottom_macro(this);
+ if (flags & DOUBLEBOX)
+ prints(".if \\n[T.] \\{.vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n"
+ "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l \\n[TW]u 0'\\s0\n"
+ ".vs\n"
+ ".\\}\n"
+ ".if \\n[" LAST_PASSED_ROW_REG "]>=0 "
+ ".nr " TOP_REG " \\n[#T]-" DOUBLE_LINE_SEP "\n"
+ ".sp -1\n"
+ "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n"
+ ".sp -1\n"
+ "\\v'" BODY_DEPTH "'\\h'|\\n[TW]u'\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n");
+ prints(".ls\n");
+ prints(".nr " LAST_PASSED_ROW_REG " \\n[" CURRENT_ROW_REG "]\n"
+ ".sp |\\n[" SAVED_VERTICAL_POS_REG "]u\n"
+ "." REPEATED_VPT_MACRO " 1\n"
+ ".\\}\n"
+ "..\n"
+ ".ec\n");
+}
+
+
+// is the vertical line before column c in row r horizontally spanned?
+
+int table::vline_spanned(int r, int c)
+{
+ assert(r >= 0 && r < nrows && c >= 0 && c < ncolumns + 1);
+ return (c != 0 && c != ncolumns && entry[r][c] != 0
+ && entry[r][c]->start_col != c
+ // horizontally spanning lines don't count
+ && entry[r][c]->to_double_line_entry() == 0
+ && entry[r][c]->to_single_line_entry() == 0);
+}
+
+int table::row_begins_section(int r)
+{
+ assert(r >= 0 && r < nrows);
+ for (int i = 0; i < ncolumns; i++)
+ if (entry[r][i] && entry[r][i]->start_row != r)
+ return 0;
+ return 1;
+}
+
+int table::row_ends_section(int r)
+{
+ assert(r >= 0 && r < nrows);
+ for (int i = 0; i < ncolumns; i++)
+ if (entry[r][i] && entry[r][i]->end_row != r)
+ return 0;
+ return 1;
+}
+
+void table::do_row(int r)
+{
+ if (!(flags & NOKEEP) && row_begins_section(r))
+ prints("." KEEP_MACRO_NAME "\n");
+ int had_line = 0;
+ for (stuff *p = stuff_list; p && p->row < r; p = p->next)
+ ;
+ for (stuff *p1 = p; p1 && p1->row == r; p1 = p1->next)
+ if (!p1->printed && (p1->is_single_line() || p1->is_double_line())) {
+ had_line = 1;
+ break;
+ }
+ if (!had_line && !row_is_all_lines[r])
+ printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r));
+ had_line = 0;
+ for (; p && p->row == r; p = p->next)
+ if (!p->printed) {
+ p->print(this);
+ if (!had_line && (p->is_single_line() || p->is_double_line())) {
+ printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r));
+ had_line = 1;
+ }
+ }
+ // Change the row *after* printing the stuff list (which might contain .TH).
+ printfs("\\*[" TRANSPARENT_STRING_NAME "].nr " CURRENT_ROW_REG " %1\n",
+ as_string(r));
+ if (!had_line && row_is_all_lines[r])
+ printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r));
+ // we might have had a .TH, for example, since we last tried
+ if (!(flags & NOKEEP) && row_begins_section(r))
+ prints("." KEEP_MACRO_NAME "\n");
+ printfs(".mk %1\n", row_start_reg(r));
+ prints(".mk " BOTTOM_REG "\n"
+ "." REPEATED_VPT_MACRO " 0\n");
+ int c;
+ int row_is_blank = 1;
+ int first_start_row = r;
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r) {
+ e->do_depth();
+ if (e->start_row < first_start_row)
+ first_start_row = e->start_row;
+ row_is_blank = 0;
+ }
+ c = e->end_col;
+ }
+ }
+ if (row_is_blank)
+ prints(".nr " BOTTOM_REG " +1v\n");
+ if (row_is_all_lines[r]) {
+ prints(".vs " LINE_SEP);
+ if (row_is_all_lines[r] == 2)
+ prints("+" DOUBLE_LINE_SEP);
+ prints(">?\\n[.V]u\n.ls 1\n");
+ prints("\\&");
+ prints("\\v'" BODY_DEPTH);
+ if (row_is_all_lines[r] == 2)
+ prints("-" HALF_DOUBLE_LINE_SEP);
+ prints("'");
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == e->start_row)
+ e->to_simple_entry()->simple_print(1);
+ c = e->end_col;
+ }
+ }
+ prints("\n");
+ prints(".ls\n"
+ ".vs\n");
+ prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n");
+ printfs(".sp |\\n[%1]u\n", row_start_reg(r));
+ }
+ for (int i = row_is_all_lines[r] ? r - 1 : r;
+ i >= first_start_row;
+ i--) {
+ simple_entry *first = 0;
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r && e->start_row == i) {
+ simple_entry *simple = e->to_simple_entry();
+ if (simple) {
+ if (!first) {
+ prints(".ta");
+ first = simple;
+ }
+ simple->add_tab();
+ }
+ }
+ c = e->end_col;
+ }
+ }
+ if (first) {
+ prints('\n');
+ first->position_vertically();
+ first->set_location();
+ prints("\\&");
+ first->simple_print(0);
+ for (c = first->end_col + 1; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r && e->start_row == i) {
+ simple_entry *simple = e->to_simple_entry();
+ if (simple)
+ simple->simple_print(0);
+ }
+ c = e->end_col;
+ }
+ }
+ prints('\n');
+ prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n");
+ printfs(".sp |\\n[%1]u\n", row_start_reg(r));
+ }
+ }
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r && e->to_simple_entry() == 0) {
+ e->position_vertically();
+ e->print();
+ prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n");
+ printfs(".sp |\\n[%1]u\n", row_start_reg(r));
+ }
+ c = e->end_col;
+ }
+ }
+ prints("." REPEATED_VPT_MACRO " 1\n"
+ ".sp |\\n[" BOTTOM_REG "]u\n"
+ "\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 1\n");
+ if (r != nrows - 1 && (flags & ALLBOX)) {
+ print_single_hline(r + 1);
+ prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 0\n");
+ }
+ if (r != nrows - 1) {
+ if (p && p->row == r + 1
+ && (p->is_single_line() || p->is_double_line())) {
+ p->print(this);
+ prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG
+ " 0\n");
+ }
+ int printed_one = 0;
+ for (vertical_rule *p = vrule_list; p; p = p->next)
+ if (p->end_row == r) {
+ if (!printed_one) {
+ prints("." REPEATED_VPT_MACRO " 0\n");
+ printed_one = 1;
+ }
+ p->print();
+ }
+ if (printed_one)
+ prints("." REPEATED_VPT_MACRO " 1\n");
+ if (!(flags & NOKEEP) && row_ends_section(r))
+ prints("." RELEASE_MACRO_NAME "\n");
+ }
+}
+
+void table::do_top()
+{
+ prints(".fc \002\003\n");
+ if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX)))
+ prints("." TABLE_KEEP_MACRO_NAME "\n");
+ if (flags & DOUBLEBOX) {
+ prints(".ls 1\n"
+ ".vs " LINE_SEP ">?\\n[.V]u\n"
+ "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]\\D'l \\n[TW]u 0'\\s0\n"
+ ".vs\n"
+ "." REPEATED_MARK_MACRO " " TOP_REG "\n"
+ ".vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n");
+ printfs("\\v'" BODY_DEPTH "'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\h'\\n[%1]u'"
+ "\\D'l |\\n[%2]u 0'"
+ "\\s0"
+ "\n",
+ column_divide_reg(0),
+ column_divide_reg(ncolumns));
+ prints(".ls\n"
+ ".vs\n");
+ }
+ else if (flags & (ALLBOX|BOX)) {
+ print_single_hline(0);
+ }
+ //printfs(".mk %1\n", row_top_reg(0));
+}
+
+void table::do_bottom()
+{
+ // print stuff after last row
+ for (stuff *p = stuff_list; p; p = p->next)
+ if (p->row > nrows - 1)
+ p->print(this);
+ if (!(flags & NOKEEP))
+ prints("." RELEASE_MACRO_NAME "\n");
+ printfs(".mk %1\n", row_top_reg(nrows));
+ prints(".nr " NEED_BOTTOM_RULE_REG " 1\n"
+ ".nr T. 1\n"
+ ".T#\n");
+ if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX)))
+ prints("." TABLE_RELEASE_MACRO_NAME "\n");
+ if (flags & DOUBLEBOX)
+ prints(".sp " DOUBLE_LINE_SEP "\n");
+ prints("." RESET_MACRO_NAME "\n"
+ ".fc\n"
+ ".cp \\n(" COMPATIBLE_REG "\n");
+}
+
+int table::get_nrows()
+{
+ return nrows;
+}
+
+const char *last_filename = 0;
+
+void set_troff_location(const char *fn, int ln)
+{
+ if (!location_force_filename && last_filename != 0
+ && strcmp(fn, last_filename) == 0)
+ printfs(".lf %1\n", as_string(ln));
+ else {
+ printfs(".lf %1 %2\n", as_string(ln), fn);
+ last_filename = fn;
+ location_force_filename = 0;
+ }
+}
+
+void printfs(const char *s, const string &arg1, const string &arg2,
+ const string &arg3, const string &arg4, const string &arg5)
+{
+ if (s) {
+ char c;
+ while ((c = *s++) != '\0') {
+ if (c == '%') {
+ switch (*s++) {
+ case '1':
+ prints(arg1);
+ break;
+ case '2':
+ prints(arg2);
+ break;
+ case '3':
+ prints(arg3);
+ break;
+ case '4':
+ prints(arg4);
+ break;
+ case '5':
+ prints(arg5);
+ break;
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+ case '%':
+ prints('%');
+ break;
+ default:
+ assert(0);
+ }
+ }
+ else
+ prints(c);
+ }
+ }
+}
+
diff --git a/gnu/usr.bin/groff/tbl/table.h b/gnu/usr.bin/groff/tbl/table.h
new file mode 100644
index 000000000000..ae27545e2c97
--- /dev/null
+++ b/gnu/usr.bin/groff/tbl/table.h
@@ -0,0 +1,151 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "cset.h"
+#include "cmap.h"
+#include "stringclass.h"
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+
+struct inc_number {
+ short inc;
+ short val;
+};
+
+struct entry_modifier {
+ inc_number point_size;
+ inc_number vertical_spacing;
+ string font;
+ enum { CENTER, TOP, BOTTOM } vertical_alignment;
+ char zero_width;
+ char stagger;
+
+ entry_modifier();
+ ~entry_modifier();
+};
+
+enum format_type {
+ FORMAT_LEFT,
+ FORMAT_CENTER,
+ FORMAT_RIGHT,
+ FORMAT_NUMERIC,
+ FORMAT_ALPHABETIC,
+ FORMAT_SPAN,
+ FORMAT_VSPAN,
+ FORMAT_HLINE,
+ FORMAT_DOUBLE_HLINE
+};
+
+struct entry_format : entry_modifier {
+ format_type type;
+
+ entry_format(format_type);
+ entry_format();
+ void debug_print() const;
+};
+
+struct table_entry;
+struct horizontal_span;
+struct stuff;
+struct vertical_rule;
+
+class table {
+ unsigned flags;
+ int nrows;
+ int ncolumns;
+ int linesize;
+ char delim[2];
+ char decimal_point_char;
+ vertical_rule *vrule_list;
+ stuff *stuff_list;
+ horizontal_span *span_list;
+ table_entry *entry_list;
+ table_entry ***entry;
+ char **vline;
+ char *row_is_all_lines;
+ string *minimum_width;
+ int *column_separation;
+ char *equal;
+ int left_separation;
+ int right_separation;
+ int allocated_rows;
+ void build_span_list();
+ void do_hspan(int r, int c);
+ void do_vspan(int r, int c);
+ void allocate(int r);
+ void compute_widths();
+ void divide_span(int, int);
+ void sum_columns(int, int);
+ void compute_separation_factor();
+ void compute_column_positions();
+ void do_row(int);
+ void init_output();
+ void add_stuff(stuff *);
+ void do_top();
+ void do_bottom();
+ void do_vertical_rules();
+ void build_vrule_list();
+ void add_vertical_rule(int, int, int, int);
+ void define_bottom_macro();
+ int vline_spanned(int r, int c);
+ int row_begins_section(int);
+ int row_ends_section(int);
+ void make_columns_equal();
+ void compute_vrule_top_adjust(int, int, string &);
+ void compute_vrule_bot_adjust(int, int, string &);
+ void determine_row_type();
+public:
+ /* used by flags */
+ enum {
+ CENTER = 01,
+ EXPAND = 02,
+ BOX = 04,
+ ALLBOX = 010,
+ DOUBLEBOX = 020,
+ NOKEEP = 040
+ };
+ table(int nc, unsigned flags, int linesize, char decimal_point_char);
+ ~table();
+
+ void add_text_line(int r, const string &, const char *, int);
+ void add_single_hline(int r);
+ void add_double_hline(int r);
+ void add_entry(int r, int c, const string &, const entry_format *,
+ const char *, int lineno);
+ void add_vlines(int r, const char *);
+ void check();
+ void print();
+ void set_minimum_width(int c, const string &w);
+ void set_column_separation(int c, int n);
+ void set_equal_column(int c);
+ void set_delim(char c1, char c2);
+ void print_single_hline(int r);
+ void print_double_hline(int r);
+ int get_nrows();
+};
+
+void set_troff_location(const char *, int);
diff --git a/gnu/usr.bin/groff/tbl/tbl.1 b/gnu/usr.bin/groff/tbl/tbl.1
new file mode 100644
index 000000000000..de72a767abe6
--- /dev/null
+++ b/gnu/usr.bin/groff/tbl/tbl.1
@@ -0,0 +1,143 @@
+.\" -*- nroff -*-
+.TH TBL 1 "1 April 1993" "Groff Version 1.08"
+.SH NAME
+tbl \- format tables for troff
+.SH SYNOPSIS
+.B tbl
+[
+.B \-Cv
+]
+[
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+This manual page describes the GNU version of
+.BR tbl ,
+which is part of the groff document formatting system.
+.B tbl
+compiles descriptions of tables embedded within
+.B troff
+input files into commands that are understood by
+.BR troff .
+Normally, it should be invoked using the
+.B \-t
+option of
+.B groff.
+It is highly compatible with Unix
+.BR tbl .
+The output generated by GNU
+.B tbl
+cannot be processed with Unix
+.BR troff ;
+it must be processed with GNU
+.BR troff .
+If no files are given on the command line, the standard input
+will be read.
+A filename of
+.B \-
+will cause the standard input to be read.
+.SH OPTIONS
+.TP
+.B \-C
+Recognize
+.B .TS
+and
+.B .TE
+even when followed by a character other than space or newline.
+.TP
+.B \-v
+Print the version number.
+.SH USAGE
+Only the differences between GNU
+.B tbl
+and Unix
+.B tbl
+are described here.
+.LP
+Normally
+.B tbl
+attempts to prevent undesirable breaks in the table by using diversions.
+This can sometimes interact badly with macro packages' own use of diversions,
+when footnotes, for example, are used.
+The
+.B nokeep
+option tells
+.B tbl
+not to try and prevent breaks in this way.
+.LP
+The
+.B decimalpoint
+option specifies the character to be recognized as the decimal
+point character in place of the default period.
+It takes an argument in parentheses, which must be a single
+character, as for the
+.B tab
+option.
+.LP
+The
+.B f
+format modifier can be followed by an arbitrary length
+font name in parentheses.
+.LP
+There is a
+.B d
+format modifier which means that a vertically spanning entry
+should be aligned at the bottom of its range.
+.LP
+There is no limit on the number of columns in a table, nor any limit
+on the number of text blocks.
+All the lines of a table are considered in deciding column
+widths, not just the first 200.
+Table continuation
+.RB ( .T& )
+lines are not restricted to the first 200 lines.
+.LP
+Numeric and alphabetic items may appear in the same column.
+.LP
+Numeric and alphabetic items may span horizontally.
+.LP
+.B tbl
+uses register, string, macro and diversion names beginning with
+.BR 3 .
+When using
+.B tbl
+you should avoid using any names beginning with a
+.BR 3 .
+.SH BUGS
+You should use
+.BR .TS\ H / .TH
+in conjunction with a supporting macro package for
+.I all
+multi-page boxed tables.
+If there is no header that you wish to appear at the top of each page
+of the table, place the
+.B .TH
+line immediately after the format section.
+Do not enclose a multi-page table within keep/release macros,
+or divert it in any other way.
+.LP
+A text block within a table must be able to fit on one page.
+.LP
+The
+.B bp
+request cannot be used to force a page-break in a multi-page table.
+Instead, define
+.B BP
+as follows
+.IP
+.B .de BP
+.br
+.B .ie '\e\en(.z'' .bp \e\e$1
+.br
+.B .el \e!.BP \e\e$1
+.br
+.B ..
+.br
+.LP
+and use
+.B BP
+instead of
+.BR bp .
+.SH "SEE ALSO"
+.BR groff (1),
+.BR troff (1)
diff --git a/gnu/usr.bin/groff/tfmtodit/Makefile b/gnu/usr.bin/groff/tfmtodit/Makefile
new file mode 100644
index 000000000000..a84f646f0a1d
--- /dev/null
+++ b/gnu/usr.bin/groff/tfmtodit/Makefile
@@ -0,0 +1,12 @@
+# Makefile for tfmtodit
+
+PROG= tfmtodit
+SRCS= tfmtodit.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF) -lm
+DPADD+= $(LIBGROFF) $(LIBMATH)
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/tfmtodit/tfmtodit.1 b/gnu/usr.bin/groff/tfmtodit/tfmtodit.1
new file mode 100644
index 000000000000..248f595034dd
--- /dev/null
+++ b/gnu/usr.bin/groff/tfmtodit/tfmtodit.1
@@ -0,0 +1,150 @@
+.\" -*- nroff -*-
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH TFMTODIT 1 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+tfmtodit \- create font files for use with groff \-Tdvi
+.SH SYNOPSIS
+.B tfmtodit
+[
+.B \-sv
+]
+[
+.BI \-g gf_file
+]
+[
+.BI \-k skewchar
+]
+.I tfm_file
+.I map_file
+.I font
+.SH DESCRIPTION
+.B tfmtodit
+creates a font file for use with
+.B
+groff \-Tdvi\fR.
+.I tfm_file
+is the name of the \*(tx font metric file for the font.
+.I map_file
+is a file giving the groff names for characters in the font;
+this file should consist of a sequence of lines of the form:
+.IP
+.I
+n c1 c2 \fR.\|.\|.
+.LP
+where
+.I n
+is a decimal integer giving the position of the character in the font,
+and
+.IR c1 ,
+.IR c2 ,.\|.\|.
+are the groff names of the character.
+If a character has no groff names but exists in the tfm file,
+then it will be put in the groff font file as an unnamed character.
+.I font
+is the name of the groff font file.
+The groff font file is written to
+.IR font .
+.LP
+The
+.B \-s
+option should be given if the font is special
+(a font is
+.I special
+if
+.B troff
+should search it whenever
+a character is not found in the current font.)
+If the font is special,
+it should be listed in the
+.B fonts
+command in the DESC file;
+if it is not special, there is no need to list it, since
+.B troff
+can automatically mount it when it's first used.
+.LP
+To do a good job of math typesetting, groff requires
+font metric information not present in the tfm file.
+The reason for this is that \*(tx has separate math italic fonts
+whereas groff uses normal italic fonts for math.
+The additional information required by groff is given by the
+two arguments to the
+.B math_fit
+macro in the Metafont programs for the Computer Modern fonts.
+In a text font (a font for which
+.B math_fitting
+is false), Metafont normally ignores these two arguments.
+Metafont can be made to put this information in the gf file
+by loading the following definition after
+.B cmbase
+when creating
+.BR cm.base :
+.IP
+.nf
+.ft B
+def ignore_math_fit(expr left_adjustment,right_adjustment) =
+ special "adjustment";
+ numspecial left_adjustment*16/designsize;
+ numspecial right_adjustment*16/designsize;
+ enddef;
+.fi
+.ft R
+.LP
+The gf file created using this modified
+.B cm.base
+should be specified with the
+.B \-g
+option.
+The
+.B \-g
+option should not be given for a font for which
+.B math_fitting
+is true.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-s
+The font is special.
+The effect of this option is to add the
+.B special
+command to the font file.
+.TP
+.BI \-k n
+The skewchar of this font is at position
+.IR n .
+.I n
+should be an integer;
+it may be given in decimal,
+or with a leading
+.B 0
+in octal,
+or with a leading
+.B 0x
+in hexadecimal.
+The effect of this option is to ignore any kerns whose second component
+is the specified character.
+.TP
+.BI \-g gf_file
+.I gf_file
+is a gf file produced by Metafont containing special and numspecial
+commands giving additional font metric information.
+.SH FILES
+.Tp \w'\fB/usr/share/groff_font/devdvi/DESC'u+2n
+.B /usr/share/groff_font/devdvi/DESC
+Device desciption file.
+.TP
+.BI /usr/share/groff_font/devdvi/ F
+Font description file for font
+.IR F .
+.SH "SEE ALSO"
+.BR groff (1),
+.BR grodvi (1),
+.BR groff_font (5)
diff --git a/gnu/usr.bin/groff/tfmtodit/tfmtodit.cc b/gnu/usr.bin/groff/tfmtodit/tfmtodit.cc
new file mode 100644
index 000000000000..851735d163bf
--- /dev/null
+++ b/gnu/usr.bin/groff/tfmtodit/tfmtodit.cc
@@ -0,0 +1,850 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* I have tried to incorporate the changes needed for TeX 3.0 tfm files,
+but I haven't tested them. */
+
+/* Groff requires more font metric information than TeX. The reason
+for this is that TeX has separate Math Italic fonts, whereas groff
+uses normal italic fonts for math. The two additional pieces of
+information required by groff correspond to the two arguments to the
+math_fit() macro in the Metafont programs for the CM fonts. In the
+case of a font for which math_fitting is false, these two arguments
+are normally ignored by Metafont. We need to get hold of these two
+parameters and put them in the groff font file.
+
+We do this by loading this definition after cmbase when creating cm.base.
+
+def ignore_math_fit(expr left_adjustment,right_adjustment) =
+ special "adjustment";
+ numspecial left_adjustment*16/designsize;
+ numspecial right_adjustment*16/designsize;
+ enddef;
+
+This puts the two arguments to the math_fit macro into the gf file.
+(They will appear in the gf file immediately before the character to
+which they apply.) We then create a gf file using this cm.base. Then
+we run tfmtodit and specify this gf file with the -g option.
+
+This need only be done for a font for which math_fitting is false;
+When it's true, the left_correction and subscript_correction should
+both be zero. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "assert.h"
+#include "cset.h"
+
+/* Values in the tfm file should be multiplied by this. */
+
+#define MULTIPLIER 1
+
+struct char_info_word {
+ unsigned char width_index;
+ char height_index;
+ char depth_index;
+ char italic_index;
+ char tag;
+ unsigned char remainder;
+};
+
+struct lig_kern_command {
+ unsigned char skip_byte;
+ unsigned char next_char;
+ unsigned char op_byte;
+ unsigned char remainder;
+};
+
+class tfm {
+ int bc;
+ int ec;
+ int nw;
+ int nh;
+ int nd;
+ int ni;
+ int nl;
+ int nk;
+ int np;
+ int cs;
+ int ds;
+ char_info_word *char_info;
+ int *width;
+ int *height;
+ int *depth;
+ int *italic;
+ lig_kern_command *lig_kern;
+ int *kern;
+ int *param;
+public:
+ tfm();
+ ~tfm();
+ int load(const char *);
+ int contains(int);
+ int get_width(int);
+ int get_height(int);
+ int get_depth(int);
+ int get_italic(int);
+ int get_param(int, int *);
+ int get_checksum();
+ int get_design_size();
+ int get_lig(unsigned char, unsigned char, unsigned char *);
+ friend class kern_iterator;
+};
+
+class kern_iterator {
+ tfm *t;
+ int c;
+ int i;
+public:
+ kern_iterator(tfm *);
+ int next(unsigned char *c1, unsigned char *c2, int *k);
+};
+
+
+kern_iterator::kern_iterator(tfm *p)
+: t(p), i(-1), c(t->bc)
+{
+}
+
+int kern_iterator::next(unsigned char *c1, unsigned char *c2, int *k)
+{
+ for (; c <= t->ec; c++)
+ if (t->char_info[c - t->bc].tag == 1) {
+ if (i < 0) {
+ i = t->char_info[c - t->bc].remainder;
+ if (t->lig_kern[i].skip_byte > 128)
+ i = (256*t->lig_kern[i].op_byte
+ + t->lig_kern[i].remainder);
+ }
+ for (;;) {
+ int skip = t->lig_kern[i].skip_byte;
+ if (skip <= 128 && t->lig_kern[i].op_byte >= 128) {
+ *c1 = c;
+ *c2 = t->lig_kern[i].next_char;
+ *k = t->kern[256*(t->lig_kern[i].op_byte - 128)
+ + t->lig_kern[i].remainder];
+ if (skip == 128) {
+ c++;
+ i = -1;
+ }
+ else
+ i += skip + 1;
+ return 1;
+ }
+ if (skip >= 128)
+ break;
+ i += skip + 1;
+ }
+ i = -1;
+ }
+ return 0;
+}
+
+tfm::tfm()
+: char_info(0), width(0), height(0), depth(0), italic(0), lig_kern(0),
+ kern(0), param(0)
+{
+}
+
+int tfm::get_lig(unsigned char c1, unsigned char c2, unsigned char *cp)
+{
+ if (contains(c1) && char_info[c1 - bc].tag == 1) {
+ int i = char_info[c1 - bc].remainder;
+ if (lig_kern[i].skip_byte > 128)
+ i = 256*lig_kern[i].op_byte + lig_kern[i].remainder;
+ for (;;) {
+ int skip = lig_kern[i].skip_byte;
+ if (skip > 128)
+ break;
+ // We are only interested in normal ligatures, for which
+ // op_byte == 0.
+ if (lig_kern[i].op_byte == 0
+ && lig_kern[i].next_char == c2) {
+ *cp = lig_kern[i].remainder;
+ return 1;
+ }
+ if (skip == 128)
+ break;
+ i += skip + 1;
+ }
+ }
+ return 0;
+}
+
+int tfm::contains(int i)
+{
+ return i >= bc && i <= ec && char_info[i - bc].width_index != 0;
+}
+
+int tfm::get_width(int i)
+{
+ return width[char_info[i - bc].width_index];
+}
+
+int tfm::get_height(int i)
+{
+ return height[char_info[i - bc].height_index];
+}
+
+int tfm::get_depth(int i)
+{
+ return depth[char_info[i - bc].depth_index];
+}
+
+int tfm::get_italic(int i)
+{
+ return italic[char_info[i - bc].italic_index];
+}
+
+int tfm::get_param(int i, int *p)
+{
+ if (i <= 0 || i > np)
+ return 0;
+ else {
+ *p = param[i - 1];
+ return 1;
+ }
+}
+
+int tfm::get_checksum()
+{
+ return cs;
+}
+
+int tfm::get_design_size()
+{
+ return ds;
+}
+
+tfm::~tfm()
+{
+ a_delete char_info;
+ a_delete width;
+ a_delete height;
+ a_delete depth;
+ a_delete italic;
+ a_delete lig_kern;
+ a_delete kern;
+ a_delete param;
+}
+
+int read2(unsigned char *&s)
+{
+ int n;
+ n = *s++ << 8;
+ n |= *s++;
+ return n;
+}
+
+int read4(unsigned char *&s)
+{
+ int n;
+ n = *s++ << 24;
+ n |= *s++ << 16;
+ n |= *s++ << 8;
+ n |= *s++;
+ return n;
+}
+
+
+int tfm::load(const char *file)
+{
+ errno = 0;
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", file, strerror(errno));
+ return 0;
+ }
+ int c1 = getc(fp);
+ int c2 = getc(fp);
+ if (c1 == EOF || c2 == EOF) {
+ fclose(fp);
+ error("unexpected end of file on `%1'", file);
+ return 0;
+ }
+ int lf = (c1 << 8) + c2;
+ int toread = lf*4 - 2;
+ unsigned char *buf = new unsigned char[toread];
+ if (fread(buf, 1, toread, fp) != toread) {
+ if (feof(fp))
+ error("unexpected end of file on `%1'", file);
+ else
+ error("error on file `%1'", file);
+ a_delete buf;
+ fclose(fp);
+ return 0;
+ }
+ fclose(fp);
+ if (lf < 6) {
+ error("bad tfm file `%1': impossibly short", file);
+ a_delete buf;
+ return 0;
+ }
+ unsigned char *ptr = buf;
+ int lh = read2(ptr);
+ bc = read2(ptr);
+ ec = read2(ptr);
+ nw = read2(ptr);
+ nh = read2(ptr);
+ nd = read2(ptr);
+ ni = read2(ptr);
+ nl = read2(ptr);
+ nk = read2(ptr);
+ int ne = read2(ptr);
+ np = read2(ptr);
+ if (6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np != lf) {
+ error("bad tfm file `%1': lengths do not sum", file);
+ a_delete buf;
+ return 0;
+ }
+ if (lh < 2) {
+ error("bad tfm file `%1': header too short", file);
+ a_delete buf;
+ return 0;
+ }
+ char_info = new char_info_word[ec - bc + 1];
+ width = new int[nw];
+ height = new int[nh];
+ depth = new int[nd];
+ italic = new int[ni];
+ lig_kern = new lig_kern_command[nl];
+ kern = new int[nk];
+ param = new int[np];
+ int i;
+ cs = read4(ptr);
+ ds = read4(ptr);
+ ptr += (lh-2)*4;
+ for (i = 0; i < ec - bc + 1; i++) {
+ char_info[i].width_index = *ptr++;
+ unsigned char tem = *ptr++;
+ char_info[i].depth_index = tem & 0xf;
+ char_info[i].height_index = tem >> 4;
+ tem = *ptr++;
+ char_info[i].italic_index = tem >> 2;
+ char_info[i].tag = tem & 3;
+ char_info[i].remainder = *ptr++;
+ }
+ for (i = 0; i < nw; i++)
+ width[i] = read4(ptr);
+ for (i = 0; i < nh; i++)
+ height[i] = read4(ptr);
+ for (i = 0; i < nd; i++)
+ depth[i] = read4(ptr);
+ for (i = 0; i < ni; i++)
+ italic[i] = read4(ptr);
+ for (i = 0; i < nl; i++) {
+ lig_kern[i].skip_byte = *ptr++;
+ lig_kern[i].next_char = *ptr++;
+ lig_kern[i].op_byte = *ptr++;
+ lig_kern[i].remainder = *ptr++;
+ }
+ for (i = 0; i < nk; i++)
+ kern[i] = read4(ptr);
+ ptr += ne*4;
+ for (i = 0; i < np; i++)
+ param[i] = read4(ptr);
+ assert(ptr == buf + lf*4 - 2);
+ a_delete buf;
+ return 1;
+}
+
+class gf {
+ int left[256];
+ int right[256];
+ static int sread4(int *p, FILE *fp);
+ static int uread3(int *p, FILE *fp);
+ static int uread2(int *p, FILE *fp);
+ static int skip(int n, FILE *fp);
+public:
+ gf();
+ int load(const char *file);
+ int get_left_adjustment(int i) { return left[i]; }
+ int get_right_adjustment(int i) { return right[i]; }
+};
+
+gf::gf()
+{
+ for (int i = 0; i < 256; i++)
+ left[i] = right[i] = 0;
+}
+
+int gf::load(const char *file)
+{
+ enum {
+ paint_0 = 0,
+ paint1 = 64,
+ boc = 67,
+ boc1 = 68,
+ eoc = 69,
+ skip0 = 70,
+ skip1 = 71,
+ new_row_0 = 74,
+ xxx1 = 239,
+ yyy = 243,
+ no_op = 244,
+ pre = 247,
+ post = 248
+ };
+ int got_an_adjustment = 0;
+ int pending_adjustment = 0;
+ int left_adj, right_adj;
+ const int gf_id_byte = 131;
+ errno = 0;
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", file, strerror(errno));
+ return 0;
+ }
+ if (getc(fp) != pre || getc(fp) != gf_id_byte) {
+ error("bad gf file");
+ return 0;
+ }
+ int n = getc(fp);
+ if (n == EOF)
+ goto eof;
+ if (!skip(n, fp))
+ goto eof;
+ for (;;) {
+ int op = getc(fp);
+ if (op == EOF)
+ goto eof;
+ if (op == post)
+ break;
+ if ((op >= paint_0 && op <= paint_0 + 63)
+ || (op >= new_row_0 && op <= new_row_0 + 164))
+ continue;
+ switch (op) {
+ case no_op:
+ case eoc:
+ case skip0:
+ break;
+ case paint1:
+ case skip1:
+ if (!skip(1, fp))
+ goto eof;
+ break;
+ case paint1 + 1:
+ case skip1 + 1:
+ if (!skip(2, fp))
+ goto eof;
+ break;
+ case paint1 + 2:
+ case skip1 + 2:
+ if (!skip(3, fp))
+ goto eof;
+ break;
+ case boc:
+ {
+ int code;
+ if (!sread4(&code, fp))
+ goto eof;
+ if (pending_adjustment) {
+ pending_adjustment = 0;
+ left[code & 0377] = left_adj;
+ right[code & 0377] = right_adj;
+ }
+ if (!skip(20, fp))
+ goto eof;
+ break;
+ }
+ case boc1:
+ {
+ int code = getc(fp);
+ if (code == EOF)
+ goto eof;
+ if (pending_adjustment) {
+ pending_adjustment = 0;
+ left[code] = left_adj;
+ right[code] = right_adj;
+ }
+ if (!skip(4, fp))
+ goto eof;
+ break;
+ }
+ case xxx1:
+ {
+ int len = getc(fp);
+ if (len == EOF)
+ goto eof;
+ char buf[256];
+ if (fread(buf, 1, len, fp) != len)
+ goto eof;
+ if (len == 10 /* strlen("adjustment") */
+ && memcmp(buf, "adjustment", len) == 0) {
+ int c = getc(fp);
+ if (c != yyy) {
+ if (c != EOF)
+ ungetc(c, fp);
+ break;
+ }
+ if (!sread4(&left_adj, fp))
+ goto eof;
+ c = getc(fp);
+ if (c != yyy) {
+ if (c != EOF)
+ ungetc(c, fp);
+ break;
+ }
+ if (!sread4(&right_adj, fp))
+ goto eof;
+ got_an_adjustment = 1;
+ pending_adjustment = 1;
+ }
+ break;
+ }
+ case xxx1 + 1:
+ if (!uread2(&n, fp) || !skip(n, fp))
+ goto eof;
+ break;
+ case xxx1 + 2:
+ if (!uread3(&n, fp) || !skip(n, fp))
+ goto eof;
+ break;
+ case xxx1 + 3:
+ if (!sread4(&n, fp) || !skip(n, fp))
+ goto eof;
+ break;
+ case yyy:
+ if (!skip(4, fp))
+ goto eof;
+ break;
+ default:
+ fatal("unrecognized opcode `%1'", op);
+ break;
+ }
+ }
+ if (!got_an_adjustment)
+ warning("no adjustment specials found in gf file");
+ return 1;
+ eof:
+ error("unexpected end of file");
+ return 0;
+}
+
+int gf::sread4(int *p, FILE *fp)
+{
+ *p = getc(fp);
+ if (*p >= 128)
+ *p -= 256;
+ *p <<= 8;
+ *p |= getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ return !ferror(fp) && !feof(fp);
+}
+
+int gf::uread3(int *p, FILE *fp)
+{
+ *p = getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ return !ferror(fp) && !feof(fp);
+}
+
+int gf::uread2(int *p, FILE *fp)
+{
+ *p = getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ return !ferror(fp) && !feof(fp);
+}
+
+int gf::skip(int n, FILE *fp)
+{
+ while (--n >= 0)
+ if (getc(fp) == EOF)
+ return 0;
+ return 1;
+}
+
+
+struct char_list {
+ char *ch;
+ char_list *next;
+ char_list(const char *, char_list * = 0);
+};
+
+char_list::char_list(const char *s, char_list *p) : ch(strsave(s)), next(p)
+{
+}
+
+
+int read_map(const char *file, char_list **table)
+{
+ errno = 0;
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", file, strerror(errno));
+ return 0;
+ }
+ for (int i = 0; i < 256; i++)
+ table[i] = 0;
+ char buf[512];
+ int lineno = 0;
+ while (fgets(buf, int(sizeof(buf)), fp)) {
+ lineno++;
+ char *ptr = buf;
+ while (csspace(*ptr))
+ ptr++;
+ if (*ptr == '\0' || *ptr == '#')
+ continue;
+ ptr = strtok(ptr, " \n\t");
+ if (!ptr)
+ continue;
+ int n;
+ if (sscanf(ptr, "%d", &n) != 1) {
+ error("%1:%2: bad map file", file, lineno);
+ fclose(fp);
+ return 0;
+ }
+ if (n < 0 || n > 255) {
+ error("%1:%2: code out of range", file, lineno);
+ fclose(fp);
+ return 0;
+ }
+ ptr = strtok(0, " \n\t");
+ if (!ptr) {
+ error("%1:%2: missing names", file, lineno);
+ fclose(fp);
+ return 0;
+ }
+ for (; ptr; ptr = strtok(0, " \n\t"))
+ table[n] = new char_list(ptr, table[n]);
+ }
+ fclose(fp);
+ return 1;
+}
+
+
+/* Every character that can participate in a ligature appears in the
+lig_chars table. `ch' gives the full-name of the character, `name'
+gives the groff name of the character, `i' gives its index in
+the encoding, which is filled in later (-1 if it does not appear). */
+
+struct {
+ const char *ch;
+ int i;
+} lig_chars[] = {
+ "f", -1,
+ "i", -1,
+ "l", -1,
+ "ff", -1,
+ "fi", -1,
+ "fl", -1,
+ "Fi", -1,
+ "Fl", -1,
+};
+
+// Indices into lig_chars[].
+
+enum { CH_f, CH_i, CH_l, CH_ff, CH_fi, CH_fl, CH_ffi, CH_ffl };
+
+// Each possible ligature appears in this table.
+
+struct {
+ unsigned char c1, c2, res;
+ const char *ch;
+} lig_table[] = {
+ CH_f, CH_f, CH_ff, "ff",
+ CH_f, CH_i, CH_fi, "fi",
+ CH_f, CH_l, CH_fl, "fl",
+ CH_ff, CH_i, CH_ffi, "ffi",
+ CH_ff, CH_l, CH_ffl, "ffl",
+ };
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int special_flag = 0;
+ int skewchar = -1;
+ int opt;
+ const char *gf_file = 0;
+ while ((opt = getopt(argc, argv, "svg:k:")) != EOF)
+ switch (opt) {
+ case 'g':
+ gf_file = optarg;
+ break;
+ case 's':
+ special_flag = 1;
+ break;
+ case 'k':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 0);
+ if ((n == 0 && ptr == optarg)
+ || *ptr != '\0'
+ || n < 0
+ || n > UCHAR_MAX)
+ error("invalid skewchar");
+ else
+ skewchar = (int)n;
+ break;
+ }
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "tfmtodit version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ break;
+ case EOF:
+ assert(0);
+ }
+ if (argc - optind != 3)
+ usage();
+ gf g;
+ if (gf_file) {
+ if (!g.load(gf_file))
+ return 1;
+ }
+ const char *tfm_file = argv[optind];
+ const char *map_file = argv[optind + 1];
+ const char *font_file = argv[optind + 2];
+ tfm t;
+ if (!t.load(tfm_file))
+ return 1;
+ char_list *table[256];
+ if (!read_map(map_file, table))
+ return 1;
+ errno = 0;
+ if (!freopen(font_file, "w", stdout)) {
+ error("can't open `%1' for writing: %2", font_file, strerror(errno));
+ return 1;
+ }
+ printf("name %s\n", font_file);
+ if (special_flag)
+ fputs("special\n", stdout);
+ char *internal_name = strsave(argv[optind]);
+ int len = strlen(internal_name);
+ if (len > 4 && strcmp(internal_name + len - 4, ".tfm") == 0)
+ internal_name[len - 4] = '\0';
+ char *s = strrchr(internal_name, '/');
+ printf("internalname %s\n", s ? s + 1 : internal_name);
+ int n;
+ if (t.get_param(2, &n)) {
+ if (n > 0)
+ printf("spacewidth %d\n", n*MULTIPLIER);
+ }
+ if (t.get_param(1, &n) && n != 0)
+ printf("slant %f\n", atan2(n/double(1<<20), 1.0)*180.0/M_PI);
+ int xheight;
+ if (!t.get_param(5, &xheight))
+ xheight = 0;
+ int i;
+ // Print the list of ligatures.
+ // First find the indices of each character that can participate in
+ // a ligature.
+ for (i = 0; i < 256; i++)
+ for (int j = 0; j < sizeof(lig_chars)/sizeof(lig_chars[0]); j++)
+ for (char_list *p = table[i]; p; p = p->next)
+ if (strcmp(lig_chars[j].ch, p->ch) == 0)
+ lig_chars[j].i = i;
+ // For each possible ligature, if its participants all exist,
+ // and it appears as a ligature in the tfm file, include in
+ // the list of ligatures.
+ int started = 0;
+ for (i = 0; i < sizeof(lig_table)/sizeof(lig_table[0]); i++) {
+ int i1 = lig_chars[lig_table[i].c1].i;
+ int i2 = lig_chars[lig_table[i].c2].i;
+ int r = lig_chars[lig_table[i].res].i;
+ if (i1 >= 0 && i2 >= 0 && r >= 0) {
+ unsigned char c;
+ if (t.get_lig(i1, i2, &c) && c == r) {
+ if (!started) {
+ started = 1;
+ fputs("ligatures", stdout);
+ }
+ printf(" %s", lig_table[i].ch);
+ }
+ }
+ }
+ if (started)
+ fputs(" 0\n", stdout);
+ printf("checksum %d\n", t.get_checksum());
+ printf("designsize %d\n", t.get_design_size());
+ // Now print out the kerning information.
+ int had_kern = 0;
+ kern_iterator iter(&t);
+ unsigned char c1, c2;
+ int k;
+ while (iter.next(&c1, &c2, &k))
+ if (c2 != skewchar) {
+ k *= MULTIPLIER;
+ char_list *q = table[c2];
+ for (char_list *p1 = table[c1]; p1; p1 = p1->next)
+ for (char_list *p2 = q; p2; p2 = p2->next) {
+ if (!had_kern) {
+ printf("kernpairs\n");
+ had_kern = 1;
+ }
+ printf("%s %s %d\n", p1->ch, p2->ch, k);
+ }
+ }
+ printf("charset\n");
+ char_list unnamed("---");
+ for (i = 0; i < 256; i++)
+ if (t.contains(i)) {
+ char_list *p = table[i] ? table[i] : &unnamed;
+ int m[6];
+ m[0] = t.get_width(i);
+ m[1] = t.get_height(i);
+ m[2] = t.get_depth(i);
+ m[3] = t.get_italic(i);
+ m[4] = g.get_left_adjustment(i);
+ m[5] = g.get_right_adjustment(i);
+ printf("%s\t%d", p->ch, m[0]*MULTIPLIER);
+ for (int j = int(sizeof(m)/sizeof(m[0])) - 1; j > 0; j--)
+ if (m[j] != 0)
+ break;
+ for (int k = 1; k <= j; k++)
+ printf(",%d", m[k]*MULTIPLIER);
+ int type = 0;
+ if (m[2] > 0)
+ type = 1;
+ if (m[1] > xheight)
+ type += 2;
+ printf("\t%d\t%04o\n", type, i);
+ for (p = p->next; p; p = p->next)
+ printf("%s\t\"\n", p->ch);
+ }
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-sv] [-g gf_file] [-k skewchar] tfm_file map_file font\n",
+ program_name);
+ exit(1);
+}
diff --git a/gnu/usr.bin/groff/tmac/Makefile b/gnu/usr.bin/groff/tmac/Makefile
new file mode 100644
index 000000000000..3c54eea63226
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/Makefile
@@ -0,0 +1,26 @@
+# Makefile for groff macros
+
+TMACOWN?= bin
+TMACGRP?= bin
+TMACMODE?= 444
+TMACDIR?= /usr/share/tmac
+
+MAN7= groff_ms.7
+MLINKS= groff_ms.7 ms.7
+
+FILES= tmac.pic tmac.ps tmac.psnew tmac.psold tmac.pspic tmac.psatk\
+ tmac.dvi tmac.tty tmac.tty-char tmac.X tmac.Xps tmac.latin1\
+ man.local eqnrc troffrc
+
+afterinstall:
+ for f in ${FILES}; do \
+ install -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ ${.CURDIR}/$$f ${DESTDIR}${TMACDIR}; \
+ done
+ install -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ ${.CURDIR}/tmac.s ${DESTDIR}${TMACDIR}/tmac.groff_ms
+ install -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ ${.CURDIR}/tmac.an ${DESTDIR}${TMACDIR}/tmac.groff_an
+
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/tmac/TODO b/gnu/usr.bin/groff/tmac/TODO
new file mode 100644
index 000000000000..5213fc274c08
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/TODO
@@ -0,0 +1,38 @@
+Support multiple line-spacing.
+
+Improve the device independence of the character definitions.
+
+If we have footnotes in the abstract in RP format, then the footnote
+will appear on the cover sheet, which it should, but also on the first
+page, which it should not.
+
+Should we allow multi-page cover-sheets?
+
+Warn about automatically numbered footnotes in floating keeps.
+
+When we bring back the footnote overflow at the top of page, it would
+be more efficient to avoid diverting it again. (Need to keep track of
+footnote height.)
+
+Possibly have a place above which the footnote trap must not be
+placed.
+
+Improved indexing, not using tm, controlled by string variable (eg
+-dIDX=file.idx).
+
+When changing from multi-column to narrower columns, we could avoid
+doing a @super-eject. (This might not be a good idea.)
+
+Think about cutmarks. Possibly implement CM.
+
+Implement thesis Mode (TM, CT).
+
+Implement more V10 features.
+
+Should this
+
+.LP
+.rs
+.sp \n(.tu
+
+print two pages?
diff --git a/gnu/usr.bin/groff/tmac/eqnrc b/gnu/usr.bin/groff/tmac/eqnrc
new file mode 100644
index 000000000000..eab720cf34da
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/eqnrc
@@ -0,0 +1,60 @@
+.\" Startup file for eqn.
+.EQ
+sdefine << %{ < back 20 < }%
+sdefine >> %{ > back 20 > }%
+
+sdefine dot %accent "\fR\(a.\fP"%
+sdefine dotdot %accent "\fR\(ad\fP"%
+sdefine vec %accent {up 52 "\s[\En[.s]/2u]\(->\s0"}%
+sdefine dyad %accent {up 52 "\s[\En[.s]/2u]\(<>\s0"}%
+
+sdefine cdot %type "binary" \(md%
+
+ifdef X75 ! define X %1% !
+ifdef X100 ! define X %1% !
+ifdef X75-12 ! define X %1% !
+ifdef X100-12 ! define X %1% !
+
+ifdef ps ! define ps|X %1% !
+ifdef X ! define ps|X %1% !
+
+ifdef ps|X ! sdefine inf %"\s[\En[.s]*13u/10u]\v'12M'\(if\v'-12M'\s0"% !
+
+ifdef dvi !
+sdefine int %{type "operator" vcenter \(is}%
+sdefine sum %{type "operator" vcenter \[sum]}%
+sdefine prod %{type "operator" vcenter \[product]}%
+sdefine coprod %{type "operator" vcenter \[coproduct]}%
+set num1 68
+set num2 39
+set denom1 69
+set denom2 34
+set sup1 41
+set sup2 36
+set sup3 29
+set sup_drop 39
+set sub_drop 5
+set axis_height 25
+set x_height 43
+set default_rule_thickness 4
+set big_op_spacing1 11
+set big_op_spacing2 16
+set big_op_spacing3 20
+set big_op_spacing4 60
+set big_op_spacing5 10
+!
+
+ifdef X ! set axis_height 32 !
+
+ifdef ps|X ! set draw_lines 1 !
+
+ifdef ascii ! define n %1% !
+ifdef latin1 ! define n %1% !
+ifdef n !
+set nroff 1
+!
+
+undef X
+undef ps|X
+undef n
+.EN
diff --git a/gnu/usr.bin/groff/tmac/groff_ms.7 b/gnu/usr.bin/groff/tmac/groff_ms.7
new file mode 100644
index 000000000000..a2aacb80e48c
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/groff_ms.7
@@ -0,0 +1,210 @@
+.\" -*- nroff -*-
+.TH GROFF_MS 7 "6 August 1992" "Groff Version 1.08"
+.SH NAME
+groff_ms \- groff ms macros
+.SH SYNOPSIS
+.B groff
+.B \-ms
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.SH DESCRIPTION
+This manual page describes the GNU version of the ms macros,
+which is part of the groff document formatting system.
+The groff ms macros are intended to be compatible with the 4.3
+.SM BSD
+Unix ms macros subject to the following limitations:
+.IP \(bu
+the internals of groff ms are not similar to the internals of Unix ms
+and so documents that depend upon implementation details of Unix ms
+may well not work with groff ms;
+.IP \(bu
+there is no support for typewriter-like devices;
+.IP \(bu
+Berkeley localisms, in particular the
+.B TM
+and
+.B CT
+macros, are not implemented;
+.IP \(bu
+groff ms
+does not provide cut marks;
+.IP \(bu
+multiple line spacing is not allowed
+(use a larger vertical spacing instead);
+.IP \(bu
+groff ms does not work in compatibility mode (eg with the
+.B \-C
+option);
+.IP \(bu
+the error-handling policy of groff ms
+is to detect and report errors,
+rather than silently to ignore them.
+.LP
+The groff ms macros make use of many features of GNU troff
+and therefore cannot be used with any other troff.
+.LP
+Bell Labs localisms are not implemented in either the
+.SM BSD
+ms macros or in the groff ms macros.
+.LP
+Some Unix ms documentation says that the
+.B CW
+and
+.B GW
+number registers can be used to control the column width and
+gutter width respectively.
+This is not the case.
+These number registers are not used in groff ms.
+.LP
+Macros that cause a reset set the indent.
+Macros that change the indent do not increment or decrement
+the indent, but rather set it absolutely.
+This can cause problems for documents that define
+additional macros of their own.
+The solution is to use not the
+.B in
+request but instead the
+.B RS
+and
+.B RE
+macros.
+.LP
+The number register
+.B GS
+is set to 1 by the groff ms macros,
+but is not used by the Unix ms macros.
+It is intended that documents that need to determine whether
+they are being formatted with Unix ms or groff ms make use of this
+number register.
+.LP
+Footnotes are implemented so that they can safely be used within
+keeps and displays.
+Automatically numbered footnotes within floating keeps are
+not recommended.
+It is safe to have another
+.B \e**
+between a
+.B \e**
+and the corresponding
+.BR .FS ;
+it is required only that each
+.B .FS
+occur after the corresponding
+.B \e**
+and that the occurrences of
+.B .FS
+are in the same order as the corresponding occurrences of
+.BR \e** .
+.LP
+The strings
+.B \e*{
+and
+.B \e*}
+can be used to begin and end a superscript.
+.LP
+Some Unix V10 ms features are implemented.
+The
+.BR B ,
+.BR I
+and
+.B BI
+macros can have an optional third argument which will be printed
+in the current font before the first argument.
+There is a macro
+.B CW
+like
+.B B
+that changes to a constant-width font.
+.LP
+The following strings can be redefined to adapt the groff ms macros
+to languages other than English:
+.LP
+.nf
+.ta \w'REFERENCES'u+2n
+String Default Value
+.sp .3v
+REFERENCES References
+ABSTRACT ABSTRACT
+TOC Table of Contents
+MONTH1 January
+MONTH2 February
+MONTH3 March
+MONTH4 April
+MONTH5 May
+MONTH6 June
+MONTH7 July
+MONTH8 August
+MONTH9 September
+MONTH10 October
+MONTH11 November
+MONTH12 December
+.fi
+.LP
+The font family is reset from the string
+.BR FAM ;
+at initialization if this string is undefined it is set to the current
+font family.
+The point size, vertical spacing, and inter-paragraph spacing for footnotes
+are taken from the number registers
+.BR FPS ,
+.BR FVS ,
+and
+.BR FPD ;
+at initialization these are set to
+.BR \en(PS-2 ,
+.BR \en[FPS]+2 ,
+and
+.B \en(PD/2
+respectively; however, if any of these registers has been defined
+before initialization, it will not be set.
+.LP
+Right-aligned displays are available with
+.B ".DS R"
+and
+.BR .RD .
+.LP
+The following conventions are used for names of macros, strings and
+number registers.
+External names available to documents that use the groff ms
+macros contain only uppercase letters and digits.
+Internally the macros are divided into modules.
+Names used only within one module are of the form
+.IB module * name\fR.
+Names used outside the module in which they are defined are of the form
+.IB module @ name\fR.
+Names associated with a particular environment are of the form
+.IB environment : name;
+these are used only within the
+.B par
+module,
+and
+.I name
+does not have a module prefix.
+Constructed names used to implement arrays are of the form
+.IB array ! index\fR.
+Thus the groff ms macros reserve the following names:
+.IP \(bu
+names containing
+.BR * ;
+.IP \(bu
+names containing
+.BR @ ;
+.IP \(bu
+names containing
+.BR : ;
+.IP \(bu
+names containing only uppercase letters and digits.
+.SH FILES
+.B /usr/share/tmac/tmac.s
+.SH "SEE ALSO"
+.BR groff (1),
+.BR troff (1),
+.BR tbl (1),
+.BR pic (1),
+.BR eqn (1)
+.br
+.BR ms (7)
diff --git a/gnu/usr.bin/groff/tmac/man.local b/gnu/usr.bin/groff/tmac/man.local
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/man.local
diff --git a/gnu/usr.bin/groff/tmac/tmac.X b/gnu/usr.bin/groff/tmac/tmac.X
new file mode 100644
index 000000000000..044113fe92e9
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.X
@@ -0,0 +1,45 @@
+.nr _C \n(.C
+.cp 0
+.ftr CW CR
+.ftr C CR
+.ftr CO CI
+.ftr CX CBI
+.ftr H HR
+.ftr HO HI
+.ftr HX HBI
+.ftr NX NBI
+.char \(ru \D'l .5m 0'
+.char \(ul \v'.25m'\D'l .5m 0'\v'-.25m'
+.char \(br \v'.25m'\D'l 0 -1m'\v'.75m'
+.char ~ \v'-.55m'\\s[\\n(.s/2u]\v'.2m'\(ti\v'-.2m'\s0\v'.55m'
+.char ^ \v'-.55m'\\s[\\n(.s/2u]\v'.3m'\(ha\v'-.3m'\s0\v'.55m'
+.if !c\(va .char \(va \o'\(ua\(da'
+.if !c\(em .char \(em --
+.if !c\(en .char \(en \-
+.if !c\(fi .char \(fi fi
+.if !c\(fl .char \(fl fl
+.if !c\(ff .char \(ff ff
+.if !c\(Fi .char \(Fi ffi
+.if !c\(Fl .char \(Fl ffl
+.if !c\(ci .char \(ci \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m'
+.if !c\(sq .char \(sq \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m'
+.if !c\(ga .char \(ga \Z'\v'-.7m'\D'l .22m .18m''\h'.33m'
+.if !c\(dg .char \(dg \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0''\h'.5m'
+.if !c\(dd .char \(dd \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m'
+.if !c\(lq .char \(lq ``
+.if !c\(rq .char \(rq ''
+.if !c\(Bq .char \(bq ,,
+.if !c\(OE .char \(OE O\h'-.25m'E
+.if !c\(oe .char \(oe o\h'-.14m'e
+.if !c\(ah .char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
+.if !c\(ao .char \(ao \v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'
+.if !c\(ho .char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.if !c\(lh .tr \(lh\(lA
+.if !c\(rh .tr \(rh\(rA
+.if !c\(bq .tr \(bq,
+.if !c\(aq .tr \(aq'
+.if '\*(.T'X100' .char \(rn \h'-\w'\(sr'u'\(rn\h'\w'\(sr'u'
+.if !\n(_C .mso tmac.pspic
+.cp \n(_C
diff --git a/gnu/usr.bin/groff/tmac/tmac.Xps b/gnu/usr.bin/groff/tmac/tmac.Xps
new file mode 100644
index 000000000000..92471abbc13d
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.Xps
@@ -0,0 +1,44 @@
+.do mso tmac.ps
+.nr _C \n(.C
+.cp 0
+.de Xps-char
+.char \\$1 \Z"\X'ps: invis'\\$2\X'ps: endinvis'"\\$1
+..
+.Xps-char \(bu \fS\(bu\fP
+.Xps-char \(em "\v'-.25m'\h'.05m'\D'l .9m 0'\h'.05m'"
+.Xps-char \(aq '
+.Xps-char \(bq ,
+.Xps-char \(Bq ,,
+.Xps-char \(lq ``
+.Xps-char \(rq ''
+.Xps-char \(OE OE
+.Xps-char \(oe oe
+.Xps-char \(Fn \fS\(Fn\fP
+.Xps-char \(vS \o'\(ahS'
+.Xps-char \(vs \o'\(ahs'
+.Xps-char \(vZ \o'\(ahZ'
+.Xps-char \(vz \o'\(ahz'
+.Xps-char \(/L \o'/L'
+.Xps-char \(/l \o'/l'
+.Xps-char \(:Y \o'\(adY'
+.Xps-char \(a" \(sd
+.Xps-char \(a. \v'-.6m'.
+.Xps-char \(ga "\Z'\v'-.7m'\D'l .22m .18m''\h'.33m'"
+.Xps-char \(ab \v'-.55m'\s'\\\\n(.s*6u/10u'u\s0
+.Xps-char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
+.Xps-char \(ao "\v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'"
+.Xps-char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.Xps-char \(.i i
+.Xps-char \(fo <
+.Xps-char \(fc >
+.Xps-char \(OK \s'\\\\n(.s*6u/10u'\e\s0/
+.Xps-char \(tm \v'-.3m'\s'\\\\n(.s*6u/10u'TM\s0\v'.3m'
+.Xps-char \(dd "\Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m'"
+.Xps-char \(dg "\Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0''\h'.5m'"
+.Xps-char \(en \-
+.Xps-char \(%0 %\s'\\\\n(.s*6u/10u'\fI0\fP\s0
+.Xps-char \(lh \(->
+.Xps-char \(rh \(<-
+.cp \n(_C
diff --git a/gnu/usr.bin/groff/tmac/tmac.an b/gnu/usr.bin/groff/tmac/tmac.an
new file mode 100644
index 000000000000..017a6a8c0916
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.an
@@ -0,0 +1,326 @@
+.\"Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+.\" Written by James Clark (jjc@jclark.com)
+.\"
+.\"This file is part of groff.
+.\"
+.\"groff is free software; you can redistribute 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.
+.\"
+.\"groff is distributed in the hope that it will be useful, but WITHOUT ANY
+.\"WARRANTY; without even the implied warranty of MERCHANTABILITY or
+.\"FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+.\"for more details.
+.\"
+.\"You should have received a copy of the GNU General Public License along
+.\"with groff; see the file COPYING. If not, write to the Free Software
+.\"Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+.\"
+.\" -rC1 => number pages continuously, rather than start each at 1
+.\" -rD1 => double-sided printing, ie different odd and even page footers
+.\" -rPnnn => number first page nnn
+.\" -rXnnn => number pages after nnn as nnna, nnnb, nnnc, ...
+.\"
+.\" The file man.local is loaded at the end. Put local additions there.
+.\" If you need to add things to TH, use `.am TH'.
+.\"
+.if !\n(.g .ab These man macros work only with groff.
+.nr _C \n(.C
+.cp 0
+.if !rD .nr D 0
+.if !rC .nr C 0
+.if rP .pn 0\nP
+.\" .TH title section extra1 extra2 extra3
+.de TH
+.cp 0
+.de an-init \" We have to do it like this to get multiple man pages right.
+.ds an-title "\\$1
+.ds an-section "\\$2
+.ds an-extra1 "\\$3
+.ie \\n[.$]>3 .ds an-extra2 "\\$4
+.el .ds an-extra2 \"Sun Release 4.0
+.ie \\n[.$]>4 .ds an-extra3 "\\$5
+.el .ds an-extra3 \"UNIX Programmer's Manual
+.ds an-init
+\\..
+.DT
+.nr IN 7.2n
+.nr LL 6.5i
+.PD
+.nr PS 10 \" normal point-size
+.nr SN 3n \" the indentation of sub-sub-headings relative to sub-headings
+.nr an-level 1
+.nr an-margin \\n[IN]
+.nr an-prevailing-indent \\n[IN]
+.nr an-tag-sep 1n
+.nr an-no-space-flag 0
+.nr an-break-flag 0
+.nr an-div? 0
+.wh 0 an-header
+.wh -1i an-footer
+.wh -.5i an-p-footer
+.if \\n[nl]>0 \{\
+. ie \\nC .bp \\n%+1
+. el .bp 1
+.\}
+..
+.de DT
+.ta T .5i \" This sets tabs every .5 inches
+..
+.de PD
+.ie \\n[.$] .nr PD (v;\\$1)
+.el .nr PD .4v>?\n[.V]
+..
+.de an-header
+.an-init
+.ev 1
+.sp .5i
+.tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])'
+.sp |1i
+.ev
+.ns
+..
+.de an-footer
+'bp
+..
+.af an-page-letter a
+.de an-p-footer
+.ev 1
+.ds an-page-string \\n%
+.if rX \{\
+. if \\n%>\\nX \{\
+. nr an-page-letter \\n%-\\nX
+. ds an-page-string \\nX\\n[an-page-letter]
+.\}\}
+.ie \\nD \{\
+. if o .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]'
+. if e .tl '\\*[an-page-string]'\\*[an-extra1]'\\*[an-extra2]'
+.\}
+.el .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]'
+.ev
+..
+.de SH
+.sp \\n[PD]u
+.nr an-level 1
+.nr an-margin \\n[IN]
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[IN]u
+.ti 0
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.ps \\n[PS]-1
+.ft B
+.ne 2v+1u
+.if \\n[.$] \&\\$*
+..
+.de SS
+.sp \\n[PD]u
+.nr an-level 1
+.nr an-margin \\n[IN]
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[IN]u
+.ti \\n[SN]u
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.ps \\n[PS]
+.ft B
+.ne 2v+1u
+.if \\n[.$] \&\\$*
+..
+.de B
+.it 1 an-trap
+.ft B
+.if \\n[.$] \&\\$*
+..
+.de I
+.it 1 an-trap
+.ft I
+.if \\n[.$] \&\\$*
+..
+.de SM
+.it 1 an-trap
+.ps -1
+.if \\n[.$] \&\\$*
+..
+.de SB
+.it 1 an-trap
+.ps -1
+.ft B
+.if \\n[.$] \&\\$*
+..
+.de TP
+.sp \\n[PD]u
+.if \\n[.$] .nr an-prevailing-indent (n;\\$1)
+.it 1 an-trap
+.if !\\n[an-div?] .di an-div
+.in 0
+.nr an-div? 1
+..
+.de an-trap
+.ft R
+.ps \\n[PS]
+.if \\n[an-break-flag] \{\
+. br
+. nr an-break-flag 0
+.\}
+.if \\n[an-no-space-flag] \{\
+. ns
+. nr an-no-space-flag 0
+.\}
+.if \\n[an-div?] .an-do-tag
+..
+.de an-do-tag
+.nr an-div? 0
+.br
+.di
+.in \\n[an-margin]u+\\n[an-prevailing-indent]u
+.ti -\\n[an-prevailing-indent]u
+.ie \\n[dl]+\\n[an-tag-sep]>\\n[an-prevailing-indent] \{\
+. ne 2v+1u
+. an-div
+. br
+.\}
+.el \{\
+. chop an-div
+. ne 1v+1u
+\\*[an-div]\\h'|\\n[an-prevailing-indent]u'\c
+.\}
+..
+.de LP
+.br
+.sp \\n[PD]u
+.ps \\n[PS]
+.ft R
+.in \\n[an-margin]u
+.nr an-prevailing-indent \\n[IN]
+..
+.als PP LP
+.als P LP
+.de IP
+.ie !\\n[.$] \{\
+. ps \\n[PS]
+. ft R
+. sp \\n[PD]u
+. ne 1v+1u
+. in \\n[an-margin]u+\\n[an-prevailing-indent]u
+.\}
+.el \{\
+. ie \\n[.$]-1 .TP "\\$2"
+. el .TP
+\&\\$1
+.\}
+..
+.de HP
+.ps \\n[PS]
+.ft R
+.sp \\n[PD]u
+.ne 1v+1u
+.if \\n[.$] .nr an-prevailing-indent (n;\\$1)
+.in \\n[an-margin]u+\\n[an-prevailing-indent]u
+.ti \\n[an-margin]u
+..
+.de RI
+.if \\n[.$] \{\
+. ds an-result \&\\$1
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \,\fI\\$1\fR\/\\$2
+. shift 2
+. \}
+. if \\n[.$] .as an-result \,\fI\\$1\fR
+\\*[an-result]
+.\}
+..
+.de IR
+.if \\n[.$] \{\
+. ds an-result \&\fI\\$1\fR
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \/\\$1\fI\,\\$2\fR
+. shift 2
+. \}
+. if \\n[.$] .as an-result \/\\$1
+\\*[an-result]
+.\}
+..
+.de IB
+.if \\n[.$] \{\
+. ds an-result \&\fI\\$1
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \/\\fB\\$1\fI\,\\$2
+. shift 2
+. \}
+. if \\n[.$] .as an-result \/\\fB\\$1
+\\*[an-result]
+. ft R
+.\}
+..
+.de BI
+.if \\n[.$] \{\
+. ds an-result \&\fB\\$1
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \,\fI\\$1\fB\/\\$2
+. shift 2
+. \}
+. if \\n[.$] .as an-result \,\fI\\$1
+\\*[an-result]
+. ft R
+.\}
+..
+.de RB
+.ds an-result \&
+.while \\n[.$]>=2 \{\
+. as an-result \fR\\$1\fB\\$2
+. shift 2
+.\}
+.if \\n[.$] .as an-result \fR\\$1
+\\*[an-result]
+.ft R
+..
+.de BR
+.ds an-result \&
+.while \\n[.$]>=2 \{\
+. as an-result \fB\\$1\fR\\$2
+. shift 2
+.\}
+.if \\n[.$] .as an-result \fB\\$1
+\\*[an-result]
+.ft R
+..
+.de RS
+.br
+.nr an-saved-margin\\n[an-level] \\n[an-margin]
+.nr an-saved-prevailing-indent\\n[an-level] \\n[an-prevailing-indent]
+.ie \\n[.$] .nr an-margin +(n;\\$1)
+.el .nr an-margin +\\n[an-prevailing-indent]
+.in \\n[an-margin]u
+.nr an-prevailing-indent \\n[IN]
+.nr an-level +1
+..
+.de RE
+.br
+.ie \\n[.$] .nr an-level (;\\$1)<?\\n[an-level]
+.el .nr an-level -1
+.nr an-level 1>?\\n[an-level]
+.nr an-margin \\n[an-saved-margin\\n[an-level]]
+.nr an-prevailing-indent \\n[an-saved-prevailing-indent\\n[an-level]]
+.in \\n[an-margin]u
+..
+.ds S \s[\\n[PS]]
+.ie c\[rg] .ds R \[rg]
+.el .ds R (Reg.)
+.ie c\[tm] .ds Tm \[tm]
+.el .ds Tm (TM)
+.ds lq \(lq
+.ds rq \(rq
+.hy 14
+.\" Load local modifications.
+.mso man.local
+.cp \n(_C
diff --git a/gnu/usr.bin/groff/tmac/tmac.dvi b/gnu/usr.bin/groff/tmac/tmac.dvi
new file mode 100644
index 000000000000..c64fc73ce739
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.dvi
@@ -0,0 +1,132 @@
+.nr _C \n(.C
+.cp 0
+.ftr CR CW
+.ftr C CW
+.ftr TT CW
+.ftr HR H
+.\" This uses the dvi-char_1 string in font CW, dvi-char_0 otherwise.
+.char _ \R'dvi-char_ \\n(.f=\f(CW\\n(.f\fP'\\*[dvi-char_\\n[dvi-char_]]
+.char \[ul] \R'dvi-char_ \w'M'=\w'i''\\*[dvi-char_\\n[dvi-char_]]
+.\" Normally use a rule.
+.ds dvi-char_0 \v'.23m'\D'R .5m .04m'\v'-.04m'\v'-.23m'
+.\" In font CW use a real _ character.
+.ds dvi-char_1 _
+.if !c\[rn] .char \[rn] \D'R .5m -.04m'\v'.04m'
+.if !c\[br] .char \[br] \Z'\v'.25m'\D'R .04m -1m''
+.if !c\[ru] .char \[ru] \v'-.02m'\D'R .5m .04m'\v'-.04m'\v'.02m'
+.if !c\[co] .char \[co] \z\(ci\h'\w'\(ci'u-\w'c'u/2u'c\h'\w'\(ci'u-\w'c'u/2u'
+.if !c\[rg] .char \[rg] \z\(ci\h'\w'\(ci'u-\w'r'u/2u'r\h'\w'\(ci'u-\w'r'u/2u'
+.if !c\[fm] .char \[fm] \v'-.35m'\s[\\n(.s*7u/10u]\[prime]\s0\v'.35m'
+.if !c\[de] .char \[de] \h'.05m'\v'-.54m'\D'c .3m'\v'.54m'\h'.05m'
+.if !c\[ct] .char \[ct] \o'c/'
+.if !c\[sq] .char \[sq] \Z'\h'.05m'\D'R .4m -.04m'\v'.04m'\h'-.04m'\
+\D'R .04m -.4m'\v'.04m'\D'R -.4m -.04m'\D'R .04m .4m''\h'.5m'
+.\"char \[sq] \h'.05m'\D'l .4m 0'\D'l 0 -.4m'\D'l -.4m 0'\D'l 0 .4m'\h'.45m'
+.if !c\[!=] .char \[!=] \[slashnot]\(eq
+.if !c\[tm] .char \[tm] \v'-.3m'\s[\\n(.s/2u]TM\s0\v'.3m'
+.if !c\[aq] .char \[aq] '
+.if !c\[bq] .char \[bq] ,
+.if !c\[Bq] .char \[Bq] ,\h'\w'\(rq'u-(2u*\w"'"u)',
+.if !c\[ho] .char \[ho] \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.if !c\[-D] .char \[-D] \Z'\v'-.1m'\h'.05m'-'D
+.if !c\[Sd] .char \[Sd] \Z'\v'-.3m'\h'.35m'-'\(pd
+.if !c\[TP] .char \[TP] I\h'-.25m'\v'-.33m'\s[\En[.s]*6u/10u]\v'.33m'D\
+\v'-.33m'\s0\v'.33m'
+.if !c\[Tp] .char \[Tp] \zlp
+.cflags 8 \(an
+.if !c\[an] .char \[an] \h'-.167m'\(mi\h'-.167m'
+.\" Define some fractions.
+.de dvi-frac
+.if !c\[\\$1\\$2] .char \[\\$1\\$2] \
+\v'-.25m'\s[\\\\n(.s*7u/10u]\\$1\s0\v'.25m'\h'-.2m'\
+/\h'-.2m'\v'.25m'\s[\\\\n(.s*7u/10u]\\$2\s0\v'-.25m'
+..
+.dvi-frac 1 2
+.dvi-frac 3 4
+.dvi-frac 1 4
+.dvi-frac 1 8
+.dvi-frac 3 8
+.dvi-frac 5 8
+.dvi-frac 7 8
+.\" support for ISO Latin-1
+.if !c\[S1] .char \[S1] \v'-.2m'\s-31\s+3\v'+.2m'
+.if !c\[S2] .char \[S2] \v'-.2m'\s-32\s+3\v'+.2m'
+.if !c\[S3] .char \[S3] \v'-.2m'\s-33\s+3\v'+.2m'
+.if !c\[Of] .char \[Of] \v'-.2m'\s'\En(.s*6u/10u'\o'_a'\s0\v'.2m'
+.if !c\[Om] .char \[Om] \v'-.2m'\s'\En(.s*6u/10u'\o'_o'\s0\v'.2m'
+.if !c\[Fo] .char \[Fo] <<
+.if !c\[Fc] .char \[Fc] >>
+.if !c\[bb] .char \[bb] |
+.if !c\[Ye] .char \[Ye] \o'-Y'
+.if !c\[Cs] .char \[Cs] \o'\[mu]o'
+.de dvi-achar
+.\" Note that character definitions are always interpreted with
+.\" compatibility mode off.
+.if !c\\$1 \{\
+.char \\$1 \\$3\
+\k[acc]\
+\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\
+\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\
+\\$2\
+\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\
+\h'|\\\\n[acc]u'
+.\}
+.hcode \\$1\\$4
+..
+.dvi-achar \(`A \` A a
+.dvi-achar \('A \' A a
+.dvi-achar \(^A ^ A a
+.dvi-achar \(~A ~ A a
+.dvi-achar \(:A \(ad A a
+.dvi-achar \(oA \(ao A a
+.dvi-achar \(`E \` E e
+.dvi-achar \('E \' E e
+.dvi-achar \(^E ^ E e
+.dvi-achar \(:E \(ad E e
+.dvi-achar \(`I \` I i
+.dvi-achar \('I \' I i
+.dvi-achar \(^I ^ I i
+.dvi-achar \(:I \(ad I i
+.dvi-achar \(~N ~ N n
+.dvi-achar \(`O \` O o
+.dvi-achar \('O \' O o
+.dvi-achar \(^O ^ O o
+.dvi-achar \(~O ~ O o
+.dvi-achar \(:O \(ad O o
+.dvi-achar \(`U \` U u
+.dvi-achar \('U \' U u
+.dvi-achar \(^U ^ U u
+.dvi-achar \(:U \(ad U u
+.dvi-achar \('Y \' Y y
+.dvi-achar \(`a \` a a
+.dvi-achar \('a \' a a
+.dvi-achar \(^a ^ a a
+.dvi-achar \(~a ~ a a
+.dvi-achar \(:a \(ad a a
+.dvi-achar \(oa \(ao a a
+.dvi-achar \(`e \` e e
+.dvi-achar \('e \' e e
+.dvi-achar \(^e ^ e e
+.dvi-achar \(:e \(ad e e
+.dvi-achar \(`i \` \(.i i
+.dvi-achar \('i \' \(.i i
+.dvi-achar \(^i ^ \(.i i
+.dvi-achar \(:i \(ad \(.i i
+.dvi-achar \(~n ~ n n
+.dvi-achar \(`o \` o o
+.dvi-achar \('o \' o o
+.dvi-achar \(^o ^ o o
+.dvi-achar \(~o ~ o o
+.dvi-achar \(:o \(ad o o
+.dvi-achar \(`u \` u u
+.dvi-achar \('u \' u u
+.dvi-achar \(^u ^ u u
+.dvi-achar \(:u \(ad u u
+.dvi-achar \('y \' y y
+.dvi-achar \(:y \(ad y y
+.char \(,C \o'\(acc'
+.hcode \(,Cc
+.char \(,c \o'\(acc'
+.hcode \(,cc
+.cp \n(_C
+.do mso tmac.latin1
diff --git a/gnu/usr.bin/groff/tmac/tmac.latin1 b/gnu/usr.bin/groff/tmac/tmac.latin1
new file mode 100644
index 000000000000..f33ea2164ddc
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.latin1
@@ -0,0 +1,101 @@
+.nr _C \n(.C
+.cp 0
+.de latin1-tr
+.if c\\$2 .if !c\\$1 .tr \\$1\\$2
+..
+.latin1-tr \[char161] \(r!
+.latin1-tr \[char162] \(ct
+.latin1-tr \[char163] \(Po
+.latin1-tr \[char164] \(Cs
+.latin1-tr \[char165] \(Ye
+.latin1-tr \[char166] \(bb
+.latin1-tr \[char167] \(sc
+.latin1-tr \[char168] \(ad
+.latin1-tr \[char169] \(co
+.latin1-tr \[char170] \(Of
+.latin1-tr \[char171] \(Fo
+.latin1-tr \[char172] \(no
+.latin1-tr \[char173] \(hy
+.latin1-tr \[char174] \(rg
+.latin1-tr \[char175] \(a-
+.latin1-tr \[char176] \(de
+.latin1-tr \[char177] \(+-
+.latin1-tr \[char178] \(S2
+.latin1-tr \[char179] \(S3
+.latin1-tr \[char180] \(aa
+.latin1-tr \[char181] \(*m
+.latin1-tr \[char182] \(ps
+.latin1-tr \[char183] \(md
+.latin1-tr \[char184] \(ac
+.latin1-tr \[char185] \(S1
+.latin1-tr \[char186] \(Om
+.latin1-tr \[char187] \(Fc
+.latin1-tr \[char188] \(14
+.latin1-tr \[char189] \(12
+.latin1-tr \[char190] \(34
+.latin1-tr \[char191] \(r?
+.latin1-tr \[char192] \(`A
+.latin1-tr \[char193] \('A
+.latin1-tr \[char194] \(^A
+.latin1-tr \[char195] \(~A
+.latin1-tr \[char196] \(:A
+.latin1-tr \[char197] \(oA
+.latin1-tr \[char198] \(AE
+.latin1-tr \[char199] \(,C
+.latin1-tr \[char200] \(`E
+.latin1-tr \[char201] \('E
+.latin1-tr \[char202] \(^E
+.latin1-tr \[char203] \(:E
+.latin1-tr \[char204] \(`I
+.latin1-tr \[char205] \('I
+.latin1-tr \[char206] \(^I
+.latin1-tr \[char207] \(:I
+.latin1-tr \[char208] \(-D
+.latin1-tr \[char209] \(~N
+.latin1-tr \[char210] \(`O
+.latin1-tr \[char211] \('O
+.latin1-tr \[char212] \(^O
+.latin1-tr \[char213] \(~O
+.latin1-tr \[char214] \(:O
+.latin1-tr \[char215] \(mu
+.latin1-tr \[char216] \(/O
+.latin1-tr \[char217] \(`U
+.latin1-tr \[char218] \('U
+.latin1-tr \[char219] \(^U
+.latin1-tr \[char220] \(:U
+.latin1-tr \[char221] \('Y
+.latin1-tr \[char222] \(TP
+.latin1-tr \[char223] \(ss
+.latin1-tr \[char224] \(`a
+.latin1-tr \[char225] \('a
+.latin1-tr \[char226] \(^a
+.latin1-tr \[char227] \(~a
+.latin1-tr \[char228] \(:a
+.latin1-tr \[char229] \(oa
+.latin1-tr \[char230] \(ae
+.latin1-tr \[char231] \(,c
+.latin1-tr \[char232] \(`e
+.latin1-tr \[char233] \('e
+.latin1-tr \[char234] \(^e
+.latin1-tr \[char235] \(:e
+.latin1-tr \[char236] \(`i
+.latin1-tr \[char237] \('i
+.latin1-tr \[char238] \(^i
+.latin1-tr \[char239] \(:i
+.latin1-tr \[char240] \(Sd
+.latin1-tr \[char241] \(~n
+.latin1-tr \[char242] \(`o
+.latin1-tr \[char243] \('o
+.latin1-tr \[char244] \(^o
+.latin1-tr \[char245] \(~o
+.latin1-tr \[char246] \(:o
+.latin1-tr \[char247] \(di
+.latin1-tr \[char248] \(/o
+.latin1-tr \[char249] \(`u
+.latin1-tr \[char250] \('u
+.latin1-tr \[char251] \(^u
+.latin1-tr \[char252] \(:u
+.latin1-tr \[char253] \('y
+.latin1-tr \[char254] \(Tp
+.latin1-tr \[char255] \(:y
+.cp \n(_C
diff --git a/gnu/usr.bin/groff/tmac/tmac.pic b/gnu/usr.bin/groff/tmac/tmac.pic
new file mode 100644
index 000000000000..1177fc09d179
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.pic
@@ -0,0 +1,10 @@
+.de PS
+.br
+.sp .3v
+.ne 0\\$1+1v+\n(.Vu
+.in \\n(.lu-\\n(.iu-0\\$2/2u>?0
+..
+.de PE
+.in
+.sp .3v+.5m
+..
diff --git a/gnu/usr.bin/groff/tmac/tmac.ps b/gnu/usr.bin/groff/tmac/tmac.ps
new file mode 100644
index 000000000000..d7d655dbad42
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.ps
@@ -0,0 +1,52 @@
+.nr _C \n(.C
+.cp 0
+.ftr AX ABI
+.ftr KR BMR
+.ftr KI BMI
+.ftr KB BMB
+.ftr KX BMBI
+.ftr CW CR
+.ftr CO CI
+.ftr CX CBI
+.ftr H HR
+.ftr HO HI
+.ftr HX HBI
+.ftr Hr HNR
+.ftr Hi HNI
+.ftr Hb HNB
+.ftr Hx HNBI
+.ftr NX NBI
+.ftr PA PR
+.ftr PX PBI
+.ftr ZI ZCMI
+.ftr C CR
+.cflags 8 \(an
+.char \(rn \h'-\w'\(sr'u'\(rn\h'\w'\(sr'u'
+.char \(mo \h'.08m'\(mo\h'-.08m'
+.char \(nm \h'.08m'\(nm\h'-.08m'
+.char \[parenlefttp] \[parenlefttp]\h'.016m'
+.char \[parenleftbt] \[parenleftbt]\h'.016m'
+.char \[parenleftex] \[parenleftex]\h'.016m'
+.char \[parenrighttp] \[parenrighttp]\h'.016m'
+.char \[parenrightbt] \[parenrightbt]\h'.016m'
+.char \[parenrightex] \[parenrightex]\h'.016m'
+.if !c\[va] .char \[va] \o'\[ua]\[da]'
+.if !c\[ci] \
+.char \[ci] \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m'
+.if !c\[sq] \
+.char \[sq] \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m'
+.if !c\[ru] .char \[ru] \D'l .5m 0'
+.if !c\[ul] .char \[ul] \v'.25m'\D'l .5m 0'\v'-.25m'
+.if !c\[br] .char \[br] \Z'\v'.25m'\D'l 0 -1m''
+.if !c\[or] .char \[or] \h'.1m'\Z'\D'l 0 -.675m''\h'.1m'
+.if !c\[Fi] .char \[Fi] ffi
+.if !c\[Fl] .char \[Fl] ffl
+.if !c\[ff] .char \[ff] ff
+.if !c\[ij] .char \[ij] ij
+.if !c\[IJ] .char \[IJ] IJ
+.if !c\[tm] .char \[tm] \s-3\v'-.3m'TM\v'+.3m'\s+3
+.\" pic tests this register to see whether it should use \X'ps:...'
+.nr 0p 1
+.cp \n(_C
+.if !\n(.C .mso tmac.pspic
+.do mso tmac.psold
diff --git a/gnu/usr.bin/groff/tmac/tmac.psatk b/gnu/usr.bin/groff/tmac/tmac.psatk
new file mode 100644
index 000000000000..b59d23a24e7e
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.psatk
@@ -0,0 +1,61 @@
+.\" Implementation of the ATK PB and PE macros for use with groff and grops.
+.\" Load this after tmac.atk.
+.nr zT 0
+.if '\*(.T'ps' .nr zT 1
+.nr psatk-unit 1p
+.de psatk-defs
+ps: mdef 5
+/PB {
+ /saved save def
+ currentpoint translate
+ \n[psatk-unit] u -\n[psatk-unit] u scale
+ userdict begin
+ /showpage {} def
+} bind def
+/PE {
+ end
+ saved restore
+} bind def
+/troffadjust {
+ pop 0
+} bind def
+..
+.de PB
+.ne \\$1p
+.nr zT \\n(zT>0
+\\*[PB\\n(zT]\\
+..
+.de PE
+\\*[PE\\n(zT]\\
+..
+.ds PB0
+.\" The last line before the "'PE" is "\}" rather than ".\}". This
+.\" would cause a spurious space to be introduced before any picture
+.\" that was the first thing on a line. So we have to catch that and
+.\" remove it.
+.de PB1
+.ev psatk
+.fi
+.di psatk-mac
+\!ps: exec PB
+..
+.de PE0
+\v'-.75m'\
+\D'l \\$1p 0'\D'l 0 \\$2p'\D'l -\\$1p 0'\D'l 0 -\\$2p'\
+\h'\\$1p'\v'.75m'\x'\\$2p-1m>?0'\c
+..
+.ds psatk-init \Y[psatk-defs]
+.de PE1
+\!PE
+.di
+.di null
+.br
+.di
+.rm null
+.ev
+\v'-.75m'\
+\\*[psatk-init]\Y[psatk-mac]\
+\h'\\$1p'\v'.75m'\x'\\$2p-1m>?0'\c
+.rm psatk-mac
+.if \\n(.P .ds psatk-init
+..
diff --git a/gnu/usr.bin/groff/tmac/tmac.psfig b/gnu/usr.bin/groff/tmac/tmac.psfig
new file mode 100644
index 000000000000..5f4111ce6a16
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.psfig
@@ -0,0 +1,87 @@
+.\" These are macros to make psfig work with groff.
+.\" They require that psfig be patched as described in ../grops/psfig.diff.
+.de psfig-defs
+ps: mdef 100
+
+% wid ht llx lly urx ury psfigstart -
+
+/psfigstart {
+ /level1 save def
+ /ury exch def
+ /urx exch def
+ /lly exch def
+ /llx exch def
+ /ht exch u def
+ /wid exch u def
+ currentpoint ht add translate
+ wid urx llx sub div ht ury lly sub div neg scale
+ llx neg lly neg translate
+
+ % set the graphics state to default values
+ 0 setgray
+ 0 setlinecap
+ 1 setlinewidth
+ 0 setlinejoin
+ 10 setmiterlimit
+ [] 0 setdash
+ newpath
+ /showpage {} def
+} bind def
+
+% psfigclip -
+
+/psfigclip {
+ currentpoint newpath
+ llx lly moveto
+ urx lly lineto
+ urx ury lineto
+ llx ury lineto
+ closepath clip
+ newpath moveto
+} bind def
+
+% psfigend -
+
+/psfigend {
+ level1 restore
+} bind def
+
+% globalstart -
+
+/globalstart {
+ % save the current space code on the stack
+ SC
+ level0 restore
+} bind def
+
+% globalend -
+
+/globalend {
+ end
+ BP
+ /SC exch def
+ DEFS begin
+} bind def
+..
+.de psfig-init
+.if \\n[.P] \{\
+\Y[psfig-defs]
+. br
+. sp -1
+. ds psfig-init\" empty
+. rm psfig-defs
+.\}
+..
+.de F+
+.br
+.psfig-init
+.nr psfig-fill \\n[.u]
+.nf
+.sp -.5
+.if !\\n[.$] .ce 9999
+..
+.de F-
+.br
+.ce 0
+.if \\n[psfig-fill] .fi
+..
diff --git a/gnu/usr.bin/groff/tmac/tmac.psnew b/gnu/usr.bin/groff/tmac/tmac.psnew
new file mode 100644
index 000000000000..e13bdb88696c
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.psnew
@@ -0,0 +1,26 @@
+.\" Undo the effect of tmac.psold. This gives access to the additional
+.\" characters that are present in the text fonts of newer PostScript
+.\" printers. It is a bad idea to use this if you are going to
+.\" distribute the resulting PostScript output to others.
+.nr _C \n(.C
+.cp 0
+.rchar \('y\('Y\(12\(14\(34\(S1\(S2\(S3\(bb\(de\(Tp\(TP\(-D\(Sd
+.tr \[char166]\[char166]
+.tr \[char176]\[char176]
+.tr \[char177]\[char177]
+.tr \[char178]\[char178]
+.tr \[char179]\[char179]
+.tr \[char181]\[char181]
+.tr \[char185]\[char185]
+.tr \[char188]\[char188]
+.tr \[char189]\[char189]
+.tr \[char190]\[char190]
+.tr \[char208]\[char208]
+.tr \[char215]\[char215]
+.tr \[char221]\[char221]
+.tr \[char222]\[char222]
+.tr \[char240]\[char240]
+.tr \[char247]\[char247]
+.tr \[char253]\[char253]
+.tr \[char254]\[char254]
+.cp \n(_C
diff --git a/gnu/usr.bin/groff/tmac/tmac.psold b/gnu/usr.bin/groff/tmac/tmac.psold
new file mode 100644
index 000000000000..04a5f6df49f0
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.psold
@@ -0,0 +1,60 @@
+.\" In the newer PostScript printers, the text fonts contain all ISO Latin-1
+.\" characters. The font description files that comes with groff match
+.\" these fonts. The text fonts in older PostScript printers are missing
+.\" some of these characters. This file prevents those characters from
+.\" being used. This will allow the PostScript output to be printed on both
+.\" old and new printers. The effect of this file can be undone by
+.\" tmac.psnew.
+.nr _C \n(.C
+.cp 0
+.\" Define an accented character.
+.de ps-achar
+.\" Note that character definitions are always interpreted with
+.\" compatibility mode off.
+.char \\$1 \\$3\
+\k[acc]\
+\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\
+\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\
+\\$2\
+\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\
+\h'|\\\\n[acc]u'
+.ie '\\$3'\(.i' .hcode \\$1i
+.el .hcode \\$1\\$3
+..
+.ps-achar \['y] \(aa y
+.ps-achar \['Y] \(aa Y
+.char \[12] \v'-.7m\s[\\n(.s*6u/10u]+.7m'1\v'-.7m\s0+.7m'\
+\(f/\s[\\n(.s*6u/10u]2\s0
+.char \[14] \v'-.7m\s[\\n(.s*6u/10u]+.7m'1\v'-.7m\s0+.7m'\
+\(f/\s[\\n(.s*6u/10u]4\s0
+.char \[34] \v'-.7m\s[\\n(.s*6u/10u]+.7m'3\v'-.7m\s0+.7m'\
+\(f/\s[\\n(.s*6u/10u]4\s0
+.char \[S1] \v'-.2m'\s-31\s+3\v'+.2m'
+.char \[S2] \v'-.2m'\s-32\s+3\v'+.2m'
+.char \[S3] \v'-.2m'\s-33\s+3\v'+.2m'
+.char \[bb] |
+.char \[de] \fS\(de
+.char \[-D] \Z'\v'-.1m'-'D
+.char \[TP] \
+I\h'-.25m'\v'-.33m'\s'\En(.s*6u/10u'\v'.33m'D\v'-.33m'\s0\v'.33m'
+.char \[Sd] \Z'\v'-.3m'\h'.2m'-'\(pd
+.char \[Tp] \zlp
+.tr \[char166]\[bb]
+.tr \[char176]\[de]
+.tr \[char177]\[+-]
+.tr \[char178]\[S2]
+.tr \[char179]\[S3]
+.tr \[char181]\[*m]
+.tr \[char185]\[S1]
+.tr \[char188]\[14]
+.tr \[char189]\[12]
+.tr \[char190]\[34]
+.tr \[char208]\[-D]
+.tr \[char215]\[mu]
+.tr \[char221]\['Y]
+.tr \[char222]\[TP]
+.tr \[char240]\[Sd]
+.tr \[char247]\[di]
+.tr \[char253]\['y]
+.tr \[char254]\[Tp]
+.cp \n(_C
diff --git a/gnu/usr.bin/groff/tmac/tmac.pspic b/gnu/usr.bin/groff/tmac/tmac.pspic
new file mode 100644
index 000000000000..9923907ff716
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.pspic
@@ -0,0 +1,41 @@
+.\" Define the PSPIC macro.
+.\" When used other than with -Tps, it will draw a box around where
+.\" the picture would go.
+.de ps-bb
+.nr ps-nargs \\n[.$]
+.if \\n[ps-nargs]=4 \{\
+. nr ps-llx 0\\$1
+. nr ps-lly 0\\$2
+. nr ps-urx 0\\$3
+. nr ps-ury 0\\$4
+.\}
+..
+.de PSPIC
+.br
+.sy echo .ps-bb `psbb \\$1` >/tmp/psbb\\n[$$]
+.so /tmp/psbb\\n[$$]
+.if \\n[ps-nargs]=4 \{\
+. nr ps-wid (\\n[ps-urx]-\\n[ps-llx])
+. nr ps-ht (\\n[ps-ury]-\\n[ps-lly])
+. if \\n[ps-wid]<0 .nr ps-wid 0-\\n[ps-wid]
+. if \\n[ps-ht]<0 .nr ps-ht 0-\\n[ps-ht]
+. ie \\n[.$]>=2 .nr ps-deswid (i;\\$2)
+. el .nr ps-deswid \\n[.l]-\\n[.i]<?\\n[ps-wid]p
+. ie \\n[.$]>=3 .nr ps-desht (i;\\$3)
+. el .nr ps-desht \\n[ps-deswid]*1000+(\\n[ps-wid]/2)/\\n[ps-wid]\
+*\\n[ps-ht]+500/1000
+. ne \\n[ps-desht]u+1v
+. nr ps-offset \\n[.l]-\\n[.i]-\\n[ps-deswid]/2
+. ie \\n[.$]>=3 .ds ps-desht \\n[ps-desht]
+. el .ds ps-desht \" empty
+\h'\\n[ps-offset]u'\
+\X'ps: invis'\
+\Z'\D'p 0 \\n[ps-desht]u \\n[ps-deswid]u 0 0 -\\n[ps-desht]u''\
+\X'ps: endinvis'\
+\v'\\n[ps-desht]u'\X'ps: import \\$1 \
+\\n[ps-llx] \\n[ps-lly] \\n[ps-urx] \\n[ps-ury] \\n[ps-deswid] \\*[ps-desht]'
+. br
+. sp \\n[ps-desht]u
+.\}
+.sy rm /tmp/psbb\\n[$$]
+..
diff --git a/gnu/usr.bin/groff/tmac/tmac.s b/gnu/usr.bin/groff/tmac/tmac.s
new file mode 100644
index 000000000000..9afb7e6f0bfb
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.s
@@ -0,0 +1,1803 @@
+.ig
+Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+..
+.if !\n(.g .ab These ms macros require groff.
+.if \n(.C \
+. ab The groff ms macros do not work in compatibility mode.
+.\" Enable warnings. You can delete this if you want.
+.warn
+.\" See if already loaded.
+.if r GS .nx
+.nr GS 1
+.de @error
+.tm \\n(.F:\\n(.c: macro error: \\$*
+..
+.de @warning
+.tm \\n(.F:\\n(.c: macro warning: \\$*
+..
+.de @fatal
+.ab \\n(.F:\\n(.c: fatal macro error: \\$*
+..
+.de @not-implemented
+.@error sorry, \\$0 not implemented
+.als \\$0 @nop
+..
+.als TM @not-implemented
+.als CT @not-implemented
+.de @nop
+..
+.de @init
+.\" a non-empty environment
+.ev ne
+\c
+.ev
+.ev nf
+'nf
+.ev
+..
+.ds REFERENCES References
+.ds ABSTRACT ABSTRACT
+.ds TOC Table of Contents
+.ds MONTH1 January
+.ds MONTH2 February
+.ds MONTH3 March
+.ds MONTH4 April
+.ds MONTH5 May
+.ds MONTH6 June
+.ds MONTH7 July
+.ds MONTH8 August
+.ds MONTH9 September
+.ds MONTH10 October
+.ds MONTH11 November
+.ds MONTH12 December
+.ds MO \\*[MONTH\n[mo]]
+.nr *year \n[yr]+1900
+.ds DY \n[dy] \*[MO] \n[*year]
+.de ND
+.if \\n[.$] .ds DY "\\$*
+..
+.de DA
+.if \\n[.$] .ds DY "\\$*
+.ds CF \\*[DY]
+..
+.\" indexing
+.de IX
+.tm \\$1\t\\$2\t\\$3\t\\$4 ... \\n[PN]
+..
+.\" print an error message and then try to recover
+.de @error-recover
+.@error \\$@ (recovering)
+.nr *pop-count 0
+.while !'\\n(.z'' \{\
+. \"@warning automatically terminating diversion \\n(.z
+. ie d @div-end!\\n(.z .@div-end!\\n(.z
+. el .*div-end-default
+. nr *pop-count +1
+. \" ensure that we don't loop forever
+. if \\n[*pop-count]>20 .@fatal recovery failed
+.\}
+.while !'\\n[.ev]'0' .ev
+.par@reset-env
+.par@reset
+..
+.de *div-end-default
+.ds *last-div \\n(.z
+.br
+.di
+.ev nf
+.\\*[*last-div]
+.ev
+..
+.\" ****************************
+.\" ******** module cov ********
+.\" ****************************
+.\" Cover sheet and first page.
+.de cov*err-not-after-first-page
+.@error \\$0 is not allowed after the first page has started
+..
+.de cov*err-not-before-tl
+.@error \\$0 is not allowed before TL
+..
+.de cov*err-not-again
+.@error \\$0 is not allowed more than once
+..
+.de cov*err-not-after-ab
+.@error \\$0 is not allowed after first AB, LP, PP, IP, SH or NH
+..
+.als AU cov*err-not-before-tl
+.als AI cov*err-not-before-tl
+.als AB cov*err-not-before-tl
+.de cov*first-page-init
+.rm cov*first-page-init
+.par@init
+.als RP cov*err-not-after-first-page
+.@init
+.ie \\n[cov*rp-format] \{\
+. pg@cs-top
+. als FS cov*FS
+. als FE cov*FE
+.\}
+.el \{\
+. pg@top
+. als FS @FS
+. als FE @FE
+.\}
+.wh 0 pg@top
+..
+.wh 0 cov*first-page-init
+.\" This handles the case where FS occurs before TL or LP.
+.de FS
+.br
+\\*[FS]\\
+..
+.nr cov*rp-format 0
+.nr cov*rp-no 0
+.\" released paper format
+.de RP
+.nr cov*rp-format 1
+.if \\n[.$] .if '\\$1'no' .nr cov*rp-no 1
+.pn 0
+..
+.de TL
+.br
+.als TL cov*err-not-again
+.rn @AB AB
+.rn @AU AU
+.rn @AI AI
+.di cov*tl-div
+.par@reset
+.ft B
+.ps +2
+.vs +3p
+.ll (u;\\n[LL]*5/6)
+.nr cov*n-au 0
+..
+.de @AU
+.par@reset
+.if !'\\n(.z'' \{\
+. br
+. di
+.\}
+.nr cov*n-au +1
+.di cov*au-div!\\n[cov*n-au]
+.nf
+.ft I
+.ps \\n[PS]
+..
+.de @AI
+.par@reset
+.if !'\\n(.z'' \{\
+. br
+. di
+.\}
+.ie !\\n[cov*n-au] .@error AI before AU
+.el \{\
+. di cov*ai-div!\\n[cov*n-au]
+. nf
+. ft R
+. ps \\n[PS]
+.\}
+..
+.de LP
+.if !'\\n[.z]'' \{\
+. br
+. di
+.\}
+.br
+.cov*ab-init
+.cov*print
+\\*[\\$0]\\
+..
+.als IP LP
+.als PP LP
+.als XP LP
+.als NH LP
+.als SH LP
+.als MC LP
+.als RT LP
+.als XS LP
+.de cov*ab-init
+.als cov*ab-init @nop
+.als LP @LP
+.als IP @IP
+.als PP @PP
+.als XP @XP
+.als RT @RT
+.als XS @XS
+.als SH @SH
+.als NH @NH
+.als QP @QP
+.als RS @RS
+.als RE @RE
+.als QS @QS
+.als QE @QE
+.als MC @MC
+.als EQ @EQ
+.als EN @EN
+.als AB cov*err-not-after-ab
+.als AU par@AU
+.als AI par@AI
+.als TL par@TL
+..
+.de @AB
+.if !'\\n(.z'' \{\
+. br
+. di
+.\}
+.cov*ab-init
+.di cov*ab-div
+.par@ab-indent
+.par@reset
+.if !'\\$1'no' \{\
+. ft I
+. ce 1
+\\*[ABSTRACT]
+. sp
+. ft R
+.\}
+.ns
+.@PP
+..
+.de AE
+.ie '\\n(.z'cov*ab-div' \{\
+. als AE cov*err-not-again
+. br
+. di
+.\" nr cov*ab-height \\n[dn]
+. par@reset-env
+. par@reset
+. cov*print
+.\}
+.el .@error AE without AB
+..
+.de @div-end!cov*ab-div
+.AE
+..
+.de cov*print
+.als cov*print @nop
+.ie d cov*tl-div \{\
+. ie \\n[cov*rp-format] .cov*rp-print
+. el .cov*draft-print
+.\}
+.el \{\
+. if \\n[cov*rp-format] \{\
+. @warning RP format but no TL
+. bp 1
+. als FS @FS
+. als FE @FE
+. \}
+. br
+.\}
+..
+.de cov*rp-print
+.nr cov*page-length \\n[.p]
+.pl 1000i
+.cov*tl-au-print
+.sp 3
+.if d cov*ab-div \{\
+. nf
+. cov*ab-div
+.\}
+.sp 3
+.par@reset
+\\*[DY]
+.br
+.if \\n[cov*fn-height] \{\
+. sp |(u;\\n[cov*page-length]-\\n[FM]\
+-\\n[cov*fn-height]-\\n[fn@sep-dist]>?\\n[nl])
+. fn@print-sep
+. ev nf
+. cov*fn-div
+. ev
+. ie \\n[cov*rp-no] .rm cov*fn-div
+. el \{\
+. rn cov*fn-div fn@overflow-div
+. nr fn@have-overflow 1
+. \}
+.\}
+.als FS @FS
+.als FE @FE
+.\" If anything was printed below where the footer line is normally printed,
+.\" then that's an overflow.
+.if -\\n[FM]/2+1v+\\n[cov*page-length]<\\n[nl] .@error cover sheet overflow
+.pl \\n[cov*page-length]u
+.bp 1
+.if !\\n[cov*rp-no] .cov*tl-au-print
+.rs
+.sp 1
+..
+.de cov*draft-print
+.cov*tl-au-print
+.if d cov*ab-div \{\
+. nf
+. sp 2
+. cov*ab-div
+.\}
+.sp 1
+..
+.de cov*tl-au-print
+.par@reset
+.nf
+.rs
+.sp 3
+.ce 9999
+.cov*tl-div
+.nr cov*i 1
+.nr cov*sp 1v
+.while \\n[cov*i]<=\\n[cov*n-au] \{\
+. sp \\n[cov*sp]u
+. cov*au-div!\\n[cov*i]
+. ie d cov*ai-div!\\n[cov*i] \{\
+. sp .5v
+. cov*ai-div!\\n[cov*i]
+. nr cov*sp 1v
+. \}
+. el .nr cov*sp .5v
+. nr cov*i +1
+.\}
+.ce 0
+..
+.nr cov*fn-height 0
+.nr cov*in-fn 0
+.\" start of footnote on cover
+.de cov*FS
+.if \\n[cov*in-fn] \{\
+. @error nested FS
+. FE
+.\}
+.nr cov*in-fn 1
+.ev fn
+.par@reset-env
+.da cov*fn-div
+.if !\\n[cov*fn-height] .ns
+.ie \\n[.$] .FP "\\$1" no
+.el .@LP
+..
+.de @div-end!cov*fn-div
+.cov*FE
+..
+.\" end of footnote on cover
+.de cov*FE
+.ie '\\n(.z'cov*fn-div' \{\
+. br
+. ev
+. di
+. nr cov*in-fn 0
+. nr cov*fn-height +\\n[dn]
+.\}
+.el .@error FE without matching FS
+..
+.\" ***************************
+.\" ******** module pg ********
+.\" ***************************
+.\" Page-level formatting.
+.\" > 0 if we have a footnote on the current page
+.nr pg@fn-flag 0
+.nr pg@colw 0
+.nr pg@fn-colw 0
+.nr HM 1i
+.nr FM 1i
+.nr PO 1i
+.ds LF
+.ds CF
+.ds RF
+.ds LH
+.ds CH -\\n[PN]-
+.ds RH
+.ds pg*OH '\\*[LH]'\\*[CH]'\\*[RH]'
+.ds pg*EH '\\*[LH]'\\*[CH]'\\*[RH]'
+.ds pg*OF '\\*[LF]'\\*[CF]'\\*[RF]'
+.ds pg*EF '\\*[LF]'\\*[CF]'\\*[RF]'
+.de OH
+.ds pg*\\$0 "\\$*
+..
+.als EH OH
+.als OF OH
+.als EF OH
+.de PT
+.ie \\n%=1 .if \\n[pg*P1] .tl \\*[pg*OH]
+.el \{\
+. ie o .tl \\*[pg*OH]
+. el .tl \\*[pg*EH]
+.\}
+..
+.de BT
+.ie o .tl \\*[pg*OF]
+.el .tl \\*[pg*EF]
+..
+.nr pg*P1 0
+.de P1
+.nr pg*P1 1
+..
+.wh -\n[FM]u pg@bottom
+.wh -\n[FM]u/2u pg*footer
+.nr MINGW 2n
+.nr pg@ncols 1
+.de @MC
+.if !'\\n(.z'' .error-recover MC while diversion open
+.br
+.ie \\n[pg@ncols]>1 .pg@super-eject
+.el \{\
+. \" flush out any floating keeps
+. while \\n[kp@tail]>\\n[kp@head] \{\
+. rs
+. bp
+. \}
+.\}
+.ie !\\n(.$ \{\
+. nr pg@colw \\n[LL]*7/15
+. nr pg*gutw \\n[LL]-(2*\\n[pg@colw])
+. nr pg@ncols 2
+.\}
+.el \{\
+. nr pg@colw (n;\\$1)<?\\n[LL]
+. ie \\n[.$]<2 .nr pg*gutw \\n[MINGW]
+. el .nr pg*gutw (n;\\$2)
+. nr pg@ncols \\n[LL]-\\n[pg@colw]/(\\n[pg@colw]+\\n[pg*gutw])+1
+. ie \\n[pg@ncols]>1 \
+. nr pg*gutw \\n[LL]-(\\n[pg@ncols]*\\n[pg@colw])/(\\n[pg@ncols]-1)
+. el .nr pg*gutw 0
+.\}
+.mk pg*col-top
+.ns
+.nr pg*col-num 0
+.nr pg@fn-colw \\n[pg@colw]*5/6
+.par@reset
+..
+.de 2C
+.MC
+..
+.de 1C
+.MC \\n[LL]u
+..
+.\" top of page macro
+.de pg@top
+.ch pg*footer -\\n[FM]u/2u
+.nr PN \\n%
+.nr pg*col-num 0
+.nr pg@fn-bottom-margin 0
+.nr pg*saved-po \\n[PO]
+.po \\n[PO]u
+.ev h
+.par@reset
+.sp (u;\\n[HM]/2)
+.PT
+.sp |\\n[HM]u
+.if d HD .HD
+.mk pg@header-bottom
+.ev
+.mk pg*col-top
+.pg*start-col
+..
+.de pg*start-col
+.\" Handle footnote overflow before floating keeps, because the keep
+.\" might contain an embedded footnote.
+.fn@top-hook
+.kp@top-hook
+.tbl@top-hook
+.ns
+..
+.de pg@cs-top
+.sp \\n[HM]u
+.\" move pg@bottom and pg*footer out of the way
+.ch pg@bottom \\n[.p]u*2u
+.ch pg*footer \\n[.p]u*2u
+.ns
+..
+.de pg@bottom
+.tbl@bottom-hook
+.if \\n[pg@fn-flag] .fn@bottom-hook
+.nr pg*col-num +1
+.ie \\n[pg*col-num]<\\n[pg@ncols] .pg*end-col
+.el .pg*end-page
+..
+.de pg*end-col
+'sp |\\n[pg*col-top]u
+.po (u;\\n[pg*saved-po]+(\\n[pg@colw]+\\n[pg*gutw]*\\n[pg*col-num]))
+.\"po +(u;\\n[pg@colw]+\\n[pg*gutw])
+.pg*start-col
+..
+.de pg*end-page
+.po \\n[pg*saved-po]u
+.\" Make sure we don't exit if there are still floats or footnotes left-over.
+.ie \\n[kp@head]<\\n[kp@tail]:\\n[fn@have-overflow] \{\
+. \" Switching environments ensures that we don't get an unnecessary
+. \" blank line at the top of the page.
+. ev ne
+' bp
+. ev
+.\}
+.el \{\
+. \" If the text has ended and there are no more footnotes or keeps, exit.
+. if \\n[pg@text-ended] .ex
+. if r pg*next-number \{\
+. pn \\n[pg*next-number]
+. rr pg*next-number
+. if d pg*next-format \{\
+. af PN \\*[pg*next-format]
+. rm pg*next-format
+. \}
+. \}
+' bp
+.\}
+..
+.\" pg@begin number format
+.de pg@begin
+.ie \\n[.$]>0 \{\
+. nr pg*next-number (;\\$1)
+. ie \\n[.$]>1 .ds pg*next-format \\$2
+. el .rm pg*next-format
+.\}
+.el .rr pg*next-number
+.pg@super-eject
+..
+.\" print the footer line
+.de pg*footer
+.ev h
+.par@reset
+.BT
+.ev
+..
+.\" flush out any keeps or footnotes
+.de pg@super-eject
+.br
+.if !'\\n(.z'' .@error-recover diversion open while ejecting page
+.\" Make sure we stay in the end macro while there is still footnote overflow
+.\" left, or floating keeps.
+.while \\n[kp@tail]>\\n[kp@head]:\\n[pg@fn-flag] \{\
+. rs
+. bp
+.\}
+.bp
+..
+.nr pg@text-ended 0
+.de pg@end-text
+.br
+.nr pg@text-ended 1
+.pg@super-eject
+..
+.em pg@end-text
+.\" ***************************
+.\" ******** module fn ********
+.\" ***************************
+.\" Footnotes.
+.nr fn@sep-dist 8p
+.ev fn
+.\" Round it vertically
+.vs \n[fn@sep-dist]u
+.nr fn@sep-dist \n[.v]
+.ev
+.nr fn*text-num 0 1
+.nr fn*note-num 0 1
+.ds * \\*[par@sup-start]\En+[fn*text-num]\\*[par@sup-end]
+.nr fn*open 0
+.\" normal FS
+.de @FS
+.ie \\n[.$] .fn*do-FS "\\$1" no
+.el \{\
+. ie \\n[fn*text-num]>\\n[fn*note-num] .fn*do-FS \\n+[fn*note-num]
+. el .fn*do-FS
+.\}
+..
+.\" Second argument of `no' means don't embellish the first argument.
+.de fn*do-FS
+.if \\n[fn*open] .@error-recover nested FS
+.nr fn*open 1
+.if \\n[.u] \{\
+. \" Ensure that the first line of the footnote is on the same page
+. \" as the reference. I think this is minimal.
+. ev fn
+. nr fn*need 1v
+. ev
+. ie \\n[pg@fn-flag] .nr fn*need +\\n[fn:PD]
+. el .nr fn*need +\\n[fn@sep-dist]
+. ne \\n[fn*need]u+\\n[.V]u>?0
+.\}
+.ev fn
+.par@reset-env
+.fn*start-div
+.par@reset
+.ie \\n[.$] .FP \\$@
+.el .@LP
+..
+.de @FE
+.ie !\\n[fn*open] .@error FE without FS
+.el \{\
+. nr fn*open 0
+. br
+. ev
+. fn*end-div
+.\}
+..
+.nr fn@have-overflow 0
+.\" called at the top of each column
+.de fn@top-hook
+.nr fn*max-width 0
+.nr fn*page-bottom-pos 0-\\n[FM]-\\n[pg@fn-bottom-margin]
+.ch pg@bottom \\n[fn*page-bottom-pos]u
+.if \\n[fn@have-overflow] \{\
+. nr fn@have-overflow 0
+. fn*start-div
+. ev nf
+. fn@overflow-div
+. ev
+. fn*end-div
+.\}
+..
+.\" This is called at the bottom of the column if pg@fn-flag is set.
+.de fn@bottom-hook
+.nr pg@fn-flag 0
+.nr fn@have-overflow 0
+.nr fn@bottom-pos \\n[.p]-\\n[FM]-\\n[pg@fn-bottom-margin]+\\n[.v]
+.ev fn
+.nr fn@bottom-pos -\\n[.v]
+.ev
+.ie \\n[nl]+\\n[fn@sep-dist]+\n[.V]>\\n[fn@bottom-pos] \{\
+. rn fn@div fn@overflow-div
+. nr fn@have-overflow 1
+.\}
+.el \{\
+. if \\n[pg@ncols]>1 \
+. if \\n[fn*max-width]>\\n[pg@fn-colw] \
+. nr pg@fn-bottom-margin \\n[.p]-\\n[FM]-\\n[nl]+1v
+. wh \\n[fn@bottom-pos]u fn*catch-overflow
+. fn@print-sep
+. ev nf
+. fn@div
+. rm fn@div
+. ev
+. if '\\n(.z'fn@overflow-div' \{\
+. di
+. nr fn@have-overflow \\n[dn]>0
+. \}
+. ch fn*catch-overflow
+.\}
+..
+.de fn*catch-overflow
+.di fn@overflow-div
+..
+.nr fn*embed-count 0
+.de @div-end!fn@div
+.br
+.if '\\n[.ev]'fn' .ev
+.fn*end-div
+.nr fn*open 0
+..
+.als @div-end!fn*embed-div @div-end!fn@div
+.de fn*start-div
+.ie '\\n(.z'' \{\
+. da fn@div
+. if !\\n[pg@fn-flag] .ns
+.\}
+.el .di fn*embed-div
+..
+.de fn*end-div
+.ie '\\n(.z'fn@div' \{\
+. di
+. nr fn*page-bottom-pos -\\n[dn]
+. nr fn*max-width \\n[fn*max-width]>?\\n[dl]
+. if !\\n[pg@fn-flag] .nr fn*page-bottom-pos -\\n[fn@sep-dist]
+. nr pg@fn-flag 1
+. nr fn*page-bottom-pos \\n[nl]-\\n[.p]+\n[.V]>?\\n[fn*page-bottom-pos]
+. ch pg@bottom \\n[fn*page-bottom-pos]u
+.\}
+.el \{\
+. ie '\\n(.z'fn*embed-div' \{\
+. di
+. rn fn*embed-div fn*embed-div!\\n[fn*embed-count]
+\!. fn*embed-start \\n[fn*embed-count]
+. rs
+' sp (u;\\n[dn]+\\n[fn@sep-dist]+\\n[.V])
+\!. fn*embed-end
+. nr fn*embed-count +1
+. \}
+. el \{\
+. ev fn
+. @error-recover unclosed diversion within footnote
+. \}
+.\}
+..
+.de fn*embed-start
+.ie '\\n(.z'' \{\
+. fn*start-div
+. ev nf
+. fn*embed-div!\\$1
+. rm fn*embed-div!\\$1
+. ev
+. fn*end-div
+. di fn*null
+.\}
+.el \{\
+\!. fn*embed-start \\$1
+. rs
+.\}
+..
+.de fn*embed-end
+.ie '\\n(.z'fn*null' \{\
+. di
+. rm fn*null
+.\}
+.el \!.fn*embed-end
+..
+.\" It's important that fn@print-sep use up exactly fn@sep-dist vertical space.
+.de fn@print-sep
+.ev fn
+.in 0
+.vs \\n[fn@sep-dist]u
+\D'l 1i 0'
+.br
+.ev
+..
+.\" ***************************
+.\" ******** module kp ********
+.\" ***************************
+.\" Keeps.
+.de KS
+.br
+.di kp*div
+..
+.de KF
+.if !'\\n(.z'' .@error-recover KF while open diversion
+.di kp*fdiv
+.ev k
+.par@reset-env
+.par@reset
+..
+.de KE
+.ie '\\n(.z'kp*div' .kp*end
+.el \{\
+. ie '\\n(.z'kp*fdiv' .kp*fend
+. el .@error KE without KS or KF
+.\}
+..
+.de @div-end!kp*div
+.kp*end
+..
+.de @div-end!kp*fdiv
+.kp*fend
+..
+.de kp*need
+.ie '\\n(.z'' .ds@need \\$1
+.el \!.kp*need \\$1
+..
+.\" end non-floating keep
+.de kp*end
+.br
+.di
+.kp*need \\n[dn]
+.ev nf
+.kp*div
+.ev
+.rm kp*div
+..
+.\" Floating keeps.
+.nr kp@head 0
+.nr kp@tail 0
+.\" end floating keep
+.de kp*fend
+.br
+.ev
+.di
+.ie \\n[.t]-(\\n[.k]>0*1v)>\\n[dn] \{\
+. br
+. ev nf
+. kp*fdiv
+. rm kp*fdiv
+. ev
+.\}
+.el \{\
+. rn kp*fdiv kp*div!\\n[kp@tail]
+. nr kp*ht!\\n[kp@tail] 0\\n[dn]
+. nr kp@tail +1
+.\}
+..
+.\" top of page processing for KF
+.nr kp*doing-top 0
+.de kp@top-hook
+.if !\\n[kp*doing-top] \{\
+. nr kp*doing-top 1
+. kp*do-top
+. nr kp*doing-top 0
+.\}
+..
+.de kp*do-top
+.\" If the first keep won't fit, only force it out if we haven't had a footnote
+.\" and we're at the top of the page.
+.nr kp*force \\n[pg@fn-flag]=0&(\\n[nl]<=\\n[pg@header-bottom])
+.nr kp*fits 1
+.while \\n[kp@tail]>\\n[kp@head]&\\n[kp*fits] \{\
+. ie \\n[.t]>\\n[kp*ht!\\n[kp@head]]:\\n[kp*force] \{\
+. nr kp*force 0
+. \" It's important to advance kp@head before bringing
+. \" back the keep, so that if the last line of the
+. \" last keep springs the bottom of page trap, a new
+. \" page will not be started unnecessarily.
+. rn kp*div!\\n[kp@head] kp*temp
+. nr kp@head +1
+. ev nf
+. kp*temp
+. ev
+. rm kp*temp
+. \}
+. el .nr kp*fits 0
+.\}
+..
+.\" ***************************
+.\" ******** module ds ********
+.\" ***************************
+.\" Displays and non-floating keeps.
+.de DE
+.ds*end!\\n[\\n[.ev]:ds-type]
+.nr \\n[.ev]:ds-type 0
+..
+.de ds@auto-end
+.if \\n[\\n[.ev]:ds-type] \{\
+. @error automatically terminating display
+. DE
+.\}
+..
+.de @div-end!ds*div
+.ie \\n[\\n[.ev]:ds-type] .DE
+.el .ds*end!2
+..
+.de ds*end!0
+.@error DE without DS, ID, CD, LD or BD
+..
+.de LD
+.br
+.nr \\n[.ev]:ds-type 1
+.par@reset
+.nf
+.sp \\n[DD]u
+..
+.de ID
+.LD
+.ie \\n[.$] .in +(n;\\$1)
+.el .in +\\n[DI]u
+..
+.de CD
+.LD
+.ce 9999
+..
+.de RD
+.LD
+.rj 9999
+..
+.de ds*common-end
+.par@reset
+.sp \\n[DD]u
+..
+.als ds*end!1 ds*common-end
+.de BD
+.LD
+.nr \\n[.ev]:ds-type 2
+.di ds*div
+..
+.de ds*end!2
+.br
+.ie '\\n(.z'ds*div' \{\
+. di
+. nf
+. in (u;\\n[.l]-\\n[dl]/2)
+. ds*div
+. rm ds*div
+. ds*common-end
+.\}
+.el .@error-recover mismatched DE
+..
+.de DS
+.br
+.di ds*div
+.ie '\\$1'B' \{\
+. LD
+. nr \\n[.ev]:ds-type 4
+.\}
+.el \{\
+. ie '\\$1'L' .LD
+. el \{\
+. ie '\\$1'C' .CD
+. el \{\
+. ie '\\$1'R' .RD
+. el \{\
+. ie '\\$1'I' .ID \\$2
+. el .ID \\$1
+. \}
+. \}
+. \}
+. nr \\n[.ev]:ds-type 3
+.\}
+..
+.de ds@need
+.if '\\n(.z'' \{\
+. while \\n[.t]<=(\\$1)&(\\n[nl]>\\n[pg@header-bottom]) \{\
+. rs
+' sp \\n[.t]u
+. \}
+.\}
+..
+.de ds*end!3
+.br
+.ie '\\n(.z'ds*div' \{\
+. di
+. ds@need \\n[dn]
+. ev nf
+. ds*div
+. ev
+. rm ds*div
+. ds*common-end
+.\}
+.el .@error-recover mismatched DE
+..
+.de ds*end!4
+.ie '\\n(.z'ds*div' \{\
+. br
+. di
+. nf
+. in (u;\\n[.l]-\\n[dl]/2)
+. ds@need \\n[dn]
+. ds*div
+. rm ds*div
+. ds*common-end
+.\}
+.el .@error-recover mismatched DE
+..
+.\" ****************************
+.\" ******** module par ********
+.\" ****************************
+.\" Paragraph-level formatting.
+.nr PS 10
+.nr LL 6i
+.de par*vs
+.\" If it's too big to be in points, treat it as units.
+.ie (p;\\$1)>=40p .vs (u;\\$1)
+.el .vs (p;\\$1)
+..
+.de par@ab-indent
+.nr 0:li (u;\\n[LL]/12)
+.nr 0:ri \\n[0:li]
+..
+.de par*env-init
+.aln \\n[.ev]:PS PS
+.aln \\n[.ev]:VS VS
+.aln \\n[.ev]:LL LL
+.aln \\n[.ev]:MCLL LL
+.aln \\n[.ev]:LT LT
+.aln \\n[.ev]:MCLT LT
+.aln \\n[.ev]:PI PI
+.aln \\n[.ev]:PD PD
+.ad \\n[par*adj]
+.par@reset-env
+..
+.\" happens when the first page begins
+.de par@init
+.if !rLT .nr LT \\n[LL]
+.if !rFL .nr FL \\n[LL]*5/6
+.if !rVS .nr VS \\n[PS]+2
+.ps \\n[PS]
+.if !rDI .nr DI .5i
+.if !rQI .nr QI 5n
+.if !rPI .nr PI 5n
+.par*vs \\n[VS]
+.if !rPD .nr PD .3v>?\n(.V
+.if !rDD .nr DD .5v>?\n(.V
+.if !dFAM .ds FAM \\n[.fam]
+.nr par*adj \\n[.j]
+.par*env-init
+.ev h
+.par*env-init
+.ev
+.ev fn
+.par*env-init
+.ev
+.ev k
+.par*env-init
+.ev
+.aln 0:MCLL pg@colw
+.aln 0:MCLT pg@colw
+.aln k:MCLL pg@colw
+.aln k:MCLT pg@colw
+.if !rFPS .nr FPS \\n[PS]-2
+.if !rFVS .nr FVS \\n[FPS]+2
+.if !rFI .nr FI 2n
+.if !rFPD .nr FPD \\n[PD]/2
+.aln fn:PS FPS
+.aln fn:VS FVS
+.aln fn:LL FL
+.aln fn:LT FL
+.aln fn:PI FI
+.aln fn:PD FPD
+.aln fn:MCLL pg@fn-colw
+.aln fn:MCLT pg@fn-colw
+..
+.de par@reset-env
+.nr \\n[.ev]:il 0
+.nr \\n[.ev]:li 0
+.nr \\n[.ev]:ri 0
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.nr \\n[.ev]:pli 0
+.nr \\n[.ev]:pri 0
+.nr \\n[.ev]:ds-type 0
+..
+.\" par@reset
+.de par@reset
+.br
+.ce 0
+.rj 0
+.ul 0
+.fi
+.ie \\n[pg@ncols]>1 \{\
+. ll (u;\\n[\\n[.ev]:MCLL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri])
+. lt \\n[\\n[.ev]:MCLT]u
+.\}
+.el \{\
+. ll (u;\\n[\\n[.ev]:LL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri])
+. lt \\n[\\n[.ev]:LT]u
+.\}
+.in (u;\\n[\\n[.ev]:li]+\\n[\\n[.ev]:pli])
+.ft 1
+.fam \\*[FAM]
+.ps \\n[\\n[.ev]:PS]
+.par*vs \\n[\\n[.ev]:VS]
+.ls 1
+.TA
+.hy 14
+..
+.als @RT par@reset
+.\" This can be redefined by the user.
+.de TA
+.ta T 5n
+..
+.de par*start
+.ds@auto-end
+.nr \\n[.ev]:pli \\$1
+.nr \\n[.ev]:pri \\$2
+.par@reset
+.sp \\n[\\n[.ev]:PD]u
+.ne 1v+\\n(.Vu
+..
+.de par@finish
+.nr \\n[.ev]:pli 0
+.nr \\n[.ev]:pri 0
+.par@reset
+..
+.\" normal LP
+.de @LP
+.par*start 0 0
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+..
+.de @PP
+.par*start 0 0
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.ti +\\n[\\n[.ev]:ai]u
+..
+.de @QP
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.par*start \\n[QI] \\n[QI]
+..
+.de @XP
+.par*start \\n[\\n[.ev]:PI] 0
+.ti -\\n[\\n[.ev]:PI]u
+..
+.de @IP
+.if \\n[.$]>1 .nr \\n[.ev]:ai (n;\\$2)
+.par*start \\n[\\n[.ev]:ai] 0
+.if !'\\$1'' \{\
+. \" Divert the label so as to freeze any spaces.
+. di par*label
+. in 0
+. nf
+\&\\$1
+. di
+. in
+. fi
+. chop par*label
+. ti -\\n[\\n[.ev]:ai]u
+. ie \\n[dl]+1n<=\\n[\\n[.ev]:ai] \\*[par*label]\h'|\\n[\\n[.ev]:ai]u'\c
+. el \{\
+\\*[par*label]
+. br
+. \}
+. rm par*label
+.\}
+..
+.de @RS
+.br
+.nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li]
+.nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri]
+.nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai]
+.nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli]
+.nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri]
+.nr \\n[.ev]:il +1
+.nr \\n[.ev]:li +\\n[\\n[.ev]:ai]
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.par@reset
+..
+.de @RE
+.br
+.ie \\n[\\n[.ev]:il] \{\
+. nr \\n[.ev]:il -1
+. nr \\n[.ev]:ai \\n[\\n[.ev]:ai!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:li \\n[\\n[.ev]:li!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:ri \\n[\\n[.ev]:ri!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:pli \\n[\\n[.ev]:pli!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:pri \\n[\\n[.ev]:pri!\\n[\\n[.ev]:il]]
+.\}
+.el .@error unbalanced \\$0
+.par@reset
+..
+.de @QS
+.br
+.nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li]
+.nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri]
+.nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai]
+.nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli]
+.nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri]
+.nr \\n[.ev]:il +1
+.nr \\n[.ev]:li +\\n[QI]
+.nr \\n[.ev]:ri +\\n[QI]
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.par@reset
+..
+.als @QE @RE
+.\" start boxed text
+.de B1
+.br
+.di par*box-div
+.nr \\n[.ev]:li +1n
+.nr \\n[.ev]:ri +1n
+.par@reset
+..
+.de @div-end!par*box-div
+.B2
+..
+.\" end boxed text
+.\" Postpone the drawing of the box until we're in the top-level diversion,
+.\" in case there's a footnote inside the box.
+.de B2
+.ie '\\n(.z'par*box-div' \{\
+. br
+. di
+. ds@need \\n[dn]
+. par*box-mark-top
+. ev nf
+. par*box-div
+. ev
+. nr \\n[.ev]:ri -1n
+. nr \\n[.ev]:li -1n
+. par@finish
+. par*box-draw \\n[.i]u \\n[.l]u
+.\}
+.el .@error B2 without B1
+..
+.de par*box-mark-top
+.ie '\\n[.z]'' .mk par*box-top
+.el \!.par*box-mark-top
+..
+.de par*box-draw
+.ie '\\n[.z]'' \{\
+. nr par*box-in \\n[.i]
+. nr par*box-ll \\n[.l]
+. nr par*box-vpt \\n[.vpt]
+. vpt 0
+. in \\$1
+. ll \\$2
+\v'-1v+.25m'\
+\D'l (u;\\n[.l]-\\n[.i]) 0'\
+\D'l 0 |\\n[par*box-top]u'\
+\D'l -(u;\\n[.l]-\\n[.i]) 0'\
+\D'l 0 -|\\n[par*box-top]u'
+. br
+. sp -1
+. in \\n[par*box-in]u
+. ll \\n[par*box-ll]u
+. vpt \\n[par*box-vpt]
+.\}
+.el \!.par*box-draw \\$1 \\$2
+..
+.de @SH
+.par@finish
+.\" Keep together the heading and the first two lines of the next paragraph.
+.ne 3v+\\n[\\n[.ev]:PD]u+\\n(.Vu
+.sp 1
+.ft B
+..
+.\" TL, AU, and AI are aliased to these in cov*ab-init.
+.de par@TL
+.par@finish
+.sp 1
+.ft B
+.ps +2
+.vs +3p
+.ce 9999
+..
+.de par@AU
+.par@finish
+.sp 1
+.ft I
+.ce 9999
+..
+.de par@AI
+.par@finish
+.sp .5
+.ce 9999
+..
+.\" In paragraph macros.
+.de NL
+.ps \\n[\\n[.ev]:PS]
+..
+.de SM
+.ps -2
+..
+.de LG
+.ps +2
+..
+.de R
+.ft R
+..
+.\" par*define-font-macro macro font
+.de par*define-font-macro
+.de \\$1
+.ie \\\\n[.$] \{\
+. nr par*prev-font \\\\n[.f]
+\&\\\\$3\f[\\$2]\\\\$1\f[\\\\n[par*prev-font]]\\\\$2
+.\}
+.el .ft \\$2
+\\..
+..
+.par*define-font-macro B B
+.par*define-font-macro I I
+.par*define-font-macro BI BI
+.par*define-font-macro CW CR
+.\" underline a word
+.de UL
+\Z'\\$1'\v'.25m'\D'l \w'\\$1'u 0'\v'-.25m'\\$2
+..
+.\" box a word
+.de BX
+.nr par*bxw \w'\\$1'+.4m
+\Z'\v'.25m'\D'l 0 -1m'\D'l \\n[par*bxw]u 0'\D'l 0 1m'\D'l -\\n[par*bxw]u 0''\
+\Z'\h'.2m'\\$1'\
+\h'\\n[par*bxw]u'
+..
+.\" The first time UX is used, put a registered mark after it.
+.ds par*ux-rg \(rg
+.de UX
+\s[\\n[.s]*8u/10u]UNIX\s0\\$1\\*[par*ux-rg]
+.ds par*ux-rg
+..
+.ds par@sup-start \v'-.9m\s'\En[.s]*7u/10u'+.7m'
+.als { par@sup-start
+.ds par@sup-end \v'-.7m\s0+.9m'
+.als } par@sup-end
+.\" footnote paragraphs
+.\" FF is the footnote format
+.nr FF 0
+.\" This can be redefined. It gets a second argument of `no' if the first
+.\" argument was supplied by the user, rather than automatically.
+.de FP
+.br
+.if !d par*fp!\\n[FF] \{\
+. @error unknown footnote format `\\n[FF]'
+. nr FF 0
+.\}
+.ie '\\$2'no' .par*fp!\\n[FF]-no "\\$1"
+.el .par*fp!\\n[FF] "\\$1"
+..
+.de par*fp!0
+.@PP
+\&\\*[par@sup-start]\\$1\\*[par@sup-end]\ \c
+..
+.de par*fp!0-no
+.@PP
+\&\\$1\ \c
+..
+.de par*fp!1
+.@PP
+\&\\$1.\ \c
+..
+.de par*fp!1-no
+.@PP
+\&\\$1\ \c
+..
+.de par*fp!2
+.@LP
+\&\\$1.\ \c
+..
+.de par*fp!2-no
+.@LP
+\&\\$1\ \c
+..
+.de par*fp!3
+.@IP "\\$1." (u;\\n[\\n[.ev]:PI]*2)
+..
+.de par*fp!3-no
+.@IP "\\$1" (u;\\n[\\n[.ev]:PI]*2)
+..
+.\" ***************************
+.\" ******** module nh ********
+.\" ***************************
+.\" Numbered headings.
+.\" nh*hl is the level of the last heading
+.nr nh*hl 0
+.\" numbered heading
+.de @NH
+.ie '\\$1'S' \{\
+. shift
+. nr nh*hl 0
+. while \\n[.$] \{\
+. nr nh*hl +1
+. nr H\\n[nh*hl] 0\\$1
+. shift
+. \}
+. if !\\n[nh*hl] \{\
+. nr H1 1
+. nr nh*hl 1
+. @error missing arguments to .NH S
+. \}
+.\}
+.el \{\
+. nr nh*ohl \\n[nh*hl]
+. ie \\n[.$] \{\
+. nr nh*hl 0\\$1
+. ie \\n[nh*hl]<=0 \{\
+. nr nh*ohl 0
+. nr nh*hl 1
+. \}
+. el \{\
+. if \\n[nh*hl]-\\n[nh*ohl]>1 \
+. @warning .NH \\n[nh*ohl] followed by .NH \\n[nh*hl]
+. \}
+. \}
+. el .nr nh*hl 1
+. while \\n[nh*hl]>\\n[nh*ohl] \{\
+. nr nh*ohl +1
+. nr H\\n[nh*ohl] 0
+. \}
+. nr H\\n[nh*hl] +1
+.\}
+.ds SN
+.nr nh*i 0
+.while \\n[nh*i]<\\n[nh*hl] \{\
+. nr nh*i +1
+. as SN \\n[H\\n[nh*i]].
+.\}
+.SH
+\\*[SN]
+..
+.\" ****************************
+.\" ******** module toc ********
+.\" ****************************
+.\" Table of contents generation.
+.de @XS
+.da toc*div
+.ev h
+.ie \\n[.$] .XA "\\$1"
+.el .XA
+..
+.de @div-end!toc*div
+.XE
+..
+.de XA
+.ie '\\n(.z'toc*div' \{\
+. if d toc*num .toc*end-entry
+. ie \\n[.$] \{\
+. ie '\\$1'no' .ds toc*num
+. el .ds toc*num "\\$1
+. \}
+. el .ds toc*num \\n[PN]
+. LP
+. na
+. ll -8n
+. in (n;0\\$2)
+.\}
+.el .@error XA without XS
+..
+.de XE
+.ie '\\n(.z'toc*div' \{\
+. if d toc*num .toc*end-entry
+. ev
+. di
+.\}
+.el .@error XS without XE
+..
+.de toc*end-entry
+\\a\\t\\*[toc*num]
+.br
+.rm toc*num
+..
+.de PX
+.1C
+.if !'\\$1'no' \{\
+. ce 1
+. ps \\n[PS]+2
+. ft B
+\\*[TOC]
+. ft
+. ps
+.\}
+.nf
+.char \[toc*leader-char] .\h'1m'
+.lc \[toc*leader-char]
+.ta (u;\\n[.l]-\\n[.i]-\w'000') (u;\\n[.l]-\\n[.i])R
+.sp 2
+.toc*div
+.par@reset
+..
+.\" print the table of contents on page i
+.de TC
+.P1
+.pg@begin 1 i
+.PX \\$1
+..
+.\" ****************************
+.\" ******** module eqn ********
+.\" ****************************
+.\" Eqn support.
+.de EQ
+..
+.de EN
+..
+.de @EQ
+.br
+.ds eqn*num "\\$2
+.ie '\\$1'L' .nr eqn*type 0
+.el \{\
+. ie '\\$1'I' .nr eqn*type 1
+. el \{\
+. nr eqn*type 2
+. if !'\\$1'C' .ds eqn*num "\\$1
+. \}
+.\}
+.di eqn*div
+.in 0
+.nf
+..
+.de @div-end!eqn*div
+.@EN
+..
+.\" Note that geqn mark and lineup work correctly in centered equations.
+.de @EN
+.ie !'\\n(.z'eqn*div' .@error-recover mismatched EN
+.el \{\
+. br
+. di
+. nr eqn*have-num 0
+. if !'\\*[eqn*num]'' .nr eqn*have-num 1
+. if \\n[dl]:\\n[eqn*have-num] \{\
+. sp \\n[DD]u
+. par@reset
+. ds eqn*tabs \\n[.tabs]
+. nf
+. ie \\n[dl] \{\
+. ds@need \\n[dn]u-1v+\n[.V]u
+. chop eqn*div
+. ie \\n[eqn*type]=0 \{\
+. ta (u;\\n[.l]-\\n[.i])R
+\\*[eqn*div]\t\\*[eqn*num]
+. \}
+. el \{\
+. ie \\n[eqn*type]=1 .ta \\n[DI]u \
+(u;\\n[.l]-\\n[.i])R
+. el .ta (u;\\n[.l]-\\n[.i]/2)C \
+(u;\\n[.l]-\\n[.i])R
+\t\\*[eqn*div]\t\\*[eqn*num]
+. \}
+. \}
+. el \{\
+. ta (u;\\n[.l]-\\n[.i])R
+\t\\*[eqn*num]
+. \}
+. sp \\n[DD]u
+. fi
+. ta \\*[eqn*tabs]
+. \}
+.\}
+..
+.\" ****************************
+.\" ******** module tbl ********
+.\" ****************************
+.\" Tbl support.
+.nr tbl*have-header 0
+.de TS
+.\" The break is necessary in the case where the first page has not yet begun.
+.br
+.sp \\n[DD]u
+.if '\\$1'H' .di tbl*header-div
+..
+.de tbl@top-hook
+.if \\n[tbl*have-header] \{\
+. ie \\n[.t]-\\n[tbl*header-ht]-1v .tbl*print-header
+. el .sp \\n[.t]u
+.\}
+..
+.de tbl*print-header
+.ev nf
+.tbl*header-div
+.ev
+.mk #T
+..
+.de TH
+.ie '\\n[.z]'tbl*header-div' \{\
+. nr T. 0
+. T#
+. br
+. di
+. ie \\n[dn]+\\n[FM]+\\n[HM]+2v>=\\n[.p] \{\
+. @error ridiculously long table header
+. ds@need \\n[dn]
+. tbl*print-header
+. \}
+. el \{\
+. nr tbl*header-ht \\n[dn]
+. ds@need \\n[dn]u+1v
+. tbl*print-header
+. nr tbl*have-header 1
+. \}
+.\}
+.el .@error-recover .TH without .TS H
+..
+.de @div-end!tbl*header-div
+.TH
+.TE
+..
+.de TE
+.ie '\\n(.z'tbl*header-div' .@error-recover .TS H but no .TH before .TE
+.el \{\
+. nr tbl*have-header 0
+. sp \\n[DD]u
+.\}
+.\" reset tabs
+.TA
+..
+.de tbl@bottom-hook
+.if \\n[tbl*have-header] \{\
+. nr T. 1
+. T#
+.\}
+..
+.de T&
+..
+.\" ****************************
+.\" ******** module pic ********
+.\" ****************************
+.\" Pic support.
+.\" PS height width
+.de PS
+.br
+.sp \\n[DD]u
+.ie \\n[.$]<2 .@error bad arguments to PS (not preprocessed with pic?)
+.el \{\
+. ds@need (u;\\$1)+1v
+. in +(u;\\n[.l]-\\n[.i]-\\$2/2>?0)
+.\}
+..
+.de PE
+.par@reset
+.sp \\n[DD]u+.5m
+..
+.\" ****************************
+.\" ******** module ref ********
+.\" ****************************
+.\" Refer support.
+.de ]-
+.rm [A [B [C [D [E [G [I [J [N [O [P [Q [R [S [T [V
+.rm ref*string
+..
+.\" Other
+.ds ref*spec!0 Q A T1 S V N P I C D O
+.\" Journal article
+.ds ref*spec!1 Q A T2 J S V N P I C D O
+.\" Book
+.ds ref*spec!2 Q A T1 S V P I C D O
+.\" Article within book
+.ds ref*spec!3 Q A T2 B E S V P I C D O
+.\" Tech report
+.ds ref*spec!4 Q A T2 R G P I C D O
+.\" ][ type
+.de ][
+.if r [T \{\
+. als [T1 [T
+. als [T2 [T
+.\}
+.ie d ref*spec!\\$1 .ref*build \\*[ref*spec!\\$1]
+.el \{\
+. @error unknown reference type `\\$1'
+. ref*build \\*[ref*spec!0]
+.\}
+.ref*print
+.rm ref*string
+.rm [F [T1 [T2
+..
+.\" start of reference number
+.ds [. \\*[par@sup-start]
+.\" end of reference number
+.ds .] \\*[par@sup-end]
+.\" period before reference
+.ds <. .
+.\" period after reference
+.ds >. \" empty
+.\" comma before reference
+.ds <, ,
+.\" comma after reference
+.ds >, \" empty
+.\" start collected references
+.de ]<
+.als ref*print ref*end-print
+.SH
+\&\\*[REFERENCES]
+.par@reset
+..
+.\" end collected references
+.de ]>
+.par@finish
+.als ref*print ref*normal-print
+..
+.de ref*normal-print
+.ie d [F .FS "\\*([.\\*([F\\*(.]"
+.el .FS \&
+\\*[ref*string]
+.FE
+..
+.de ref*end-print
+.ie d [F .IP "\\*([F."
+.el .XP
+\\*[ref*string]
+..
+.als ref*print ref*normal-print
+.de ref*build
+.rm ref*string ref*post-punct
+.nr ref*suppress-period 1
+.while \\n[.$] \{\
+. if d [\\$1 \{\
+. ie d ref*add-\\$1 .ref*add-\\$1
+. el .ref*add-dflt \\$1
+. \}
+. shift
+.\}
+.\" now add a final period
+.ie d ref*string \{\
+. if !\\n[ref*suppress-period] .as ref*string .
+. if d ref*post-punct \{\
+. as ref*string "\\*[ref*post-punct]
+. rm ref*post-punct
+. \}
+.\}
+.el .ds ref*string
+..
+.de ref*add-T1
+.ref*field T , "\fI" "" "\fP"
+.if r [T .nr ref*suppress-period \\n([T
+..
+.de ref*add-T2
+.ref*field T , "\\*Q" "" "\\*U"
+.if r [T .nr ref*suppress-period \\n([T
+..
+.de ref*add-P
+.ie \\n([P>0 .ref*field P , "pp. "
+.el .ref*field P , "p. "
+..
+.de ref*add-J
+.ref*field J , \fI "" \fP
+..
+.de ref*add-D
+.ref*field D "" ( )
+..
+.de ref*add-E
+.ref*field E , "ed. "
+..
+.de ref*add-G
+.ref*field G "" ( )
+..
+.de ref*add-B
+.ref*field B "" "in \fI" "" \fP
+..
+.de ref*add-O
+.ref*field O .
+.ie r [O .nr ref*suppress-period \\n([O
+.el .nr ref*suppress-period 1
+..
+.de ref*add-A
+.ref*field A ,
+.if r [A .nr ref*suppress-period \\n([A
+..
+.de ref*add-dflt
+.ref*field \\$1 ,
+..
+.\" First argument is the field letter.
+.\" Second argument is the punctuation character to use to separate this field
+.\" from the previous field.
+.\" Third argument is a string with which to prefix this field.
+.\" Fourth argument is a string with which to postfix this field.
+.\" Fifth argument is a string to add after the punctuation character supplied
+.\" by the next field.
+.de ref*field
+.if d ref*string \{\
+. ie d ref*post-punct \{\
+. as ref*string "\\$2\\*[ref*post-punct] \"
+. rm ref*post-punct
+. \}
+. el .as ref*string "\\$2 \"
+.\}
+.as ref*string "\\$3\\*([\\$1\\$4
+.if \\n[.$]>4 .ds ref*post-punct "\\$5
+.nr ref*suppress-period 0
+..
+.\" ****************************
+.\" ******** module acc ********
+.\" ****************************
+.\" Accents and special characters.
+.ds Q \(lq
+.ds U \(rq
+.ds - \(em
+.\" Characters
+.\" The idea of this definition is for the top of the 3 to be at the x-height.
+.if !c\[yogh] .char \[yogh] \Z'\v'\w'x'*0-\En[rst]u'\s[\En[.s]*8u/10u]\
+\v'\w'3'*0+\En[rst]u'3\s0'\h'\w'\s[\En[.s]*8u/10u]3'u'
+.\" Accents
+.de acc*over-def
+.ds \\$1 \Z'\v'(u;\w'x'*0+\En[rst]-\En[.cht])'\
+\h'(u;-\En[skw]+(-\En[.w]-\w'\\$2'/2)+\En[.csk])'\\$2'
+..
+.de acc*under-def
+.ds \\$1 \Z'\v'\En[.cdp]u'\h'(u;-\En[.w]-\w'\\$2'/2)'\\$2'
+..
+.de acc*slash-def
+.ds \\$1 \Z'\h'(u;-\En[.w]-\w'\\$2'/2)'\
+\v'(u;\En[.cdp]-\En[.cht]+\En[rst]+\En[rsb]/2)'\\$2'
+..
+.de acc*prefix-def
+.ds \\$1 \Z'\h'(u;\w'x'-\w'\\$2'/2)'\\$2'
+..
+.acc*prefix-def ' \'
+.acc*prefix-def ` \`
+.acc*prefix-def ^ ^
+.acc*prefix-def , \(ac
+.acc*prefix-def : \(ad
+.acc*prefix-def ~ ~
+.\" improved accent marks
+.de AM
+.acc*over-def ' \'
+.acc*over-def ` \`
+.acc*over-def ^ ^
+.acc*over-def ~ ~
+.acc*over-def : \(ad
+.acc*over-def v \(ah
+.acc*over-def _ \(a-
+.acc*over-def o \(ao
+.acc*under-def , \(ac
+.acc*under-def . \s[\En[.s]*8u/10u]\v'.2m'.\v'-.2m'\s0
+.acc*under-def hook \(ho
+.acc*slash-def / /
+.char \[hooko] o\\\\*[hook]
+.ds q \[hooko]
+.ds 3 \[yogh]
+.ds D- \(-D\" Icelandic uppercase eth
+.ds d- \(Sd\" Icelandic lowercase eth
+.ds Th \(TP\" Icelandic uppercase thorn
+.ds th \(Tp\" Icelandic lowercase thorn
+.ds 8 \(ss\" German double s
+.ds Ae \(AE\" AE ligature
+.ds ae \(ae\" ae ligature
+.ds Oe \(OE\" OE ligature
+.ds oe \(oe\" oe ligature
+.ds ? \(r?\" upside down ?
+.ds ! \(r!\" upside down !
+..
+.\" Make sure that no blank lines creep in at the end of this file.
diff --git a/gnu/usr.bin/groff/tmac/tmac.tty b/gnu/usr.bin/groff/tmac/tmac.tty
new file mode 100644
index 000000000000..4d5193fe3ab5
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.tty
@@ -0,0 +1,48 @@
+.nr _C \n(.C
+.cp 0
+.nroff
+.ftr CW B
+.ftr C B
+.ftr CR B
+.po 0
+.if c\[char173] .shc \[char173]
+.de tty-char
+.if !c\\$1 .char \\$1 "\\$2
+..
+.if c\(md .tr \(bu\(md
+.tty-char \(bu \z+o
+.tty-char \(14 1/4
+.tty-char \(12 1/2
+.tty-char \(34 3/4
+.tty-char \(ff ff
+.tty-char \(fi fi
+.tty-char \(fl fl
+.tty-char \(Fi ffi
+.tty-char \(Fl ffl
+.tty-char \(<- <-
+.tty-char \(-> ->
+.tty-char \(<> <->
+.tty-char \(em --
+.tty-char \(+- +-
+.tty-char \(co (C)
+.tty-char \(<= <=
+.tty-char \(>= >=
+.tty-char \(!= !=
+.tty-char \(== ==
+.tty-char \(~= ~=
+.tty-char \(sq []
+.tty-char \(lh <=
+.tty-char \(rh =>
+.tty-char \(lA <=
+.tty-char \(rA =>
+.tty-char \(hA <=>
+.tty-char \(rg (R)
+.tty-char \(OE OE
+.tty-char \(oe oe
+.tty-char \(AE AE
+.tty-char \(ae ae
+.tty-char \(an -
+.cp \n(_C
+.\" If you want the character definitions in tmac.tty-char to be loaded
+.\" automatically, remove the `\"' from the next line.
+.\"do mso tmac.tty-char
diff --git a/gnu/usr.bin/groff/tmac/tmac.tty-char b/gnu/usr.bin/groff/tmac/tmac.tty-char
new file mode 100644
index 000000000000..9815e6c0f0e6
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.tty-char
@@ -0,0 +1,196 @@
+.\" This file defines standard troff characters and some groff characters for
+.\" use with -Tascii and -Tlatin1.
+.\"
+.\" These definitions are chosen so that, as far as possible, they:
+.\" - work with both -Tascii and -Tlatin1.
+.\" - work on devices that display only the last overstruck character
+.\" as well as on devices that support overstriking
+.\" - represent the character's graphical shape (not its meaning)
+.\"
+.nr _C \n(.C
+.cp 0
+.de tty-char
+.if !c\\$1 .char \\$1 "\\$2
+..
+.ie c\(a- .ds tty-rn \(a-
+.el .ds tty-rn \v'-1m'_\v'+1m'
+.tty-char \(tm tm
+.tty-char \(rn \*[tty-rn]
+.tty-char \(ua \z|^
+.tty-char \(da \z|v
+.tty-char \(sc S
+.tty-char \(ct \z/c
+.tty-char \(dg \z|-
+.tty-char \(dd \z|=
+.tty-char \(ib (\z=_
+.tty-char \(ip \z=_)
+.tty-char \(sb (=
+.tty-char \(sp =)
+.tty-char \(if oo
+.tty-char \(pt oc
+.tty-char \(es {}
+.tty-char \(ca (^)
+.tty-char \(cu U
+.tty-char \(de o
+.tty-char \(di -:-
+.tty-char \(no ~
+.tty-char \(gr \Z'\*[tty-rn]'V
+.tty-char \(is \z'\z,I
+.tty-char \(mo E
+.tty-char \(pd a
+.tty-char \(sr \e/
+.tty-char \(*C \z_H
+.tty-char \(*D \z_/\z_\e
+.tty-char \(*F \zIO
+.tty-char \(*G |\*[tty-rn]
+.tty-char \(*H \z-O
+.tty-char \(*L /\e
+.tty-char \(*P TT
+.tty-char \(*Q \zIY
+.tty-char \(*S \z_\Z'\*[tty-rn]'>
+.tty-char \(*W \z_O
+.if c\(ss .tty-char \(*b \(ss
+.tty-char \(*b B
+.tty-char \(*a a
+.tty-char \(*c \z,E
+.tty-char \(*d d
+.tty-char \(*e e
+.tty-char \(*f \z|o
+.tty-char \(+f \z|o
+.tty-char \(*g y
+.tty-char \(*h \z-0
+.tty-char \(+h \z-0
+.tty-char \(*i i
+.tty-char \(*k k
+.tty-char \(*l \z>\e
+.tty-char \(*m \z,u
+.tty-char \(*n v
+.tty-char \(*p \z-n
+.tty-char \(+p \z-w
+.tty-char \(*q \z|u
+.tty-char \(*r p
+.tty-char \(*s \z-o
+.tty-char \(*t \z~t
+.tty-char \(*u u
+.tty-char \(*w w
+.tty-char \(*x x
+.tty-char \(*y n
+.tty-char \(*z \z,C
+.tty-char \(ts s
+.\" Definition of \(ss should follow that of \(*b.
+.tty-char \(ss B
+.tty-char \(c* \zO\(mu
+.tty-char \(c+ \zO+
+.tty-char \(AN ^
+.tty-char \(OR v
+.tty-char \(uA \z=^
+.tty-char \(dA \z=v
+.if c\(md .tty-char \(a. \(md
+.tty-char \(Im I
+.tty-char \(Re R
+.tty-char \(/L \z/L
+.tty-char \(/l \z/l
+.tty-char \(%0 %o
+.tty-char \(ao o
+.tty-char \(a" """"
+.tty-char \(ah v
+.tty-char \(ho \(ac
+.tty-char \(/_ \z_/
+.tty-char \(=~ =~
+.tty-char \(Ah N
+.tty-char \(CR _|
+.tty-char \(fa \z-V
+.tty-char \(nm \z/E
+.tty-char \(pp \z_|
+.tty-char \(sd ''
+.tty-char \(st -)
+.tty-char \(te 3
+.if c\(md .tty-char \(tf .\(md.
+.tty-char \(tf .:.
+.tty-char \(wp p
+.tty-char \(~~ ~~
+.tty-char \(Fn \z,f
+.tty-char \(Bq ,,
+.tty-char \(bq ,
+.tty-char \(lz <>
+.\" Latin-1 characters
+.tty-char \(r! \z,i
+.tty-char \(Po \z-L
+.tty-char \(Cs \zox
+.tty-char \(Ye \z=Y
+.tty-char \(bb |
+.tty-char \(ad """"
+.tty-char \(Of \z_a
+.tty-char \(Fo <<
+.tty-char \(a- \*[tty-rn]
+.tty-char \(S2 2
+.tty-char \(S3 3
+.tty-char \(ps 9|
+.tty-char \(md .
+.tty-char \(ac ,
+.tty-char \(S1 1
+.tty-char \(Om \z_o
+.tty-char \(Fc >>
+.tty-char \(r? \z'c
+.tty-char \(`A \z`A
+.tty-char \('A \z'A
+.tty-char \(^A \z^A
+.tty-char \(~A \z~A
+.tty-char \(:A \z"A
+.tty-char \(oA \zoA
+.tty-char \(,C \z,C
+.tty-char \(`E \z`E
+.tty-char \('E \z'E
+.tty-char \(^E \z^E
+.tty-char \(:E \z"E
+.tty-char \(`I \z`I
+.tty-char \('I \z'I
+.tty-char \(^I \z^I
+.tty-char \(:I \z"I
+.tty-char \(-D \z-D
+.tty-char \(~N \z~N
+.tty-char \(`O \z`O
+.tty-char \('O \z'O
+.tty-char \(^O \z^O
+.tty-char \(~O \z~O
+.tty-char \(:O \z"O
+.tty-char \(/O \z/O
+.tty-char \(`U \z`U
+.tty-char \('U \z'U
+.tty-char \(^U \z^U
+.tty-char \(:U \z"U
+.tty-char \('Y \z'Y
+.tty-char \(TP \zIb
+.tty-char \(`a \z`a
+.tty-char \('a \z'a
+.tty-char \(^a \z^a
+.tty-char \(~a \z~a
+.tty-char \(:a \z"a
+.tty-char \(oa \zoa
+.tty-char \(,c \z,c
+.tty-char \(`e \z`e
+.tty-char \('e \z'e
+.tty-char \(^e \z^e
+.tty-char \(:e \z"e
+.tty-char \(`i \z`i
+.tty-char \('i \z'i
+.tty-char \(^i \z^i
+.tty-char \(:i \z"i
+.tty-char \(Sd \z`\z'o
+.tty-char \(~n \z~n
+.tty-char \(`o \z`o
+.tty-char \('o \z'o
+.tty-char \(^o \z^o
+.tty-char \(~o \z~o
+.tty-char \(:o \z"o
+.tty-char \(/o \z/o
+.tty-char \(`u \z`u
+.tty-char \('u \z'u
+.tty-char \(^u \z^u
+.tty-char \(:u \z"u
+.tty-char \('y \z'y
+.tty-char \(Tp \zpb
+.tty-char \(:y \z"y
+.\"tty-char \(:y \ij
+.cp \n(_C
+.do mso tmac.latin1
diff --git a/gnu/usr.bin/groff/tmac/troffrc b/gnu/usr.bin/groff/tmac/troffrc
new file mode 100644
index 000000000000..f3140d8e6abd
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/troffrc
@@ -0,0 +1,24 @@
+.\" Startup file for troff.
+.\" This is tested by pic.
+.nr 0p 0
+.\" Use .do here, so that it works with -C.
+.\" The groff command defines the .X string if the -X option was given.
+.ie r.X .do ds troffrc!ps tmac.Xps
+.el .do ds troffrc!ps tmac.ps
+.do ds troffrc!dvi tmac.dvi
+.do ds troffrc!X75 tmac.X
+.do ds troffrc!X75-12 tmac.X
+.do ds troffrc!X100 tmac.X
+.do ds troffrc!X100-12 tmac.X
+.do ds troffrc!ascii tmac.tty
+.do ds troffrc!latin1 tmac.tty
+.do if d troffrc!\*[.T] \
+. do mso \*[troffrc!\*[.T]]
+.do rm troffrc!ps troffrc!Xps troffrc!dvi troffrc!X75 troffrc!X75-12 \
+troffrc!X100 troffrc!X100-12
+.do tr \[char160]
+.\" Set the hyphenation language to `us'.
+.do hla us
+.\" Load hyphenation patterns from `hyphen.us' (in the tmac directory).
+.do hpf hyphen.us
+.\" Don't let blank lines creep in here.
diff --git a/gnu/usr.bin/groff/troff/Makefile b/gnu/usr.bin/groff/troff/Makefile
new file mode 100644
index 000000000000..2de307ee96fc
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/Makefile
@@ -0,0 +1,38 @@
+# Makefile for troff
+
+PROG= troff
+SRCS= env.cc node.cc input.cc div.cc symbol.cc dictionary.cc reg.cc \
+ number.cc majorminor.cc
+CFLAGS+= -I$(.CURDIR)/../include
+CXXFLAGS+= -I$(.CURDIR)/../include
+LDADD+= $(LIBGROFF) -lm
+DPADD+= $(LIBGROFF) $(LIBMATH)
+tmacdir?= /usr/share/tmac
+
+CLEANFILES+= majorminor.cc
+
+majorminor.cc: $(.CURDIR)/../VERSION
+ @${ECHO} Making $@
+ @-rm -f $@
+ @echo const char \*major_version = \
+ \"`sed -e 's/^\([^.]*\)\..*$$/\1/' $(.CURDIR)/../VERSION`\"\; >$@
+ @echo const char \*minor_version = \
+ \"`sed -e 's/^[^.]*\.\([0-9]*\).*$$/\1/' $(.CURDIR)/../VERSION`\"\; >>$@
+
+install_data: hyphen.us
+ -test -d $(datadir) || mkdir $(datadir)
+ -test -d $(datasubdir) || mkdir $(datasubdir)
+ -test -d $(tmacdir) || mkdir $(tmacdir)
+ -rm -f $(tmacdir)/hyphen.us
+ $(INSTALL_DATA) $(srcdir)/hyphen.us $(tmacdir)/hyphen.us
+
+uninstall_sub:
+ -rm -f $(tmacdir)/hyphen.us
+
+afterinstall:
+ install -c -o bin -g bin -m 444 $(.CURDIR)/hyphen.us \
+ $(DESTDIR)$(tmacdir)/hyphen.us
+
+.include "../../../usr.bin/Makefile.inc"
+.include "../Makefile.cfg"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/troff/TODO b/gnu/usr.bin/groff/troff/TODO
new file mode 100644
index 000000000000..f67707490ed1
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/TODO
@@ -0,0 +1,132 @@
+Give a more helpful error message when the indent is set to a value
+greater than the line-length.
+
+Tracing. This is a pain to implement because requests are responsible
+for reading their own arguments.
+
+Possibly implement -s option (stop every N pages). This functionality
+would be more appropriate in a postprocessor.
+
+Line breaking should be smarter. In particular, it should be possible
+to shrink spaces. Also avoid having a line that's been shrunk a lot
+next to a line that's been stretched a lot. The difficulty is to
+design a mechanism that allows the user complete control over the
+decision of where to break the line.
+
+Provide a mechanism to control the shape of the rag in non-justified
+text.
+
+Add a discretionary break escape sequence. \B'...'...'...' like TeX.
+
+Think about kerning between characters and spaces. (Need to implement
+get_breakpoints and split methods for kern_pair_node class.)
+
+In troff, if .L > 1 when a diversion is reread in no-fill mode, then
+extra line-spacing is added on. Groff at the moment treats line-spacing
+like vertical spacing and doesn't do this.
+
+Suppose \(ch comes from a special font S, and that the current font is
+R. Suppose that R contains a hyphen character and that S does not.
+Suppose that the current font is R. Suppose that \(ch is in a word
+and has a non-zero hyphen-type. Then we ought to be able to hyphenate,
+but we won't be able to because we will look for the hyphen only in
+font S and not in font R.
+
+Variant of tm which doesn't write a newline.
+
+Perhaps the current input level should be accessible in a number register.
+
+Should \w deal with a newline like \X?
+
+Have another look at uses of token::delimiter. Perhaps we need to
+distinguish the case where we want to see if a token could start a
+number, from the case where we want to see if it could occur somewhere
+in a number expression.
+
+Provide a facility like copy thru in pic.
+
+Fancier implementation of font families which doesn't group fonts into
+families purely on the basis of their names.
+
+In the DESC file make the number of fonts optional if they are all on
+one line.
+
+Number register to give the diversion level.
+
+Time various alternative implementations of scale (both in font.c and
+number.c). On a sparc it's faster to always do it in floating point.
+
+Devise a more compact representation for the hyphenation patterns trie.
+
+Have a per-environment parameter to increase letter-spacing.
+
+Number register to return character height.
+
+Number register to return character slant.
+
+Request to set character height.
+
+Request to set character slant.
+
+Provide some way to upcase or downcase strings.
+
+Support non-uniformly scaleable fonts. Perhaps associate a suffix with
+a particular range of sizes. eg
+ sizesuffix .display 14-512
+Then is you ask for R at pointsize 16, groff will first look for
+R.display and then R. Probably necessary to be able to specify a
+separate unitwidth for each sizesuffix (eg. for X).
+
+Request to copy an environment into the current environment.
+
+Variant of `.it' for which a line interrupted with \c counts as one
+input line.
+
+Make it possible to suppress hyphenation on a word-by-word basis.
+(Perhaps store hyphenation flags in tfont.)
+
+Possibly allow multiple simultaneous input line traps.
+
+Unpaddable, breakable space escape sequence.
+
+Support hanging punctuation.
+
+In justified text, if the last line of a paragraph is only a little
+bit short it might be desirable to justify the line. Allow the user
+control over this.
+
+Have a blank line macro like the end macro. When a blank line macro
+has been set, then a blank line causes the blank line macro to be
+called rather than doing the equivalent of .sp.
+
+The pm request could print where the macro was defined. Also could
+optionally print the contents of a macro.
+
+Provide some way to round numbers to multiples of the current
+horizontal or vertical resolution.
+
+Better string-processing support (substring, length, search).
+
+Generalized ligatures.
+
+Provide some way for a macro to tell whether it was called with `'' or
+`.'. This would be useful for implementing a tracing macro packge.
+
+Request to remove an environment. (Maintain a count of the references
+to the environment from the environment table, environment dictionary
+or environment stack.)
+
+Perhaps in the nr request a leading `-' should only be recognized as a
+decrement when it's at the same input level as the request.
+
+Don't ever change a charinfo. Create new variants instead and chain
+them together.
+
+Make it possible to tr characters onto \~.
+
+Unix troff appears to read the first character of a request name in
+copy mode. Should we do the same?
+
+Number register giving name of end macro.
+
+More thorough range checking.
diff --git a/gnu/usr.bin/groff/troff/charinfo.h b/gnu/usr.bin/groff/troff/charinfo.h
new file mode 100644
index 000000000000..29a5b853d4b5
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/charinfo.h
@@ -0,0 +1,165 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+class macro;
+
+class charinfo {
+ static int next_index;
+ charinfo *translation;
+ int index;
+ int number;
+ macro *mac;
+ unsigned char special_translation;
+ unsigned char hyphenation_code;
+ unsigned char flags;
+ unsigned char ascii_code;
+ char not_found;
+ char transparent_translate; // non-zero means translation applies to
+ // to transparent throughput
+public:
+ enum {
+ ENDS_SENTENCE = 1,
+ BREAK_BEFORE = 2,
+ BREAK_AFTER = 4,
+ OVERLAPS_HORIZONTALLY = 8,
+ OVERLAPS_VERTICALLY = 16,
+ TRANSPARENT = 32,
+ NUMBERED = 64
+ };
+ enum {
+ TRANSLATE_NONE,
+ TRANSLATE_SPACE,
+ TRANSLATE_DUMMY,
+ TRANSLATE_STRETCHABLE_SPACE,
+ TRANSLATE_HYPHEN_INDICATOR
+ };
+ symbol nm;
+ charinfo(symbol s);
+ int get_index();
+ int ends_sentence();
+ int overlaps_vertically();
+ int overlaps_horizontally();
+ int can_break_before();
+ int can_break_after();
+ int transparent();
+ unsigned char get_hyphenation_code();
+ unsigned char get_ascii_code();
+ void set_hyphenation_code(unsigned char);
+ void set_ascii_code(unsigned char);
+ charinfo *get_translation(int = 0);
+ void set_translation(charinfo *, int);
+ void set_flags(unsigned char);
+ void set_special_translation(int, int);
+ int get_special_translation(int = 0);
+ macro *set_macro(macro *);
+ macro *get_macro();
+ int first_time_not_found();
+ void set_number(int);
+ int get_number();
+ int numbered();
+};
+
+charinfo *get_charinfo(symbol);
+extern charinfo *charset_table[];
+charinfo *get_charinfo_by_number(int);
+
+inline int charinfo::overlaps_horizontally()
+{
+ return flags & OVERLAPS_HORIZONTALLY;
+}
+
+inline int charinfo::overlaps_vertically()
+{
+ return flags & OVERLAPS_VERTICALLY;
+}
+
+inline int charinfo::can_break_before()
+{
+ return flags & BREAK_BEFORE;
+}
+
+inline int charinfo::can_break_after()
+{
+ return flags & BREAK_AFTER;
+}
+
+inline int charinfo::ends_sentence()
+{
+ return flags & ENDS_SENTENCE;
+}
+
+inline int charinfo::transparent()
+{
+ return flags & TRANSPARENT;
+}
+
+inline int charinfo::numbered()
+{
+ return flags & NUMBERED;
+}
+
+inline charinfo *charinfo::get_translation(int transparent_throughput)
+{
+ return (transparent_throughput && !transparent_translate
+ ? 0
+ : translation);
+}
+
+inline unsigned char charinfo::get_hyphenation_code()
+{
+ return hyphenation_code;
+}
+
+inline unsigned char charinfo::get_ascii_code()
+{
+ return ascii_code;
+}
+
+inline void charinfo::set_flags(unsigned char c)
+{
+ flags = c;
+}
+
+inline int charinfo::get_index()
+{
+ return index;
+}
+
+inline int charinfo::get_special_translation(int transparent_throughput)
+{
+ return (transparent_throughput && !transparent_translate
+ ? TRANSLATE_NONE
+ : special_translation);
+}
+
+inline macro *charinfo::get_macro()
+{
+ return mac;
+}
+
+inline int charinfo::first_time_not_found()
+{
+ if (not_found)
+ return 0;
+ else {
+ not_found = 1;
+ return 1;
+ }
+}
diff --git a/gnu/usr.bin/groff/troff/column.cc b/gnu/usr.bin/groff/troff/column.cc
new file mode 100644
index 000000000000..230e544e0d0c
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/column.cc
@@ -0,0 +1,732 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef COLUMN
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "div.h"
+#include "reg.h"
+#include "stringclass.h"
+
+void output_file::vjustify(vunits, symbol)
+{
+ // do nothing
+}
+
+struct justification_spec;
+struct output_line;
+
+class column : public output_file {
+private:
+ output_file *out;
+ vunits bottom;
+ output_line *col;
+ output_line **tail;
+ void add_output_line(output_line *);
+ void begin_page(int pageno, vunits page_length);
+ void flush();
+ void print_line(hunits, vunits, node *, vunits, vunits);
+ void vjustify(vunits, symbol);
+ void transparent_char(unsigned char c);
+ void copy_file(hunits, vunits, const char *);
+ int is_printing();
+ void check_bottom();
+public:
+ column();
+ ~column();
+ void start();
+ void output();
+ void justify(const justification_spec &);
+ void trim();
+ void reset();
+ vunits get_bottom();
+ vunits get_last_extra_space();
+ int is_active() { return out != 0; }
+};
+
+column *the_column = 0;
+
+struct transparent_output_line;
+struct vjustify_output_line;
+
+class output_line {
+ output_line *next;
+public:
+ output_line();
+ virtual ~output_line();
+ virtual void output(output_file *, vunits);
+ virtual transparent_output_line *as_transparent_output_line();
+ virtual vjustify_output_line *as_vjustify_output_line();
+ virtual vunits distance();
+ virtual vunits height();
+ virtual void reset();
+ virtual vunits extra_space(); // post line
+ friend class column;
+ friend class justification_spec;
+};
+
+class position_output_line : public output_line {
+ vunits dist;
+public:
+ position_output_line(vunits);
+ vunits distance();
+};
+
+class node_output_line : public position_output_line {
+ node *nd;
+ hunits page_offset;
+ vunits before;
+ vunits after;
+public:
+ node_output_line(vunits, node *, hunits, vunits, vunits);
+ ~node_output_line();
+ void output(output_file *, vunits);
+ vunits height();
+ vunits extra_space();
+};
+
+class vjustify_output_line : public position_output_line {
+ vunits current;
+ symbol typ;
+public:
+ vjustify_output_line(vunits dist, symbol);
+ vunits height();
+ vjustify_output_line *as_vjustify_output_line();
+ void vary(vunits amount);
+ void reset();
+ symbol type();
+};
+
+inline symbol vjustify_output_line::type()
+{
+ return typ;
+}
+
+class copy_file_output_line : public position_output_line {
+ symbol filename;
+ hunits hpos;
+public:
+ copy_file_output_line(vunits, const char *, hunits);
+ void output(output_file *, vunits);
+};
+
+class transparent_output_line : public output_line {
+ string buf;
+public:
+ transparent_output_line();
+ void output(output_file *, vunits);
+ void append_char(unsigned char c);
+ transparent_output_line *as_transparent_output_line();
+};
+
+output_line::output_line() : next(0)
+{
+}
+
+output_line::~output_line()
+{
+}
+
+void output_line::reset()
+{
+}
+
+transparent_output_line *output_line::as_transparent_output_line()
+{
+ return 0;
+}
+
+vjustify_output_line *output_line::as_vjustify_output_line()
+{
+ return 0;
+}
+
+void output_line::output(output_file *, vunits)
+{
+}
+
+vunits output_line::distance()
+{
+ return V0;
+}
+
+vunits output_line::height()
+{
+ return V0;
+}
+
+vunits output_line::extra_space()
+{
+ return V0;
+}
+
+position_output_line::position_output_line(vunits d)
+: dist(d)
+{
+}
+
+vunits position_output_line::distance()
+{
+ return dist;
+}
+
+node_output_line::node_output_line(vunits d, node *n, hunits po, vunits b, vunits a)
+: position_output_line(d), nd(n), page_offset(po), before(b), after(a)
+{
+}
+
+node_output_line::~node_output_line()
+{
+ delete_node_list(nd);
+}
+
+void node_output_line::output(output_file *out, vunits pos)
+{
+ out->print_line(page_offset, pos, nd, before, after);
+ nd = 0;
+}
+
+vunits node_output_line::height()
+{
+ return after;
+}
+
+vunits node_output_line::extra_space()
+{
+ return after;
+}
+
+vjustify_output_line::vjustify_output_line(vunits d, symbol t)
+: position_output_line(d), typ(t)
+{
+}
+
+void vjustify_output_line::reset()
+{
+ current = V0;
+}
+
+vunits vjustify_output_line::height()
+{
+ return current;
+}
+
+vjustify_output_line *vjustify_output_line::as_vjustify_output_line()
+{
+ return this;
+}
+
+inline void vjustify_output_line::vary(vunits amount)
+{
+ current += amount;
+}
+
+transparent_output_line::transparent_output_line()
+{
+}
+
+transparent_output_line *transparent_output_line::as_transparent_output_line()
+{
+ return this;
+}
+
+void transparent_output_line::append_char(unsigned char c)
+{
+ assert(c != 0);
+ buf += c;
+}
+
+void transparent_output_line::output(output_file *out, vunits)
+{
+ int len = buf.length();
+ for (int i = 0; i < len; i++)
+ out->transparent_char(buf[i]);
+}
+
+copy_file_output_line::copy_file_output_line(vunits d, const char *f, hunits h)
+: position_output_line(d), hpos(h), filename(f)
+{
+}
+
+void copy_file_output_line::output(output_file *out, vunits pos)
+{
+ out->copy_file(hpos, pos, filename.contents());
+}
+
+column::column()
+: bottom(V0), col(0), tail(&col), out(0)
+{
+}
+
+column::~column()
+{
+ assert(out != 0);
+ error("automatically outputting column before exiting");
+ output();
+ delete the_output;
+}
+
+void column::start()
+{
+ assert(out == 0);
+ if (!the_output)
+ init_output();
+ assert(the_output != 0);
+ out = the_output;
+ the_output = this;
+}
+
+void column::begin_page(int pageno, vunits page_length)
+{
+ assert(out != 0);
+ if (col) {
+ error("automatically outputting column before beginning next page");
+ output();
+ the_output->begin_page(pageno, page_length);
+ }
+ else
+ out->begin_page(pageno, page_length);
+
+}
+
+void column::flush()
+{
+ assert(out != 0);
+ out->flush();
+}
+
+int column::is_printing()
+{
+ assert(out != 0);
+ return out->is_printing();
+}
+
+vunits column::get_bottom()
+{
+ return bottom;
+}
+
+void column::add_output_line(output_line *ln)
+{
+ *tail = ln;
+ bottom += ln->distance();
+ bottom += ln->height();
+ ln->next = 0;
+ tail = &(*tail)->next;
+}
+
+void column::print_line(hunits page_offset, vunits pos, node *nd,
+ vunits before, vunits after)
+{
+ assert(out != 0);
+ add_output_line(new node_output_line(pos - bottom, nd, page_offset, before, after));
+}
+
+void column::vjustify(vunits pos, symbol typ)
+{
+ assert(out != 0);
+ add_output_line(new vjustify_output_line(pos - bottom, typ));
+}
+
+void column::transparent_char(unsigned char c)
+{
+ assert(out != 0);
+ transparent_output_line *tl = 0;
+ if (*tail)
+ tl = (*tail)->as_transparent_output_line();
+ if (!tl) {
+ tl = new transparent_output_line;
+ add_output_line(tl);
+ }
+ tl->append_char(c);
+}
+
+void column::copy_file(hunits page_offset, vunits pos, const char *filename)
+{
+ assert(out != 0);
+ add_output_line(new copy_file_output_line(pos - bottom, filename, page_offset));
+}
+
+void column::trim()
+{
+ output_line **spp = 0;
+ for (output_line **pp = &col; *pp; pp = &(*pp)->next)
+ if ((*pp)->as_vjustify_output_line() == 0)
+ spp = 0;
+ else if (!spp)
+ spp = pp;
+ if (spp) {
+ output_line *ln = *spp;
+ *spp = 0;
+ tail = spp;
+ while (ln) {
+ output_line *tem = ln->next;
+ bottom -= ln->distance();
+ bottom -= ln->height();
+ delete ln;
+ ln = tem;
+ }
+ }
+}
+
+void column::reset()
+{
+ bottom = V0;
+ for (output_line *ln = col; ln; ln = ln->next) {
+ bottom += ln->distance();
+ ln->reset();
+ bottom += ln->height();
+ }
+}
+
+void column::check_bottom()
+{
+ vunits b;
+ for (output_line *ln = col; ln; ln = ln->next) {
+ b += ln->distance();
+ b += ln->height();
+ }
+ assert(b == bottom);
+}
+
+void column::output()
+{
+ assert(out != 0);
+ vunits vpos(V0);
+ output_line *ln = col;
+ while (ln) {
+ vpos += ln->distance();
+ ln->output(out, vpos);
+ vpos += ln->height();
+ output_line *tem = ln->next;
+ delete ln;
+ ln = tem;
+ }
+ tail = &col;
+ bottom = V0;
+ col = 0;
+ the_output = out;
+ out = 0;
+}
+
+vunits column::get_last_extra_space()
+{
+ if (!col)
+ return V0;
+ for (output_line *p = col; p->next; p = p->next)
+ ;
+ return p->extra_space();
+}
+
+class justification_spec {
+ vunits height;
+ symbol *type;
+ vunits *amount;
+ int n;
+ int maxn;
+public:
+ justification_spec(vunits);
+ ~justification_spec();
+ void append(symbol t, vunits v);
+ void justify(output_line *, vunits *bottomp) const;
+};
+
+justification_spec::justification_spec(vunits h)
+: height(h), n(0), maxn(10)
+{
+ type = new symbol[maxn];
+ amount = new vunits[maxn];
+}
+
+justification_spec::~justification_spec()
+{
+ a_delete type;
+ a_delete amount;
+}
+
+void justification_spec::append(symbol t, vunits v)
+{
+ if (v <= V0) {
+ if (v < V0)
+ warning(WARN_RANGE,
+ "maximum space for vertical justification must not be negative");
+ else
+ warning(WARN_RANGE,
+ "maximum space for vertical justification must not be zero");
+ return;
+ }
+ if (n >= maxn) {
+ maxn *= 2;
+ symbol *old_type = type;
+ type = new symbol[maxn];
+ int i;
+ for (i = 0; i < n; i++)
+ type[i] = old_type[i];
+ a_delete old_type;
+ vunits *old_amount = amount;
+ amount = new vunits[maxn];
+ for (i = 0; i < n; i++)
+ amount[i] = old_amount[i];
+ a_delete old_amount;
+ }
+ assert(n < maxn);
+ type[n] = t;
+ amount[n] = v;
+ n++;
+}
+
+void justification_spec::justify(output_line *col, vunits *bottomp) const
+{
+ if (*bottomp >= height)
+ return;
+ vunits total;
+ output_line *p;
+ for (p = col; p; p = p->next) {
+ vjustify_output_line *sp = p->as_vjustify_output_line();
+ if (sp) {
+ symbol t = sp->type();
+ for (int i = 0; i < n; i++) {
+ if (t == type[i])
+ total += amount[i];
+ }
+ }
+ }
+ vunits gap = height - *bottomp;
+ for (p = col; p; p = p->next) {
+ vjustify_output_line *sp = p->as_vjustify_output_line();
+ if (sp) {
+ symbol t = sp->type();
+ for (int i = 0; i < n; i++) {
+ if (t == type[i]) {
+ if (total <= gap) {
+ sp->vary(amount[i]);
+ gap -= amount[i];
+ }
+ else {
+ // gap < total
+ vunits v = scale(amount[i], gap, total);
+ sp->vary(v);
+ gap -= v;
+ }
+ total -= amount[i];
+ }
+ }
+ }
+ }
+ assert(total == V0);
+ *bottomp = height - gap;
+}
+
+void column::justify(const justification_spec &js)
+{
+ check_bottom();
+ js.justify(col, &bottom);
+ check_bottom();
+}
+
+void column_justify()
+{
+ vunits height;
+ if (!the_column->is_active())
+ error("can't justify column - column not active");
+ else if (get_vunits(&height, 'v')) {
+ justification_spec js(height);
+ symbol nm = get_long_name(1);
+ if (!nm.is_null()) {
+ vunits v;
+ if (get_vunits(&v, 'v')) {
+ js.append(nm, v);
+ int err = 0;
+ while (has_arg()) {
+ nm = get_long_name(1);
+ if (nm.is_null()) {
+ err = 1;
+ break;
+ }
+ if (!get_vunits(&v, 'v')) {
+ err = 1;
+ break;
+ }
+ js.append(nm, v);
+ }
+ if (!err)
+ the_column->justify(js);
+ }
+ }
+ }
+ skip_line();
+}
+
+void column_start()
+{
+ if (the_column->is_active())
+ error("can't start column - column already active");
+ else
+ the_column->start();
+ skip_line();
+}
+
+void column_output()
+{
+ if (!the_column->is_active())
+ error("can't output column - column not active");
+ else
+ the_column->output();
+ skip_line();
+}
+
+void column_trim()
+{
+ if (!the_column->is_active())
+ error("can't trim column - column not active");
+ else
+ the_column->trim();
+ skip_line();
+}
+
+void column_reset()
+{
+ if (!the_column->is_active())
+ error("can't reset column - column not active");
+ else
+ the_column->reset();
+ skip_line();
+}
+
+class column_bottom_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *column_bottom_reg::get_string()
+{
+ return itoa(the_column->get_bottom().to_units());
+}
+
+class column_extra_space_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *column_extra_space_reg::get_string()
+{
+ return itoa(the_column->get_last_extra_space().to_units());
+}
+
+class column_active_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *column_active_reg::get_string()
+{
+ return the_column->is_active() ? "1" : "0";
+}
+
+static int no_vjustify_mode = 0;
+
+class vjustify_node : public node {
+ symbol typ;
+public:
+ vjustify_node(symbol);
+ int reread(int *);
+ const char *type();
+ int same(node *);
+ node *copy();
+};
+
+vjustify_node::vjustify_node(symbol t)
+: typ(t)
+{
+}
+
+node *vjustify_node::copy()
+{
+ return new vjustify_node(typ);
+}
+
+const char *vjustify_node::type()
+{
+ return "vjustify_node";
+}
+
+int vjustify_node::same(node *nd)
+{
+ return typ == ((vjustify_node *)nd)->typ;
+}
+
+int vjustify_node::reread(int *bolp)
+{
+ curdiv->vjustify(typ);
+ *bolp = 1;
+ return 1;
+}
+
+void macro_diversion::vjustify(symbol type)
+{
+ if (!no_vjustify_mode)
+ mac->append(new vjustify_node(type));
+}
+
+void top_level_diversion::vjustify(symbol type)
+{
+ if (no_space_mode || no_vjustify_mode)
+ return;
+ assert(first_page_begun); // I'm not sure about this.
+ the_output->vjustify(vertical_position, type);
+}
+
+void no_vjustify()
+{
+ skip_line();
+ no_vjustify_mode = 1;
+}
+
+void restore_vjustify()
+{
+ skip_line();
+ no_vjustify_mode = 0;
+}
+
+void init_column_requests()
+{
+ the_column = new column;
+ init_request("cols", column_start);
+ init_request("colo", column_output);
+ init_request("colj", column_justify);
+ init_request("colr", column_reset);
+ init_request("colt", column_trim);
+ init_request("nvj", no_vjustify);
+ init_request("rvj", restore_vjustify);
+ number_reg_dictionary.define(".colb", new column_bottom_reg);
+ number_reg_dictionary.define(".colx", new column_extra_space_reg);
+ number_reg_dictionary.define(".cola", new column_active_reg);
+ number_reg_dictionary.define(".nvj",
+ new constant_int_reg(&no_vjustify_mode));
+}
+
+#endif /* COLUMN */
diff --git a/gnu/usr.bin/groff/troff/dictionary.cc b/gnu/usr.bin/groff/troff/dictionary.cc
new file mode 100644
index 000000000000..5437a1a1ed30
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/dictionary.cc
@@ -0,0 +1,211 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+
+// is `p' a good size for a hash table
+
+static int is_good_size(int p)
+{
+ const int SMALL = 10;
+ for (unsigned i = 2; i <= p/2; i++)
+ if (p % i == 0)
+ return 0;
+ for (i = 0x100; i != 0; i <<= 8)
+ if (i % p <= SMALL || i % p > p - SMALL)
+ return 0;
+ return 1;
+}
+
+dictionary::dictionary(int n) : threshold(0.5), factor(1.5), used(0), size(n)
+{
+ table = new association[n];
+ for (int i = 0; i < n; i++)
+ table[i].v = 0;
+}
+
+// see Knuth, Sorting and Searching, p518, Algorithm L
+// we can't use double-hashing because we want a remove function
+
+void *dictionary::lookup(symbol s, void *v)
+{
+ for (int i = int(s.hash() % size);
+ table[i].v != 0;
+ i == 0 ? i = size - 1: --i)
+ if (s == table[i].s) {
+ if (v != 0) {
+ void *temp = table[i].v;
+ table[i].v = v;
+ return temp;
+ }
+ else
+ return table[i].v;
+ }
+ if (v == 0)
+ return 0;
+ ++used;
+ table[i].v = v;
+ table[i].s = s;
+ if ((double)used/(double)size >= threshold || used + 1 >= size) {
+ int old_size = size;
+ size = int(size*factor);
+ while (!is_good_size(size))
+ ++size;
+ association *old_table = table;
+ table = new association[size];
+ used = 0;
+ for (i = 0; i < old_size; i++)
+ if (old_table[i].v != 0)
+ (void)lookup(old_table[i].s, old_table[i].v);
+ a_delete old_table;
+ }
+ return 0;
+}
+
+void *dictionary::lookup(const char *p)
+{
+ symbol s(p, MUST_ALREADY_EXIST);
+ if (s.is_null())
+ return 0;
+ else
+ return lookup(s);
+}
+
+// see Knuth, Sorting and Searching, p527, Algorithm R
+
+void *dictionary::remove(symbol s)
+{
+ // this relies on the fact that we are using linear probing
+ for (int i = int(s.hash() % size);
+ table[i].v != 0 && s != table[i].s;
+ i == 0 ? i = size - 1: --i)
+ ;
+ void *p = table[i].v;
+ while (table[i].v != 0) {
+ table[i].v = 0;
+ int j = i;
+ int r;
+ do {
+ --i;
+ if (i < 0)
+ i = size - 1;
+ if (table[i].v == 0)
+ break;
+ r = int(table[i].s.hash() % size);
+ } while ((i <= r && r < j) || (j < i && i <= r));
+ table[j] = table[i];
+ }
+ if (p != 0)
+ --used;
+ return p;
+}
+
+dictionary_iterator::dictionary_iterator(dictionary &d) : dict(&d), i(0)
+{
+}
+
+int dictionary_iterator::get(symbol *sp, void **vp)
+{
+ for (; i < dict->size; i++)
+ if (dict->table[i].v) {
+ *sp = dict->table[i].s;
+ *vp = dict->table[i].v;
+ i++;
+ return 1;
+ }
+ return 0;
+}
+
+object_dictionary_iterator::object_dictionary_iterator(object_dictionary &od)
+ : di(od.d)
+{
+}
+
+object::object() : rcount(0)
+{
+}
+
+object::~object()
+{
+}
+
+void object::add_reference()
+{
+ rcount += 1;
+}
+
+void object::remove_reference()
+{
+ if (--rcount == 0)
+ delete this;
+}
+
+object_dictionary::object_dictionary(int n) : d(n)
+{
+}
+
+object *object_dictionary::lookup(symbol nm)
+{
+ return (object *)d.lookup(nm);
+}
+
+void object_dictionary::define(symbol nm, object *obj)
+{
+ obj->add_reference();
+ obj = (object *)d.lookup(nm, obj);
+ if (obj)
+ obj->remove_reference();
+}
+
+void object_dictionary::rename(symbol oldnm, symbol newnm)
+{
+ object *obj = (object *)d.remove(oldnm);
+ if (obj) {
+ obj = (object *)d.lookup(newnm, obj);
+ if (obj)
+ obj->remove_reference();
+ }
+}
+
+void object_dictionary::remove(symbol nm)
+{
+ object *obj = (object *)d.remove(nm);
+ if (obj)
+ obj->remove_reference();
+}
+
+// Return non-zero if oldnm was defined.
+
+int object_dictionary::alias(symbol newnm, symbol oldnm)
+{
+ object *obj = (object *)d.lookup(oldnm);
+ if (obj) {
+ obj->add_reference();
+ obj = (object *)d.lookup(newnm, obj);
+ if (obj)
+ obj->remove_reference();
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/gnu/usr.bin/groff/troff/dictionary.h b/gnu/usr.bin/groff/troff/dictionary.h
new file mode 100644
index 000000000000..47d6d59926e4
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/dictionary.h
@@ -0,0 +1,92 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+
+// there is no distinction between name with no value and name with NULL value
+// null names are not permitted (they will be ignored).
+
+struct association {
+ symbol s;
+ void *v;
+ association() : v(0) {}
+};
+
+class dictionary;
+
+class dictionary_iterator {
+ dictionary *dict;
+ int i;
+public:
+ dictionary_iterator(dictionary &);
+ int get(symbol *, void **);
+};
+
+class dictionary {
+ int size;
+ int used;
+ double threshold;
+ double factor;
+ association *table;
+ void rehash(int);
+public:
+ dictionary(int);
+ void *lookup(symbol s, void *v=0); // returns value associated with key
+ void *lookup(const char *);
+ // if second parameter not NULL, value will be replaced
+ void *remove(symbol);
+ friend class dictionary_iterator;
+};
+
+class object {
+ int rcount;
+ public:
+ object();
+ virtual ~object();
+ void add_reference();
+ void remove_reference();
+};
+
+class object_dictionary;
+
+class object_dictionary_iterator {
+ dictionary_iterator di;
+public:
+ object_dictionary_iterator(object_dictionary &);
+ int get(symbol *, object **);
+};
+
+class object_dictionary {
+ dictionary d;
+public:
+ object_dictionary(int);
+ object *lookup(symbol nm);
+ void define(symbol nm, object *obj);
+ void rename(symbol oldnm, symbol newnm);
+ void remove(symbol nm);
+ int alias(symbol newnm, symbol oldnm);
+ friend class object_dictionary_iterator;
+};
+
+
+inline int object_dictionary_iterator::get(symbol *sp, object **op)
+{
+ return di.get(sp, (void **)op);
+}
diff --git a/gnu/usr.bin/groff/troff/div.cc b/gnu/usr.bin/groff/troff/div.cc
new file mode 100644
index 000000000000..c30001f2ae8f
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/div.cc
@@ -0,0 +1,1124 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+// diversions
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "div.h"
+#include "reg.h"
+
+int exit_started = 0; // the exit process has started
+int done_end_macro = 0; // the end macro (if any) has finished
+int seen_last_page_ejector = 0; // seen the LAST_PAGE_EJECTOR cookie
+static int began_page_in_end_macro = 0; // a new page was begun during the end macro
+
+static int last_post_line_extra_space = 0; // needed for \n(.a
+static int nl_reg_contents = -1;
+static int dl_reg_contents = 0;
+static int dn_reg_contents = 0;
+static int vertical_position_traps_flag = 1;
+static vunits truncated_space;
+static vunits needed_space;
+
+diversion::diversion(symbol s)
+: nm(s), prev(0), vertical_position(V0), marked_place(V0), high_water_mark(V0)
+{
+}
+
+struct vertical_size {
+ vunits pre_extra, post_extra, pre, post;
+ vertical_size(vunits vs, int ls);
+};
+
+vertical_size::vertical_size(vunits vs, int ls)
+: pre_extra(V0), post_extra(V0), pre(vs)
+{
+ if (ls > 1)
+ post = vs*(ls - 1);
+ else
+ post = V0;
+}
+
+void node::set_vertical_size(vertical_size *)
+{
+}
+
+void extra_size_node::set_vertical_size(vertical_size *v)
+{
+ if (n < V0) {
+ if (-n > v->pre_extra)
+ v->pre_extra = -n;
+ }
+ else if (n > v->post_extra)
+ v->post_extra = n;
+}
+
+void vertical_size_node::set_vertical_size(vertical_size *v)
+{
+ if (n < V0)
+ v->pre = -n;
+ else
+ v->post = n;
+}
+
+top_level_diversion *topdiv;
+
+diversion *curdiv;
+
+void do_divert(int append)
+{
+ tok.skip();
+ symbol nm = get_name();
+ if (nm.is_null()) {
+ if (curdiv->prev) {
+ diversion *temp = curdiv;
+ curdiv = curdiv->prev;
+ delete temp;
+ }
+ else
+ warning(WARN_DI, "diversion stack underflow");
+ }
+ else {
+ macro_diversion *md = new macro_diversion(nm, append);
+ md->prev = curdiv;
+ curdiv = md;
+ }
+ skip_line();
+}
+
+void divert()
+{
+ do_divert(0);
+}
+
+void divert_append()
+{
+ do_divert(1);
+}
+
+void diversion::need(vunits n)
+{
+ vunits d = distance_to_next_trap();
+ if (d < n) {
+ space(d, 1);
+ truncated_space = -d;
+ needed_space = n;
+ }
+}
+
+macro_diversion::macro_diversion(symbol s, int append)
+: diversion(s), max_width(H0)
+{
+#if 0
+ if (append) {
+ /* We don't allow recursive appends eg:
+
+ .da a
+ .a
+ .di
+
+ This causes an infinite loop in troff anyway.
+ This is because the user could do
+
+ .as a foo
+
+ in the diversion, and this would mess things up royally,
+ since there would be two things appending to the same
+ macro_header.
+ To make it work, we would have to copy the _contents_
+ of the macro into which we were diverting; this doesn't
+ strike me as worthwhile.
+ However,
+
+ .di a
+ .a
+ .a
+ .di
+
+ will work and will make `a' contain two copies of what it contained
+ before; in troff, `a' would contain nothing. */
+ request_or_macro *rm
+ = (request_or_macro *)request_dictionary.remove(s);
+ if (!rm || (mac = rm->to_macro()) == 0)
+ mac = new macro;
+ }
+ else
+ mac = new macro;
+#endif
+ // We can now catch the situation described above by comparing
+ // the length of the charlist in the macro_header with the length
+ // stored in the macro. When we detect this, we copy the contents.
+ mac = new macro;
+ if (append) {
+ request_or_macro *rm
+ = (request_or_macro *)request_dictionary.lookup(s);
+ if (rm) {
+ macro *m = rm->to_macro();
+ if (m)
+ *mac = *m;
+ }
+ }
+}
+
+macro_diversion::~macro_diversion()
+{
+ request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);
+ macro *m = rm ? rm->to_macro() : 0;
+ if (m) {
+ *m = *mac;
+ delete mac;
+ }
+ else
+ request_dictionary.define(nm, mac);
+ mac = 0;
+ dl_reg_contents = max_width.to_units();
+ dn_reg_contents = vertical_position.to_units();
+}
+
+vunits macro_diversion::distance_to_next_trap()
+{
+ if (!diversion_trap.is_null() && diversion_trap_pos > vertical_position)
+ return diversion_trap_pos - vertical_position;
+ else
+ // Substract vresolution so that vunits::vunits does not overflow.
+ return vunits(INT_MAX - vresolution);
+}
+
+void macro_diversion::transparent_output(unsigned char c)
+{
+ mac->append(c);
+}
+
+void macro_diversion::transparent_output(node *n)
+{
+ mac->append(n);
+}
+
+void macro_diversion::output(node *nd, int retain_size,
+ vunits vs, int ls, hunits width)
+{
+ vertical_size v(vs, ls);
+ while (nd != 0) {
+ nd->set_vertical_size(&v);
+ node *temp = nd;
+ nd = nd->next;
+ if (temp->interpret(mac)) {
+ delete temp;
+ }
+ else {
+#if 1
+ temp->freeze_space();
+#endif
+ mac->append(temp);
+ }
+ }
+ if (!v.post_extra.is_zero())
+ last_post_line_extra_space = v.post_extra.to_units();
+ if (!retain_size) {
+ v.pre = vs;
+ v.post = (ls > 1) ? vs*(ls - 1) : V0;
+ }
+ if (width > max_width)
+ max_width = width;
+ vunits x = v.pre + v.pre_extra + v.post + v.post_extra;
+ if (vertical_position_traps_flag
+ && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
+ && diversion_trap_pos <= vertical_position + x) {
+ vunits trunc = vertical_position + x - diversion_trap_pos;
+ if (trunc > v.post)
+ trunc = v.post;
+ v.post -= trunc;
+ x -= trunc;
+ truncated_space = trunc;
+ spring_trap(diversion_trap);
+ }
+ mac->append(new vertical_size_node(-v.pre));
+ mac->append(new vertical_size_node(v.post));
+ mac->append('\n');
+ vertical_position += x;
+ if (vertical_position - v.post > high_water_mark)
+ high_water_mark = vertical_position - v.post;
+}
+
+void macro_diversion::space(vunits n, int)
+{
+ if (vertical_position_traps_flag
+ && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
+ && diversion_trap_pos <= vertical_position + n) {
+ truncated_space = vertical_position + n - diversion_trap_pos;
+ n = diversion_trap_pos - vertical_position;
+ spring_trap(diversion_trap);
+ }
+ else if (n + vertical_position < V0)
+ n = -vertical_position;
+ mac->append(new diverted_space_node(n));
+ vertical_position += n;
+}
+
+void macro_diversion::copy_file(const char *filename)
+{
+ mac->append(new diverted_copy_file_node(filename));
+}
+
+top_level_diversion::top_level_diversion()
+: page_count(0), have_next_page_number(0), page_length(units_per_inch*11),
+ page_offset(units_per_inch), prev_page_offset(units_per_inch),
+ ejecting_page(0), page_trap_list(0), before_first_page(1), no_space_mode(0),
+ page_number(0), last_page_count(-1)
+{
+}
+
+// find the next trap after pos
+
+trap *top_level_diversion::find_next_trap(vunits *next_trap_pos)
+{
+ trap *next_trap = 0;
+ for (trap *pt = page_trap_list; pt != 0; pt = pt->next)
+ if (!pt->nm.is_null()) {
+ if (pt->position >= V0) {
+ if (pt->position > vertical_position
+ && pt->position < page_length
+ && (next_trap == 0 || pt->position < *next_trap_pos)) {
+ next_trap = pt;
+ *next_trap_pos = pt->position;
+ }
+ }
+ else {
+ vunits pos = pt->position;
+ pos += page_length;
+ if (pos > 0 && pos > vertical_position && (next_trap == 0 || pos < *next_trap_pos)) {
+ next_trap = pt;
+ *next_trap_pos = pos;
+ }
+ }
+ }
+ return next_trap;
+}
+
+vunits top_level_diversion::distance_to_next_trap()
+{
+ vunits d;
+ if (!find_next_trap(&d))
+ return page_length - vertical_position;
+ else
+ return d - vertical_position;
+}
+
+void top_level_diversion::output(node *nd, int retain_size,
+ vunits vs, int ls, hunits /*width*/)
+{
+ no_space_mode = 0;
+ vunits next_trap_pos;
+ trap *next_trap = find_next_trap(&next_trap_pos);
+ if (before_first_page && begin_page())
+ fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
+ vertical_size v(vs, ls);
+ for (node *tem = nd; tem != 0; tem = tem->next)
+ tem->set_vertical_size(&v);
+ if (!v.post_extra.is_zero())
+ last_post_line_extra_space = v.post_extra.to_units();
+ if (!retain_size) {
+ v.pre = vs;
+ v.post = (ls > 1) ? vs*(ls - 1) : V0;
+ }
+ vertical_position += v.pre;
+ vertical_position += v.pre_extra;
+ the_output->print_line(page_offset, vertical_position, nd,
+ v.pre + v.pre_extra, v.post_extra);
+ vertical_position += v.post_extra;
+ if (vertical_position > high_water_mark)
+ high_water_mark = vertical_position;
+ if (vertical_position_traps_flag && vertical_position >= page_length)
+ begin_page();
+ else if (vertical_position_traps_flag
+ && next_trap != 0 && vertical_position >= next_trap_pos) {
+ nl_reg_contents = vertical_position.to_units();
+ truncated_space = v.post;
+ spring_trap(next_trap->nm);
+ }
+ else if (v.post > V0) {
+ vertical_position += v.post;
+ if (vertical_position_traps_flag
+ && next_trap != 0 && vertical_position >= next_trap_pos) {
+ truncated_space = vertical_position - next_trap_pos;
+ vertical_position = next_trap_pos;
+ nl_reg_contents = vertical_position.to_units();
+ spring_trap(next_trap->nm);
+ }
+ else if (vertical_position_traps_flag && vertical_position >= page_length)
+ begin_page();
+ else
+ nl_reg_contents = vertical_position.to_units();
+ }
+ else
+ nl_reg_contents = vertical_position.to_units();
+}
+
+void top_level_diversion::transparent_output(unsigned char c)
+{
+ if (before_first_page && begin_page())
+ // This can only happen with the transparent() request.
+ fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
+ const char *s = asciify(c);
+ while (*s)
+ the_output->transparent_char(*s++);
+}
+
+void top_level_diversion::transparent_output(node * /*n*/)
+{
+ error("can't transparently output node at top level");
+}
+
+void top_level_diversion::copy_file(const char *filename)
+{
+ if (before_first_page && begin_page())
+ fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
+ the_output->copy_file(page_offset, vertical_position, filename);
+}
+
+void top_level_diversion::space(vunits n, int forced)
+{
+ if (no_space_mode) {
+ if (!forced)
+ return;
+ else
+ no_space_mode = 0;
+ }
+ if (before_first_page) {
+ if (begin_page()) {
+ // This happens if there's a top of page trap, and the first-page
+ // transition is caused by `'sp'.
+ truncated_space = n > V0 ? n : V0;
+ return;
+ }
+ }
+ vunits next_trap_pos;
+ trap *next_trap = find_next_trap(&next_trap_pos);
+ vunits y = vertical_position + n;
+ if (vertical_position_traps_flag && next_trap != 0 && y >= next_trap_pos) {
+ vertical_position = next_trap_pos;
+ nl_reg_contents = vertical_position.to_units();
+ truncated_space = y - vertical_position;
+ spring_trap(next_trap->nm);
+ }
+ else if (y < V0) {
+ vertical_position = V0;
+ nl_reg_contents = vertical_position.to_units();
+ }
+ else if (vertical_position_traps_flag && y >= page_length && n >= V0)
+ begin_page();
+ else {
+ vertical_position = y;
+ nl_reg_contents = vertical_position.to_units();
+ }
+}
+
+trap::trap(symbol s, vunits n, trap *p)
+ : nm(s), next(p), position(n)
+{
+}
+
+void top_level_diversion::add_trap(symbol nm, vunits pos)
+{
+ trap *first_free_slot = 0;
+ for (trap **p = &page_trap_list; *p; p = &(*p)->next) {
+ if ((*p)->nm.is_null()) {
+ if (first_free_slot == 0)
+ first_free_slot = *p;
+ }
+ else if ((*p)->position == pos) {
+ (*p)->nm = nm;
+ return;
+ }
+ }
+ if (first_free_slot) {
+ first_free_slot->nm = nm;
+ first_free_slot->position = pos;
+ }
+ else
+ *p = new trap(nm, pos, 0);
+}
+
+void top_level_diversion::remove_trap(symbol nm)
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->nm == nm) {
+ p->nm = NULL_SYMBOL;
+ return;
+ }
+}
+
+void top_level_diversion::remove_trap_at(vunits pos)
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->position == pos) {
+ p->nm = NULL_SYMBOL;
+ return;
+ }
+}
+
+void top_level_diversion::change_trap(symbol nm, vunits pos)
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->nm == nm) {
+ p->position = pos;
+ return;
+ }
+}
+
+void top_level_diversion::print_traps()
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->nm.is_null())
+ fprintf(stderr, " empty\n");
+ else
+ fprintf(stderr, "%s\t%d\n", p->nm.contents(), p->position.to_units());
+ fflush(stderr);
+}
+
+void end_diversions()
+{
+ while (curdiv != topdiv) {
+ error("automatically ending diversion `%1' on exit",
+ curdiv->nm.contents());
+ diversion *tem = curdiv;
+ curdiv = curdiv->prev;
+ delete tem;
+ }
+}
+
+NO_RETURN void cleanup_and_exit(int exit_code)
+{
+ if (the_output) {
+ the_output->trailer(topdiv->get_page_length());
+ delete the_output;
+ }
+ exit(exit_code);
+}
+
+// returns non-zero if it sprung a top of page trap
+
+int top_level_diversion::begin_page()
+{
+ if (exit_started) {
+ if (page_count == last_page_count
+ ? curenv->is_empty()
+ : (done_end_macro && (seen_last_page_ejector || began_page_in_end_macro)))
+ cleanup_and_exit(0);
+ if (!done_end_macro)
+ began_page_in_end_macro = 1;
+ }
+ if (!the_output)
+ init_output();
+ ++page_count;
+ if (have_next_page_number) {
+ page_number = next_page_number;
+ have_next_page_number = 0;
+ }
+ else if (before_first_page == 1)
+ page_number = 1;
+ else
+ page_number++;
+ // spring the top of page trap if there is one
+ vunits next_trap_pos;
+ vertical_position = -vresolution;
+ trap *next_trap = find_next_trap(&next_trap_pos);
+ vertical_position = V0;
+ high_water_mark = V0;
+ ejecting_page = 0;
+ // If before_first_page was 2, then the top of page transition was undone
+ // using eg .nr nl 0-1. See nl_reg::set_value.
+ if (before_first_page != 2)
+ the_output->begin_page(page_number, page_length);
+ before_first_page = 0;
+ nl_reg_contents = vertical_position.to_units();
+ if (vertical_position_traps_flag && next_trap != 0 && next_trap_pos == V0) {
+ truncated_space = V0;
+ spring_trap(next_trap->nm);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void continue_page_eject()
+{
+ if (topdiv->get_ejecting()) {
+ if (curdiv != topdiv)
+ error("can't continue page ejection because of current diversion");
+ else if (!vertical_position_traps_flag)
+ error("can't continue page ejection because vertical position traps disabled");
+ else {
+ push_page_ejector();
+ topdiv->space(topdiv->get_page_length(), 1);
+ }
+ }
+}
+
+void top_level_diversion::set_next_page_number(int n)
+{
+ next_page_number= n;
+ have_next_page_number = 1;
+}
+
+int top_level_diversion::get_next_page_number()
+{
+ return have_next_page_number ? next_page_number : page_number + 1;
+}
+
+void top_level_diversion::set_page_length(vunits n)
+{
+ page_length = n;
+}
+
+diversion::~diversion()
+{
+}
+
+void page_offset()
+{
+ hunits n;
+ if (!has_arg() || !get_hunits(&n, 'v', topdiv->page_offset))
+ n = topdiv->prev_page_offset;
+ topdiv->prev_page_offset = topdiv->page_offset;
+ topdiv->page_offset = n;
+ skip_line();
+}
+
+void page_length()
+{
+ vunits n;
+ if (has_arg() && get_vunits(&n, 'v', topdiv->get_page_length()))
+ topdiv->set_page_length(n);
+ else
+ topdiv->set_page_length(11*units_per_inch);
+ skip_line();
+}
+
+void when_request()
+{
+ vunits n;
+ if (get_vunits(&n, 'v')) {
+ symbol s = get_name();
+ if (s.is_null())
+ topdiv->remove_trap_at(n);
+ else
+ topdiv->add_trap(s, n);
+ }
+ skip_line();
+}
+
+void begin_page()
+{
+ int got_arg = 0;
+ int n;
+ if (has_arg() && get_integer(&n, topdiv->get_page_number()))
+ got_arg = 1;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (curdiv == topdiv) {
+ if (topdiv->before_first_page) {
+ if (!break_flag) {
+ if (got_arg)
+ topdiv->set_next_page_number(n);
+ if (got_arg || !topdiv->no_space_mode)
+ topdiv->begin_page();
+ }
+ else if (topdiv->no_space_mode && !got_arg)
+ topdiv->begin_page();
+ else {
+ /* Given this
+
+ .wh 0 x
+ .de x
+ .tm \\n%
+ ..
+ .bp 3
+
+ troff prints
+
+ 1
+ 3
+
+ This code makes groff do the same. */
+
+ push_page_ejector();
+ topdiv->begin_page();
+ if (got_arg)
+ topdiv->set_next_page_number(n);
+ topdiv->set_ejecting();
+ }
+ }
+ else {
+ push_page_ejector();
+ if (break_flag)
+ curenv->do_break();
+ if (got_arg)
+ topdiv->set_next_page_number(n);
+ if (!(topdiv->no_space_mode && !got_arg))
+ topdiv->set_ejecting();
+ }
+ }
+ tok.next();
+}
+
+void no_space()
+{
+ if (curdiv == topdiv)
+ topdiv->no_space_mode = 1;
+ skip_line();
+}
+
+void restore_spacing()
+{
+ if (curdiv == topdiv)
+ topdiv->no_space_mode = 0;
+ skip_line();
+}
+
+/* It is necessary to generate a break before before reading the argument,
+because otherwise arguments using | will be wrong. But if we just
+generate a break as usual, then the line forced out may spring a trap
+and thus push a macro onto the input stack before we have had a chance
+to read the argument to the sp request. We resolve this dilemma by
+setting, before generating the break, a flag which will postpone the
+actual pushing of the macro associated with the trap sprung by the
+outputting of the line forced out by the break till after we have read
+the argument to the request. If the break did cause a trap to be
+sprung, then we don't actually do the space. */
+
+void space_request()
+{
+ postpone_traps();
+ if (break_flag)
+ curenv->do_break();
+ vunits n;
+ if (!has_arg() || !get_vunits(&n, 'v'))
+ n = curenv->get_vertical_spacing();
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (!unpostpone_traps())
+ curdiv->space(n);
+ else
+ // The line might have had line spacing that was truncated.
+ truncated_space += n;
+ tok.next();
+}
+
+void blank_line()
+{
+ curenv->do_break();
+ if (!trap_sprung_flag)
+ curdiv->space(curenv->get_vertical_spacing());
+ else
+ truncated_space += curenv->get_vertical_spacing();
+}
+
+/* need_space might spring a trap and so we must be careful that the
+BEGIN_TRAP token is not skipped over. */
+
+void need_space()
+{
+ vunits n;
+ if (!has_arg() || !get_vunits(&n, 'v'))
+ n = curenv->get_vertical_spacing();
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ curdiv->need(n);
+ tok.next();
+}
+
+void page_number()
+{
+ int n;
+ if (has_arg() && get_integer(&n, topdiv->get_page_number()))
+ topdiv->set_next_page_number(n);
+ skip_line();
+}
+
+vunits saved_space;
+
+void save_vertical_space()
+{
+ vunits x;
+ if (get_vunits(&x, 'v')) {
+ if (curdiv->distance_to_next_trap() > x)
+ curdiv->space(x, 1);
+ else
+ saved_space = x;
+ }
+ skip_line();
+}
+
+void output_saved_vertical_space()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (saved_space > V0)
+ curdiv->space(saved_space, 1);
+ saved_space = V0;
+ tok.next();
+}
+
+void flush_output()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (the_output)
+ the_output->flush();
+ tok.next();
+}
+
+void macro_diversion::set_diversion_trap(symbol s, vunits n)
+{
+ diversion_trap = s;
+ diversion_trap_pos = n;
+}
+
+void macro_diversion::clear_diversion_trap()
+{
+ diversion_trap = NULL_SYMBOL;
+}
+
+void top_level_diversion::set_diversion_trap(symbol, vunits)
+{
+ error("can't set diversion trap when no current diversion");
+}
+
+void top_level_diversion::clear_diversion_trap()
+{
+ error("can't set diversion trap when no current diversion");
+}
+
+void diversion_trap()
+{
+ vunits n;
+ if (has_arg() && get_vunits(&n, 'v')) {
+ symbol s = get_name();
+ if (!s.is_null())
+ curdiv->set_diversion_trap(s, n);
+ else
+ curdiv->clear_diversion_trap();
+ }
+ else
+ curdiv->clear_diversion_trap();
+ skip_line();
+}
+
+void change_trap()
+{
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ vunits x;
+ if (has_arg() && get_vunits(&x, 'v'))
+ topdiv->change_trap(s, x);
+ else
+ topdiv->remove_trap(s);
+ }
+ skip_line();
+}
+
+void print_traps()
+{
+ topdiv->print_traps();
+ skip_line();
+}
+
+void mark()
+{
+ symbol s = get_name();
+ if (s.is_null())
+ curdiv->marked_place = curdiv->get_vertical_position();
+ else if (curdiv == topdiv)
+ set_number_reg(s, nl_reg_contents);
+ else
+ set_number_reg(s, curdiv->get_vertical_position().to_units());
+ skip_line();
+}
+
+// This is truly bizarre. It is documented in the SQ manual.
+
+void return_request()
+{
+ vunits dist = curdiv->marked_place - curdiv->get_vertical_position();
+ if (has_arg()) {
+ if (tok.ch() == '-') {
+ tok.next();
+ vunits x;
+ if (get_vunits(&x, 'v'))
+ dist = -x;
+ }
+ else {
+ vunits x;
+ if (get_vunits(&x, 'v'))
+ dist = x >= V0 ? x - curdiv->get_vertical_position() : V0;
+ }
+ }
+ if (dist < V0)
+ curdiv->space(dist);
+ skip_line();
+}
+
+void vertical_position_traps()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ vertical_position_traps_flag = (n != 0);
+ else
+ vertical_position_traps_flag = 1;
+ skip_line();
+}
+
+class page_offset_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int page_offset_reg::get_value(units *res)
+{
+ *res = topdiv->get_page_offset().to_units();
+ return 1;
+}
+
+const char *page_offset_reg::get_string()
+{
+ return itoa(topdiv->get_page_offset().to_units());
+}
+
+class page_length_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int page_length_reg::get_value(units *res)
+{
+ *res = topdiv->get_page_length().to_units();
+ return 1;
+}
+
+const char *page_length_reg::get_string()
+{
+ return itoa(topdiv->get_page_length().to_units());
+}
+
+class vertical_position_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int vertical_position_reg::get_value(units *res)
+{
+ if (curdiv == topdiv && topdiv->before_first_page)
+ *res = -1;
+ else
+ *res = curdiv->get_vertical_position().to_units();
+ return 1;
+}
+
+const char *vertical_position_reg::get_string()
+{
+ if (curdiv == topdiv && topdiv->before_first_page)
+ return "-1";
+ else
+ return itoa(curdiv->get_vertical_position().to_units());
+}
+
+class high_water_mark_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int high_water_mark_reg::get_value(units *res)
+{
+ *res = curdiv->get_high_water_mark().to_units();
+ return 1;
+}
+
+const char *high_water_mark_reg::get_string()
+{
+ return itoa(curdiv->get_high_water_mark().to_units());
+}
+
+class distance_to_next_trap_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int distance_to_next_trap_reg::get_value(units *res)
+{
+ *res = curdiv->distance_to_next_trap().to_units();
+ return 1;
+}
+
+const char *distance_to_next_trap_reg::get_string()
+{
+ return itoa(curdiv->distance_to_next_trap().to_units());
+}
+
+class diversion_name_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *diversion_name_reg::get_string()
+{
+ return curdiv->get_diversion_name();
+}
+
+class page_number_reg : public general_reg {
+public:
+ page_number_reg();
+ int get_value(units *);
+ void set_value(units);
+};
+
+page_number_reg::page_number_reg()
+{
+}
+
+void page_number_reg::set_value(units n)
+{
+ topdiv->set_page_number(n);
+}
+
+int page_number_reg::get_value(units *res)
+{
+ *res = topdiv->get_page_number();
+ return 1;
+}
+
+class next_page_number_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *next_page_number_reg::get_string()
+{
+ return itoa(topdiv->get_next_page_number());
+}
+
+class page_ejecting_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *page_ejecting_reg::get_string()
+{
+ return itoa(topdiv->get_ejecting());
+}
+
+class constant_vunits_reg : public reg {
+ vunits *p;
+public:
+ constant_vunits_reg(vunits *);
+ const char *get_string();
+};
+
+constant_vunits_reg::constant_vunits_reg(vunits *q) : p(q)
+{
+}
+
+const char *constant_vunits_reg::get_string()
+{
+ return itoa(p->to_units());
+}
+
+class nl_reg : public variable_reg {
+public:
+ nl_reg();
+ void set_value(units);
+};
+
+nl_reg::nl_reg() : variable_reg(&nl_reg_contents)
+{
+}
+
+void nl_reg::set_value(units n)
+{
+ variable_reg::set_value(n);
+ // Setting nl to a negative value when the vertical position in
+ // the top-level diversion is 0 undoes the top of page transition,
+ // so that the header macro will be called as if the top of page
+ // transition hasn't happened. This is used by Larry Wall's
+ // wrapman program. Setting before_first_page to 2 rather than 1,
+ // tells top_level_diversion::begin_page not to call
+ // output_file::begin_page again.
+ if (n < 0 && topdiv->get_vertical_position() == V0)
+ topdiv->before_first_page = 2;
+}
+
+void init_div_requests()
+{
+ init_request("wh", when_request);
+ init_request("ch", change_trap);
+ init_request("pl", page_length);
+ init_request("po", page_offset);
+ init_request("rs", restore_spacing);
+ init_request("ns", no_space);
+ init_request("sp", space_request);
+ init_request("di", divert);
+ init_request("da", divert_append);
+ init_request("bp", begin_page);
+ init_request("ne", need_space);
+ init_request("pn", page_number);
+ init_request("dt", diversion_trap);
+ init_request("rt", return_request);
+ init_request("mk", mark);
+ init_request("sv", save_vertical_space);
+ init_request("os", output_saved_vertical_space);
+ init_request("fl", flush_output);
+ init_request("vpt", vertical_position_traps);
+ init_request("ptr", print_traps);
+ number_reg_dictionary.define(".a",
+ new constant_int_reg(&last_post_line_extra_space));
+ number_reg_dictionary.define(".z", new diversion_name_reg);
+ number_reg_dictionary.define(".o", new page_offset_reg);
+ number_reg_dictionary.define(".p", new page_length_reg);
+ number_reg_dictionary.define(".d", new vertical_position_reg);
+ number_reg_dictionary.define(".h", new high_water_mark_reg);
+ number_reg_dictionary.define(".t", new distance_to_next_trap_reg);
+ number_reg_dictionary.define("dl", new variable_reg(&dl_reg_contents));
+ number_reg_dictionary.define("dn", new variable_reg(&dn_reg_contents));
+ number_reg_dictionary.define("nl", new nl_reg);
+ number_reg_dictionary.define(".vpt",
+ new constant_int_reg(&vertical_position_traps_flag));
+ number_reg_dictionary.define("%", new page_number_reg);
+ number_reg_dictionary.define(".pn", new next_page_number_reg);
+ number_reg_dictionary.define(".trunc",
+ new constant_vunits_reg(&truncated_space));
+ number_reg_dictionary.define(".ne",
+ new constant_vunits_reg(&needed_space));
+ number_reg_dictionary.define(".pe", new page_ejecting_reg);
+}
diff --git a/gnu/usr.bin/groff/troff/div.h b/gnu/usr.bin/groff/troff/div.h
new file mode 100644
index 000000000000..9ca612be404a
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/div.h
@@ -0,0 +1,146 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+class diversion {
+ friend void do_divert(int append);
+ friend void end_diversions();
+ diversion *prev;
+protected:
+ symbol nm;
+ vunits vertical_position;
+ vunits high_water_mark;
+public:
+ vunits marked_place;
+ diversion(symbol s = NULL_SYMBOL);
+ virtual ~diversion();
+ virtual void output(node *nd, int retain_size, vunits vs, int ls, hunits width) = 0;
+ virtual void transparent_output(unsigned char) = 0;
+ virtual void transparent_output(node *) = 0;
+ virtual void space(vunits distance, int forced = 0) = 0;
+#ifdef COLUMN
+ virtual void vjustify(symbol) = 0;
+#endif /* COLUMN */
+ vunits get_vertical_position() { return vertical_position; }
+ vunits get_high_water_mark() { return high_water_mark; }
+ virtual vunits distance_to_next_trap() = 0;
+ void need(vunits);
+ const char *get_diversion_name() { return nm.contents(); }
+ virtual void set_diversion_trap(symbol, vunits) = 0;
+ virtual void clear_diversion_trap() = 0;
+ virtual void copy_file(const char *filename) = 0;
+};
+
+class macro;
+
+class macro_diversion : public diversion {
+ macro *mac;
+ hunits max_width;
+ symbol diversion_trap;
+ vunits diversion_trap_pos;
+public:
+ macro_diversion(symbol, int);
+ ~macro_diversion();
+ void output(node *nd, int retain_size, vunits vs, int ls, hunits width);
+ void transparent_output(unsigned char);
+ void transparent_output(node *);
+ void space(vunits distance, int forced = 0);
+#ifdef COLUMN
+ void vjustify(symbol);
+#endif /* COLUMN */
+ vunits distance_to_next_trap();
+ void set_diversion_trap(symbol, vunits);
+ void clear_diversion_trap();
+ void copy_file(const char *filename);
+};
+
+struct trap {
+ trap *next;
+ vunits position;
+ symbol nm;
+ trap(symbol, vunits, trap *);
+};
+
+struct output_file;
+
+class top_level_diversion : public diversion {
+ int page_number;
+ int page_count;
+ int last_page_count;
+ vunits page_length;
+ hunits prev_page_offset;
+ hunits page_offset;
+ trap *page_trap_list;
+ trap *find_next_trap(vunits *);
+ int have_next_page_number;
+ int next_page_number;
+ int ejecting_page; // Is the current page being ejected?
+public:
+ int before_first_page;
+ int no_space_mode;
+ top_level_diversion();
+ void output(node *nd, int retain_size, vunits vs, int ls, hunits width);
+ void transparent_output(unsigned char);
+ void transparent_output(node *);
+ void space(vunits distance, int forced = 0);
+#ifdef COLUMN
+ void vjustify(symbol);
+#endif /* COLUMN */
+ hunits get_page_offset() { return page_offset; }
+ vunits get_page_length() { return page_length; }
+ vunits distance_to_next_trap();
+ void add_trap(symbol nm, vunits pos);
+ void change_trap(symbol nm, vunits pos);
+ void remove_trap(symbol);
+ void remove_trap_at(vunits pos);
+ void print_traps();
+ int get_page_count() { return page_count; }
+ int get_page_number() { return page_number; }
+ int get_next_page_number();
+ void set_page_number(int n) { page_number = n; }
+ int begin_page();
+ void set_next_page_number(int);
+ void set_page_length(vunits);
+ void copy_file(const char *filename);
+ int get_ejecting() { return ejecting_page; }
+ void set_ejecting() { ejecting_page = 1; }
+ friend void page_offset();
+ void set_diversion_trap(symbol, vunits);
+ void clear_diversion_trap();
+ void set_last_page() { last_page_count = page_count; }
+};
+
+extern top_level_diversion *topdiv;
+extern diversion *curdiv;
+
+extern int exit_started;
+extern int done_end_macro;
+extern int seen_last_page_ejector;
+
+void spring_trap(symbol); // implemented by input.c
+extern int trap_sprung_flag;
+void postpone_traps();
+int unpostpone_traps();
+
+void push_page_ejector();
+void continue_page_eject();
+void handle_first_page_transition();
+void blank_line();
+
+extern volatile void cleanup_and_exit(int);
diff --git a/gnu/usr.bin/groff/troff/env.cc b/gnu/usr.bin/groff/troff/env.cc
new file mode 100644
index 000000000000..0d343ffc5901
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/env.cc
@@ -0,0 +1,3052 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "div.h"
+#include "reg.h"
+#include "charinfo.h"
+#include "searchpath.h"
+#include "macropath.h"
+#include <math.h>
+
+symbol default_family("T");
+
+enum { ADJUST_LEFT = 0, ADJUST_BOTH = 1, ADJUST_CENTER = 3, ADJUST_RIGHT = 5 };
+
+enum { HYPHEN_LAST_LINE = 2, HYPHEN_LAST_CHARS = 4, HYPHEN_FIRST_CHARS = 8 };
+
+struct env_list {
+ environment *env;
+ env_list *next;
+ env_list(environment *e, env_list *p) : env(e), next(p) {}
+};
+
+env_list *env_stack;
+const int NENVIRONMENTS = 10;
+environment *env_table[NENVIRONMENTS];
+dictionary env_dictionary(10);
+environment *curenv;
+static int next_line_number = 0;
+
+charinfo *field_delimiter_char;
+charinfo *padding_indicator_char;
+
+int translate_space_to_dummy = 0;
+
+class pending_output_line {
+ node *nd;
+ int no_fill;
+ vunits vs;
+ int ls;
+ hunits width;
+#ifdef WIDOW_CONTROL
+ int last_line; // Is it the last line of the paragraph?
+#endif /* WIDOW_CONTROL */
+public:
+ pending_output_line *next;
+
+ pending_output_line(node *, int, vunits, int, hunits,
+ pending_output_line * = 0);
+ ~pending_output_line();
+ int output();
+
+#ifdef WIDOW_CONTROL
+ friend void environment::mark_last_line();
+ friend void environment::output(node *, int, vunits, int, hunits);
+#endif /* WIDOW_CONTROL */
+};
+
+pending_output_line::pending_output_line(node *n, int nf, vunits v, int l,
+ hunits w, pending_output_line *p)
+: nd(n), no_fill(nf), vs(v), ls(l), width(w),
+#ifdef WIDOW_CONTROL
+ last_line(0),
+#endif /* WIDOW_CONTROL */
+ next(p)
+{
+}
+
+pending_output_line::~pending_output_line()
+{
+ delete_node_list(nd);
+}
+
+int pending_output_line::output()
+{
+ if (trap_sprung_flag)
+ return 0;
+#ifdef WIDOW_CONTROL
+ if (next && next->last_line && !no_fill) {
+ curdiv->need(vs*ls + vunits(vresolution));
+ if (trap_sprung_flag) {
+ next->last_line = 0; // Try to avoid infinite loops.
+ return 0;
+ }
+ }
+#endif
+ curdiv->output(nd, no_fill, vs, ls, width);
+ nd = 0;
+ return 1;
+}
+
+void environment::output(node *nd, int no_fill, vunits vs, int ls,
+ hunits width)
+{
+#ifdef WIDOW_CONTROL
+ while (pending_lines) {
+ if (widow_control && !pending_lines->no_fill && !pending_lines->next)
+ break;
+ if (!pending_lines->output())
+ break;
+ pending_output_line *tem = pending_lines;
+ pending_lines = pending_lines->next;
+ delete tem;
+ }
+#else /* WIDOW_CONTROL */
+ output_pending_lines();
+#endif /* WIDOW_CONTROL */
+ if (!trap_sprung_flag && !pending_lines
+#ifdef WIDOW_CONTROL
+ && (!widow_control || no_fill)
+#endif /* WIDOW_CONTROL */
+ )
+ curdiv->output(nd, no_fill, vs, ls, width);
+ else {
+ for (pending_output_line **p = &pending_lines; *p; p = &(*p)->next)
+ ;
+ *p = new pending_output_line(nd, no_fill, vs, ls, width);
+ }
+}
+
+// a line from .tl goes at the head of the queue
+
+void environment::output_title(node *nd, int no_fill, vunits vs, int ls,
+ hunits width)
+{
+ if (!trap_sprung_flag)
+ curdiv->output(nd, no_fill, vs, ls, width);
+ else
+ pending_lines = new pending_output_line(nd, no_fill, vs, ls, width,
+ pending_lines);
+}
+
+void environment::output_pending_lines()
+{
+ while (pending_lines && pending_lines->output()) {
+ pending_output_line *tem = pending_lines;
+ pending_lines = pending_lines->next;
+ delete tem;
+ }
+}
+
+#ifdef WIDOW_CONTROL
+
+void environment::mark_last_line()
+{
+ if (!widow_control || !pending_lines)
+ return;
+ for (pending_output_line *p = pending_lines; p->next; p = p->next)
+ ;
+ if (!p->no_fill)
+ p->last_line = 1;
+}
+
+void widow_control_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->widow_control = n != 0;
+ else
+ curenv->widow_control = 1;
+ skip_line();
+}
+
+#endif /* WIDOW_CONTROL */
+
+/* font_size functions */
+
+size_range *font_size::size_table = 0;
+int font_size::nranges = 0;
+
+extern "C" {
+
+static int compare_ranges(const void *p1, const void *p2)
+{
+ return ((size_range *)p1)->min - ((size_range *)p2)->min;
+}
+
+}
+
+void font_size::init_size_table(int *sizes)
+{
+ nranges = 0;
+ while (sizes[nranges*2] != 0)
+ nranges++;
+ assert(nranges > 0);
+ size_table = new size_range[nranges];
+ for (int i = 0; i < nranges; i++) {
+ size_table[i].min = sizes[i*2];
+ size_table[i].max = sizes[i*2 + 1];
+ }
+ qsort(size_table, nranges, sizeof(size_range), compare_ranges);
+}
+
+font_size::font_size(int sp)
+{
+ for (int i = 0; i < nranges; i++) {
+ if (sp < size_table[i].min) {
+ if (i > 0 && size_table[i].min - sp >= sp - size_table[i - 1].max)
+ p = size_table[i - 1].max;
+ else
+ p = size_table[i].min;
+ return;
+ }
+ if (sp <= size_table[i].max) {
+ p = sp;
+ return;
+ }
+ }
+ p = size_table[nranges - 1].max;
+}
+
+int font_size::to_units()
+{
+ return scale(p, units_per_inch, sizescale*72);
+}
+
+// we can't do this in a static constructor because various dictionaries
+// have to get initialized first
+
+void init_environments()
+{
+ curenv = env_table[0] = new environment("0");
+}
+
+void tab_character()
+{
+ curenv->tab_char = get_optional_char();
+ skip_line();
+}
+
+void leader_character()
+{
+ curenv->leader_char = get_optional_char();
+ skip_line();
+}
+
+void environment::add_char(charinfo *ci)
+{
+ if (interrupted)
+ ;
+ // don't allow fields in dummy environments
+ else if (ci == field_delimiter_char && !dummy) {
+ if (current_field)
+ wrap_up_field();
+ else
+ start_field();
+ }
+ else if (current_field && ci == padding_indicator_char)
+ add_padding();
+ else if (current_tab) {
+ if (tab_contents == 0)
+ tab_contents = new line_start_node;
+ if (ci != hyphen_indicator_char)
+ tab_contents = tab_contents->add_char(ci, this, &tab_width);
+ else
+ tab_contents = tab_contents->add_discretionary_hyphen();
+ }
+ else {
+ if (line == 0)
+ start_line();
+ if (ci != hyphen_indicator_char)
+ line = line->add_char(ci, this, &width_total);
+ else
+ line = line->add_discretionary_hyphen();
+ }
+}
+
+node *environment::make_char_node(charinfo *ci)
+{
+ return make_node(ci, this);
+}
+
+void environment::add_node(node *n)
+{
+ assert(n != 0);
+ if (current_tab || current_field)
+ n->freeze_space();
+ if (interrupted) {
+ delete n;
+ }
+ else if (current_tab) {
+ n->next = tab_contents;
+ tab_contents = n;
+ tab_width += n->width();
+ }
+ else {
+ if (line == 0) {
+ if (discarding && n->discardable()) {
+ // XXX possibly: input_line_start -= n->width();
+ delete n;
+ return;
+ }
+ start_line();
+ }
+ width_total += n->width();
+ space_total += n->nspaces();
+ n->next = line;
+ line = n;
+ }
+}
+
+
+void environment::add_hyphen_indicator()
+{
+ if (current_tab || interrupted || current_field
+ || hyphen_indicator_char != 0)
+ return;
+ if (line == 0)
+ start_line();
+ line = line->add_discretionary_hyphen();
+}
+
+int environment::get_hyphenation_flags()
+{
+ return hyphenation_flags;
+}
+
+int environment::get_hyphen_line_max()
+{
+ return hyphen_line_max;
+}
+
+int environment::get_hyphen_line_count()
+{
+ return hyphen_line_count;
+}
+
+int environment::get_center_lines()
+{
+ return center_lines;
+}
+
+int environment::get_right_justify_lines()
+{
+ return right_justify_lines;
+}
+
+void environment::add_italic_correction()
+{
+ if (current_tab) {
+ if (tab_contents)
+ tab_contents = tab_contents->add_italic_correction(&tab_width);
+ }
+ else if (line)
+ line = line->add_italic_correction(&width_total);
+}
+
+void environment::space_newline()
+{
+ assert(!current_tab && !current_field);
+ if (interrupted)
+ return;
+ hunits x = H0;
+ if (!translate_space_to_dummy) {
+ x = env_space_width(this);
+ if (node_list_ends_sentence(line) == 1)
+ x += env_sentence_space_width(this);
+ }
+ if (line != 0 && line->merge_space(x)) {
+ width_total += x;
+ return;
+ }
+ add_node(new word_space_node(x));
+ possibly_break_line(spread_flag);
+ spread_flag = 0;
+}
+
+void environment::space()
+{
+ if (interrupted)
+ return;
+ if (current_field && padding_indicator_char == 0) {
+ add_padding();
+ return;
+ }
+ hunits x = translate_space_to_dummy ? H0 : env_space_width(this);
+ node *p = current_tab ? tab_contents : line;
+ hunits *tp = current_tab ? &tab_width : &width_total;
+ if (p && p->nspaces() == 1 && p->width() == x
+ && node_list_ends_sentence(p->next) == 1) {
+ hunits xx = translate_space_to_dummy ? H0 : env_sentence_space_width(this);
+ if (p->merge_space(xx)) {
+ *tp += xx;
+ return;
+ }
+ }
+ if (p && p->merge_space(x)) {
+ *tp += x;
+ return;
+ }
+ add_node(new word_space_node(x));
+ possibly_break_line(spread_flag);
+ spread_flag = 0;
+}
+
+void environment::set_font(symbol nm)
+{
+ if (interrupted)
+ return;
+ if (nm == symbol("P")) {
+ if (family->make_definite(prev_fontno) < 0)
+ return;
+ int tem = fontno;
+ fontno = prev_fontno;
+ prev_fontno = tem;
+ }
+ else {
+ int n = symbol_fontno(nm);
+ if (n < 0) {
+ n = next_available_font_position();
+ if (!mount_font(n, nm))
+ return;
+ }
+ if (family->make_definite(n) < 0)
+ return;
+ prev_fontno = fontno;
+ fontno = n;
+ }
+}
+
+void environment::set_font(int n)
+{
+ if (interrupted)
+ return;
+ if (is_good_fontno(n)) {
+ prev_fontno = fontno;
+ fontno = n;
+ }
+ else
+ error("bad font number");
+}
+
+void environment::set_family(symbol fam)
+{
+ if (fam.is_null()) {
+ if (prev_family->make_definite(fontno) < 0)
+ return;
+ font_family *tem = family;
+ family = prev_family;
+ prev_family = tem;
+ }
+ else {
+ font_family *f = lookup_family(fam);
+ if (f->make_definite(fontno) < 0)
+ return;
+ prev_family = family;
+ family = f;
+ }
+}
+
+void environment::set_size(int n)
+{
+ if (interrupted)
+ return;
+ if (n == 0) {
+ font_size temp = prev_size;
+ prev_size = size;
+ size = temp;
+ int temp2 = prev_requested_size;
+ prev_requested_size = requested_size;
+ requested_size = temp2;
+ }
+ else {
+ prev_size = size;
+ size = font_size(n);
+ prev_requested_size = requested_size;
+ requested_size = n;
+ }
+}
+
+void environment::set_char_height(int n)
+{
+ if (interrupted)
+ return;
+ if (n == requested_size || n <= 0)
+ char_height = 0;
+ else
+ char_height = n;
+}
+
+void environment::set_char_slant(int n)
+{
+ if (interrupted)
+ return;
+ char_slant = n;
+}
+
+environment::environment(symbol nm)
+: name(nm),
+ prev_line_length((units_per_inch*13)/2),
+ line_length((units_per_inch*13)/2),
+ prev_title_length((units_per_inch*13)/2),
+ title_length((units_per_inch*13)/2),
+ prev_size(sizescale*10),
+ size(sizescale*10),
+ requested_size(sizescale*10),
+ prev_requested_size(sizescale*10),
+ char_height(0),
+ char_slant(0),
+ space_size(12),
+ sentence_space_size(12),
+ adjust_mode(ADJUST_BOTH),
+ fill(1),
+ interrupted(0),
+ prev_line_interrupted(0),
+ center_lines(0),
+ right_justify_lines(0),
+ prev_vertical_spacing(points_to_units(12)),
+ vertical_spacing(points_to_units(12)),
+ prev_line_spacing(1),
+ line_spacing(1),
+ prev_indent(0),
+ indent(0),
+ have_temporary_indent(0),
+ temporary_indent(0),
+ underline_lines(0),
+ input_trap_count(0),
+ prev_text_length(0),
+ width_total(0),
+ space_total(0),
+ input_line_start(0),
+ control_char('.'),
+ no_break_control_char('\''),
+ hyphen_indicator_char(0),
+ spread_flag(0),
+ line(0),
+ pending_lines(0),
+ discarding(0),
+ tabs(units_per_inch/2, TAB_LEFT),
+ current_tab(TAB_NONE),
+ current_field(0),
+ margin_character_flags(0),
+ margin_character_node(0),
+ margin_character_distance(points_to_units(10)),
+ numbering_nodes(0),
+ number_text_separation(1),
+ line_number_multiple(1),
+ line_number_indent(0),
+ no_number_count(0),
+ tab_char(0),
+ leader_char(charset_table['.']),
+ hyphenation_flags(1),
+ dummy(0),
+ leader_node(0),
+#ifdef WIDOW_CONTROL
+ widow_control(0),
+#endif /* WIDOW_CONTROL */
+ hyphen_line_count(0),
+ hyphen_line_max(-1),
+ hyphenation_space(H0),
+ hyphenation_margin(H0),
+ composite(0)
+{
+ prev_family = family = lookup_family(default_family);
+ prev_fontno = fontno = 1;
+ if (!is_good_fontno(1))
+ fatal("font number 1 not a valid font");
+ if (family->make_definite(1) < 0)
+ fatal("invalid default family `%1'", default_family.contents());
+ prev_fontno = fontno;
+}
+
+environment::environment(const environment *e)
+: name(e->name), // so that eg `.if "\n[.ev]"0"' works
+ prev_line_length(e->prev_line_length),
+ line_length(e->line_length),
+ prev_title_length(e->prev_title_length),
+ title_length(e->title_length),
+ prev_size(e->prev_size),
+ size(e->size),
+ prev_requested_size(e->prev_requested_size),
+ requested_size(e->requested_size),
+ char_height(e->char_height),
+ char_slant(e->char_slant),
+ space_size(e->space_size),
+ sentence_space_size(e->sentence_space_size),
+ adjust_mode(e->adjust_mode),
+ fill(e->fill),
+ interrupted(0),
+ prev_line_interrupted(0),
+ center_lines(0),
+ right_justify_lines(0),
+ prev_vertical_spacing(e->prev_vertical_spacing),
+ vertical_spacing(e->vertical_spacing),
+ prev_line_spacing(e->prev_line_spacing),
+ line_spacing(e->line_spacing),
+ prev_indent(e->prev_indent),
+ indent(e->indent),
+ have_temporary_indent(0),
+ temporary_indent(0),
+ underline_lines(0),
+ input_trap_count(0),
+ prev_text_length(e->prev_text_length),
+ width_total(0),
+ space_total(0),
+ input_line_start(0),
+ control_char(e->control_char),
+ no_break_control_char(e->no_break_control_char),
+ hyphen_indicator_char(e->hyphen_indicator_char),
+ spread_flag(0),
+ line(0),
+ pending_lines(0),
+ discarding(0),
+ tabs(e->tabs),
+ current_tab(TAB_NONE),
+ current_field(0),
+ margin_character_flags(e->margin_character_flags),
+ margin_character_node(e->margin_character_node),
+ margin_character_distance(e->margin_character_distance),
+ numbering_nodes(0),
+ number_text_separation(e->number_text_separation),
+ line_number_multiple(e->line_number_multiple),
+ line_number_indent(e->line_number_indent),
+ no_number_count(e->no_number_count),
+ tab_char(e->tab_char),
+ leader_char(e->leader_char),
+ hyphenation_flags(e->hyphenation_flags),
+ fontno(e->fontno),
+ prev_fontno(e->prev_fontno),
+ dummy(1),
+ family(e->family),
+ prev_family(e->prev_family),
+ leader_node(0),
+#ifdef WIDOW_CONTROL
+ widow_control(e->widow_control),
+#endif /* WIDOW_CONTROL */
+ hyphen_line_max(e->hyphen_line_max),
+ hyphen_line_count(0),
+ hyphenation_space(e->hyphenation_space),
+ hyphenation_margin(e->hyphenation_margin),
+ composite(0)
+{
+}
+
+environment::~environment()
+{
+ delete leader_node;
+ delete_node_list(line);
+ delete_node_list(numbering_nodes);
+}
+
+hunits environment::get_input_line_position()
+{
+ hunits n;
+ if (line == 0)
+ n = -input_line_start;
+ else
+ n = width_total - input_line_start;
+ if (current_tab)
+ n += tab_width;
+ return n;
+}
+
+void environment::set_input_line_position(hunits n)
+{
+ input_line_start = line == 0 ? -n : width_total - n;
+ if (current_tab)
+ input_line_start += tab_width;
+}
+
+hunits environment::get_line_length()
+{
+ return line_length;
+}
+
+hunits environment::get_saved_line_length()
+{
+ if (line)
+ return target_text_length + saved_indent;
+ else
+ return line_length;
+}
+
+vunits environment::get_vertical_spacing()
+{
+ return vertical_spacing;
+}
+
+int environment::get_line_spacing()
+{
+ return line_spacing;
+}
+
+int environment::get_bold()
+{
+ return get_bold_fontno(fontno);
+}
+
+hunits environment::get_digit_width()
+{
+ return env_digit_width(this);
+}
+
+int environment::get_adjust_mode()
+{
+ return adjust_mode;
+}
+
+int environment::get_fill()
+{
+ return fill;
+}
+
+hunits environment::get_indent()
+{
+ return indent;
+}
+
+hunits environment::get_saved_indent()
+{
+ if (line)
+ return saved_indent;
+ else if (have_temporary_indent)
+ return temporary_indent;
+ else
+ return indent;
+}
+
+hunits environment::get_temporary_indent()
+{
+ return temporary_indent;
+}
+
+hunits environment::get_title_length()
+{
+ return title_length;
+}
+
+node *environment::get_prev_char()
+{
+ for (node *n = current_tab ? tab_contents : line; n; n = n->next) {
+ node *last = n->last_char_node();
+ if (last)
+ return last;
+ }
+ return 0;
+}
+
+hunits environment::get_prev_char_width()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return H0;
+ return last->width();
+}
+
+hunits environment::get_prev_char_skew()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return H0;
+ return last->skew();
+}
+
+vunits environment::get_prev_char_height()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return V0;
+ vunits min, max;
+ last->vertical_extent(&min, &max);
+ return -min;
+}
+
+vunits environment::get_prev_char_depth()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return V0;
+ vunits min, max;
+ last->vertical_extent(&min, &max);
+ return max;
+}
+
+hunits environment::get_text_length()
+{
+ hunits n = line == 0 ? H0 : width_total;
+ if (current_tab)
+ n += tab_width;
+ return n;
+}
+
+hunits environment::get_prev_text_length()
+{
+ return prev_text_length;
+}
+
+
+static int sb_reg_contents = 0;
+static int st_reg_contents = 0;
+static int ct_reg_contents = 0;
+static int rsb_reg_contents = 0;
+static int rst_reg_contents = 0;
+static int skw_reg_contents = 0;
+static int ssc_reg_contents = 0;
+
+void environment::width_registers()
+{
+ // this is used to implement \w; it sets the st, sb, ct registers
+ vunits min = 0, max = 0, cur = 0;
+ int character_type = 0;
+ ssc_reg_contents = line ? line->subscript_correction().to_units() : 0;
+ skw_reg_contents = line ? line->skew().to_units() : 0;
+ line = reverse_node_list(line);
+ vunits real_min = V0;
+ vunits real_max = V0;
+ vunits v1, v2;
+ for (node *tem = line; tem; tem = tem->next) {
+ tem->vertical_extent(&v1, &v2);
+ v1 += cur;
+ if (v1 < real_min)
+ real_min = v1;
+ v2 += cur;
+ if (v2 > real_max)
+ real_max = v2;
+ if ((cur += tem->vertical_width()) < min)
+ min = cur;
+ else if (cur > max)
+ max = cur;
+ character_type |= tem->character_type();
+ }
+ line = reverse_node_list(line);
+ st_reg_contents = -min.to_units();
+ sb_reg_contents = -max.to_units();
+ rst_reg_contents = -real_min.to_units();
+ rsb_reg_contents = -real_max.to_units();
+ ct_reg_contents = character_type;
+}
+
+node *environment::extract_output_line()
+{
+ if (current_tab)
+ wrap_up_tab();
+ node *n = line;
+ line = 0;
+ return n;
+}
+
+/* environment related requests */
+
+void environment_switch()
+{
+ int pop = 0; // 1 means pop, 2 means pop but no error message on underflow
+ if (curenv->is_dummy())
+ error("can't switch environments when current environment is dummy");
+ else if (!has_arg())
+ pop = 1;
+ else {
+ symbol nm;
+ if (!tok.delimiter()) {
+ // It looks like a number.
+ int n;
+ if (get_integer(&n)) {
+ if (n >= 0 && n < NENVIRONMENTS) {
+ env_stack = new env_list(curenv, env_stack);
+ if (env_table[n] == 0)
+ env_table[n] = new environment(itoa(n));
+ curenv = env_table[n];
+ }
+ else
+ nm = itoa(n);
+ }
+ else
+ pop = 2;
+ }
+ else {
+ nm = get_long_name(1);
+ if (nm.is_null())
+ pop = 2;
+ }
+ if (!nm.is_null()) {
+ environment *e = (environment *)env_dictionary.lookup(nm);
+ if (!e) {
+ e = new environment(nm);
+ (void)env_dictionary.lookup(nm, e);
+ }
+ env_stack = new env_list(curenv, env_stack);
+ curenv = e;
+ }
+ }
+ if (pop) {
+ if (env_stack == 0) {
+ if (pop == 1)
+ error("environment stack underflow");
+ }
+ else {
+ curenv = env_stack->env;
+ env_list *tem = env_stack;
+ env_stack = env_stack->next;
+ delete tem;
+ }
+ }
+ skip_line();
+}
+
+
+static symbol P_symbol("P");
+
+void font_change()
+{
+ symbol s = get_name();
+ int is_number = 1;
+ if (s.is_null() || s == P_symbol) {
+ s = P_symbol;
+ is_number = 0;
+ }
+ else {
+ for (const char *p = s.contents(); p != 0 && *p != 0; p++)
+ if (!csdigit(*p)) {
+ is_number = 0;
+ break;
+ }
+ }
+ if (is_number)
+ curenv->set_font(atoi(s.contents()));
+ else
+ curenv->set_font(s);
+ skip_line();
+}
+
+void family_change()
+{
+ symbol s = get_name(1);
+ if (!s.is_null())
+ curenv->set_family(s);
+ skip_line();
+}
+
+void point_size()
+{
+ int n;
+ if (has_arg() && get_number(&n, 'z', curenv->get_requested_point_size())) {
+ if (n <= 0)
+ n = 1;
+ curenv->set_size(n);
+ }
+ else
+ curenv->set_size(0);
+ skip_line();
+}
+
+void space_size()
+{
+ int n;
+ if (get_integer(&n)) {
+ curenv->space_size = n;
+ if (has_arg() && get_integer(&n))
+ curenv->sentence_space_size = n;
+ else
+ curenv->sentence_space_size = curenv->space_size;
+ }
+ skip_line();
+}
+
+void fill()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->fill = 1;
+ tok.next();
+}
+
+void no_fill()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->fill = 0;
+ tok.next();
+}
+
+void center()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ else if (n < 0)
+ n = 0;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->right_justify_lines = 0;
+ curenv->center_lines = n;
+ tok.next();
+}
+
+void right_justify()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ else if (n < 0)
+ n = 0;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->center_lines = 0;
+ curenv->right_justify_lines = n;
+ tok.next();
+}
+
+void line_length()
+{
+ hunits temp;
+ if (has_arg() && get_hunits(&temp, 'm', curenv->line_length)) {
+ if (temp < H0) {
+ warning(WARN_RANGE, "bad line length %1u", temp.to_units());
+ temp = H0;
+ }
+ }
+ else
+ temp = curenv->prev_line_length;
+ curenv->prev_line_length = curenv->line_length;
+ curenv->line_length = temp;
+ skip_line();
+}
+
+void title_length()
+{
+ hunits temp;
+ if (has_arg() && get_hunits(&temp, 'm', curenv->title_length)) {
+ if (temp < H0) {
+ warning(WARN_RANGE, "bad title length %1u", temp.to_units());
+ temp = H0;
+ }
+ }
+ else
+ temp = curenv->prev_title_length;
+ curenv->prev_title_length = curenv->title_length;
+ curenv->title_length = temp;
+ skip_line();
+}
+
+void vertical_spacing()
+{
+ vunits temp;
+ if (has_arg() && get_vunits(&temp, 'p', curenv->vertical_spacing)) {
+ if (temp <= V0) {
+ warning(WARN_RANGE, "vertical spacing must be greater than 0");
+ temp = vresolution;
+ }
+ }
+ else
+ temp = curenv->prev_vertical_spacing;
+ curenv->prev_vertical_spacing = curenv->vertical_spacing;
+ curenv->vertical_spacing = temp;
+ skip_line();
+}
+
+void line_spacing()
+{
+ int temp;
+ if (has_arg() && get_integer(&temp)) {
+ if (temp < 1) {
+ warning(WARN_RANGE, "value %1 out of range: interpreted as 1", temp);
+ temp = 1;
+ }
+ }
+ else
+ temp = curenv->prev_line_spacing;
+ curenv->prev_line_spacing = curenv->line_spacing;
+ curenv->line_spacing = temp;
+ skip_line();
+}
+
+void indent()
+{
+ hunits temp;
+ if (has_arg() && get_hunits(&temp, 'm', curenv->indent)) {
+ if (temp < H0) {
+ warning(WARN_RANGE, "indent cannot be negative");
+ temp = H0;
+ }
+ }
+ else
+ temp = curenv->prev_indent;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->have_temporary_indent = 0;
+ curenv->prev_indent = curenv->indent;
+ curenv->indent = temp;
+ tok.next();
+}
+
+void temporary_indent()
+{
+ int err = 0;
+ hunits temp;
+ if (!get_hunits(&temp, 'm', curenv->get_indent()))
+ err = 1;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (temp < H0) {
+ warning(WARN_RANGE, "total indent cannot be negative");
+ temp = H0;
+ }
+ if (!err) {
+ curenv->temporary_indent = temp;
+ curenv->have_temporary_indent = 1;
+ }
+ tok.next();
+}
+
+void underline()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ if (n <= 0) {
+ if (curenv->underline_lines > 0) {
+ curenv->prev_fontno = curenv->fontno;
+ curenv->fontno = curenv->pre_underline_fontno;
+ }
+ curenv->underline_lines = 0;
+ }
+ else {
+ curenv->underline_lines = n;
+ curenv->pre_underline_fontno = curenv->fontno;
+ curenv->fontno = get_underline_fontno();
+ }
+ skip_line();
+}
+
+void control_char()
+{
+ curenv->control_char = '.';
+ if (has_arg()) {
+ if (tok.ch() == 0)
+ error("bad control character");
+ else
+ curenv->control_char = tok.ch();
+ }
+ skip_line();
+}
+
+void no_break_control_char()
+{
+ curenv->no_break_control_char = '\'';
+ if (has_arg()) {
+ if (tok.ch() == 0)
+ error("bad control character");
+ else
+ curenv->no_break_control_char = tok.ch();
+ }
+ skip_line();
+}
+
+void margin_character()
+{
+ charinfo *ci = get_optional_char();
+ if (ci) {
+ node *nd = curenv->make_char_node(ci);
+ if (nd) {
+ delete curenv->margin_character_node;
+ curenv->margin_character_node = nd;
+ curenv->margin_character_flags = (MARGIN_CHARACTER_ON
+ |MARGIN_CHARACTER_NEXT);
+ hunits d;
+ if (has_arg() && get_hunits(&d, 'm'))
+ curenv->margin_character_distance = d;
+ }
+ }
+ else {
+ curenv->margin_character_flags &= ~MARGIN_CHARACTER_ON;
+ if (curenv->margin_character_flags == 0) {
+ delete curenv->margin_character_node;
+ curenv->margin_character_node = 0;
+ }
+ }
+ skip_line();
+}
+
+void number_lines()
+{
+ delete_node_list(curenv->numbering_nodes);
+ curenv->numbering_nodes = 0;
+ if (has_arg()) {
+ node *nd = 0;
+ for (int i = '9'; i >= '0'; i--) {
+ node *tem = make_node(charset_table[i], curenv);
+ if (!tem) {
+ skip_line();
+ return;
+ }
+ tem->next = nd;
+ nd = tem;
+ }
+ curenv->numbering_nodes = nd;
+ curenv->line_number_digit_width = env_digit_width(curenv);
+ int n;
+ if (!tok.delimiter()) {
+ if (get_integer(&n, next_line_number)) {
+ next_line_number = n;
+ if (next_line_number < 0) {
+ warning(WARN_RANGE, "negative line number");
+ next_line_number = 0;
+ }
+ }
+ }
+ else
+ while (!tok.space() && !tok.newline() && !tok.eof())
+ tok.next();
+ if (has_arg()) {
+ if (!tok.delimiter()) {
+ if (get_integer(&n)) {
+ if (n <= 0) {
+ warning(WARN_RANGE, "negative or zero line number multiple");
+ }
+ else
+ curenv->line_number_multiple = n;
+ }
+ }
+ else
+ while (!tok.space() && !tok.newline() && !tok.eof())
+ tok.next();
+ if (has_arg()) {
+ if (!tok.delimiter()) {
+ if (get_integer(&n))
+ curenv->number_text_separation = n;
+ }
+ else
+ while (!tok.space() && !tok.newline() && !tok.eof())
+ tok.next();
+ if (has_arg() && !tok.delimiter() && get_integer(&n))
+ curenv->line_number_indent = n;
+ }
+ }
+ }
+ skip_line();
+}
+
+void no_number()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->no_number_count = n > 0 ? n : 0;
+ else
+ curenv->no_number_count = 1;
+ skip_line();
+}
+
+void no_hyphenate()
+{
+ curenv->hyphenation_flags = 0;
+ skip_line();
+}
+
+void hyphenate_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->hyphenation_flags = n;
+ else
+ curenv->hyphenation_flags = 1;
+ skip_line();
+}
+
+void hyphen_char()
+{
+ curenv->hyphen_indicator_char = get_optional_char();
+ skip_line();
+}
+
+void hyphen_line_max_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->hyphen_line_max = n;
+ else
+ curenv->hyphen_line_max = -1;
+ skip_line();
+}
+
+void environment::interrupt()
+{
+ if (!dummy) {
+ add_node(new transparent_dummy_node);
+ interrupted = 1;
+ }
+}
+
+void environment::newline()
+{
+ if (underline_lines > 0) {
+ if (--underline_lines == 0) {
+ prev_fontno = fontno;
+ fontno = pre_underline_fontno;
+ }
+ }
+ if (current_field)
+ wrap_up_field();
+ if (current_tab)
+ wrap_up_tab();
+ // strip trailing spaces
+ while (line != 0 && line->discardable()) {
+ width_total -= line->width();
+ space_total -= line->nspaces();
+ node *tem = line;
+ line = line->next;
+ delete tem;
+ }
+ node *to_be_output = 0;
+ hunits to_be_output_width;
+ prev_line_interrupted = 0;
+ if (dummy)
+ space_newline();
+ else if (interrupted) {
+ interrupted = 0;
+ // see environment::final_break
+ prev_line_interrupted = exit_started ? 2 : 1;
+ }
+ else if (center_lines > 0) {
+ --center_lines;
+ hunits x = target_text_length - width_total;
+ if (x > H0)
+ saved_indent += x/2;
+ to_be_output = line;
+ to_be_output_width = width_total;
+ line = 0;
+ }
+ else if (right_justify_lines > 0) {
+ --right_justify_lines;
+ hunits x = target_text_length - width_total;
+ if (x > H0)
+ saved_indent += x;
+ to_be_output = line;
+ to_be_output_width = width_total;
+ line = 0;
+ }
+ else if (fill)
+ space_newline();
+ else {
+ to_be_output = line;
+ to_be_output_width = width_total;
+ line = 0;
+ }
+ input_line_start = line == 0 ? H0 : width_total;
+ if (to_be_output) {
+ output_line(to_be_output, to_be_output_width);
+ hyphen_line_count = 0;
+ }
+ if (input_trap_count > 0) {
+ if (--input_trap_count == 0)
+ spring_trap(input_trap);
+ }
+}
+
+void environment::output_line(node *n, hunits width)
+{
+ prev_text_length = width;
+ if (margin_character_flags) {
+ hunits d = line_length + margin_character_distance - saved_indent - width;
+ if (d > 0) {
+ n = new hmotion_node(d, n);
+ width += d;
+ }
+ margin_character_flags &= ~MARGIN_CHARACTER_NEXT;
+ node *tem;
+ if (!margin_character_flags) {
+ tem = margin_character_node;
+ margin_character_node = 0;
+ }
+ else
+ tem = margin_character_node->copy();
+ tem->next = n;
+ n = tem;
+ width += tem->width();
+ }
+ node *nn = 0;
+ while (n != 0) {
+ node *tem = n->next;
+ n->next = nn;
+ nn = n;
+ n = tem;
+ }
+ if (!saved_indent.is_zero())
+ nn = new hmotion_node(saved_indent, nn);
+ width += saved_indent;
+ if (no_number_count > 0)
+ --no_number_count;
+ else if (numbering_nodes) {
+ hunits w = (line_number_digit_width
+ *(3+line_number_indent+number_text_separation));
+ if (next_line_number % line_number_multiple != 0)
+ nn = new hmotion_node(w, nn);
+ else {
+ hunits x = w;
+ nn = new hmotion_node(number_text_separation*line_number_digit_width,
+ nn);
+ x -= number_text_separation*line_number_digit_width;
+ char buf[30];
+ sprintf(buf, "%3d", next_line_number);
+ for (char *p = strchr(buf, '\0') - 1; p >= buf && *p != ' '; --p) {
+ node *gn = numbering_nodes;
+ for (int count = *p - '0'; count > 0; count--)
+ gn = gn->next;
+ gn = gn->copy();
+ x -= gn->width();
+ gn->next = nn;
+ nn = gn;
+ }
+ nn = new hmotion_node(x, nn);
+ }
+ width += w;
+ ++next_line_number;
+ }
+ output(nn, !fill, vertical_spacing, line_spacing, width);
+}
+
+void environment::start_line()
+{
+ assert(line == 0);
+ discarding = 0;
+ line = new line_start_node;
+ if (have_temporary_indent) {
+ saved_indent = temporary_indent;
+ have_temporary_indent = 0;
+ }
+ else
+ saved_indent = indent;
+ target_text_length = line_length - saved_indent;
+ width_total = H0;
+ space_total = 0;
+}
+
+hunits environment::get_hyphenation_space()
+{
+ return hyphenation_space;
+}
+
+void hyphenation_space_request()
+{
+ hunits n;
+ if (get_hunits(&n, 'm')) {
+ if (n < H0) {
+ warning(WARN_RANGE, "hyphenation space cannot be negative");
+ n = H0;
+ }
+ curenv->hyphenation_space = n;
+ }
+ skip_line();
+}
+
+hunits environment::get_hyphenation_margin()
+{
+ return hyphenation_margin;
+}
+
+void hyphenation_margin_request()
+{
+ hunits n;
+ if (get_hunits(&n, 'm')) {
+ if (n < H0) {
+ warning(WARN_RANGE, "hyphenation margin cannot be negative");
+ n = H0;
+ }
+ curenv->hyphenation_margin = n;
+ }
+ skip_line();
+}
+
+breakpoint *environment::choose_breakpoint()
+{
+ hunits x = width_total;
+ int s = space_total;
+ node *n = line;
+ breakpoint *best_bp = 0; // the best breakpoint so far
+ int best_bp_fits = 0;
+ while (n != 0) {
+ x -= n->width();
+ s -= n->nspaces();
+ breakpoint *bp = n->get_breakpoints(x, s);
+ while (bp != 0) {
+ if (bp->width <= target_text_length) {
+ if (!bp->hyphenated) {
+ breakpoint *tem = bp->next;
+ bp->next = 0;
+ while (tem != 0) {
+ breakpoint *tem1 = tem;
+ tem = tem->next;
+ delete tem1;
+ }
+ if (best_bp_fits
+ // Decide whether to use the hyphenated breakpoint.
+ && (hyphen_line_max < 0
+ // Only choose the hyphenated breakpoint if it would not
+ // exceed the maximum number of consecutive hyphenated
+ // lines.
+ || hyphen_line_count + 1 <= hyphen_line_max)
+ && !(adjust_mode == ADJUST_BOTH
+ // Don't choose the hyphenated breakpoint if the line
+ // can be justified by adding no more than
+ // hyphenation_space to any word space.
+ ? (bp->nspaces > 0
+ && (((target_text_length - bp->width
+ + (bp->nspaces - 1)*hresolution)/bp->nspaces)
+ <= hyphenation_space))
+ // Don't choose the hyphenated breakpoint if the line
+ // is no more than hyphenation_margin short.
+ : target_text_length - bp->width <= hyphenation_margin)) {
+ delete bp;
+ return best_bp;
+ }
+ if (best_bp)
+ delete best_bp;
+ return bp;
+ }
+ else {
+ if ((adjust_mode == ADJUST_BOTH
+ ? hyphenation_space == H0
+ : hyphenation_margin == H0)
+ && (hyphen_line_max < 0
+ || hyphen_line_count + 1 <= hyphen_line_max)) {
+ // No need to consider a non-hyphenated breakpoint.
+ if (best_bp)
+ delete best_bp;
+ return bp;
+ }
+ // It fits but it's hyphenated.
+ if (!best_bp_fits) {
+ if (best_bp)
+ delete best_bp;
+ best_bp = bp;
+ bp = bp->next;
+ best_bp_fits = 1;
+ }
+ else {
+ breakpoint *tem = bp;
+ bp = bp->next;
+ delete tem;
+ }
+ }
+ }
+ else {
+ if (best_bp)
+ delete best_bp;
+ best_bp = bp;
+ bp = bp->next;
+ }
+ }
+ n = n->next;
+ }
+ if (best_bp) {
+ if (!best_bp_fits)
+ warning(WARN_BREAK, "can't break line");
+ return best_bp;
+ }
+ return 0;
+}
+
+void environment::hyphenate_line()
+{
+ if (line == 0)
+ return;
+ hyphenation_type prev_type = line->get_hyphenation_type();
+ for (node **startp = &line->next; *startp != 0; startp = &(*startp)->next) {
+ hyphenation_type this_type = (*startp)->get_hyphenation_type();
+ if (prev_type == HYPHEN_BOUNDARY && this_type == HYPHEN_MIDDLE)
+ break;
+ prev_type = this_type;
+ }
+ if (*startp == 0)
+ return;
+ node *tem = *startp;
+ int i = 0;
+ do {
+ ++i;
+ tem = tem->next;
+ } while (tem != 0 && tem->get_hyphenation_type() == HYPHEN_MIDDLE);
+ int inhibit = (tem != 0 && tem->get_hyphenation_type() == HYPHEN_INHIBIT);
+ node *end = tem;
+ hyphen_list *sl = 0;
+ tem = *startp;
+ node *forward = 0;
+ while (tem != end) {
+ sl = tem->get_hyphen_list(sl);
+ node *tem1 = tem;
+ tem = tem->next;
+ tem1->next = forward;
+ forward = tem1;
+ }
+ if (!inhibit) {
+ // this is for characters like hyphen and emdash
+ int prev_code = 0;
+ for (hyphen_list *h = sl; h; h = h->next) {
+ h->breakable = (prev_code != 0
+ && h->next != 0
+ && h->next->hyphenation_code != 0);
+ prev_code = h->hyphenation_code;
+ }
+ }
+ if (hyphenation_flags != 0
+ && !inhibit
+ // this may not be right if we have extra space on this line
+ && !((hyphenation_flags & HYPHEN_LAST_LINE)
+ && curdiv->distance_to_next_trap() <= line_spacing*vertical_spacing)
+ && i >= 4)
+ hyphenate(sl, hyphenation_flags);
+ while (forward != 0) {
+ node *tem1 = forward;
+ forward = forward->next;
+ tem1->next = 0;
+ tem = tem1->add_self(tem, &sl);
+ }
+ *startp = tem;
+}
+
+static node *node_list_reverse(node *n)
+{
+ node *res = 0;
+ while (n) {
+ node *tem = n;
+ n = n->next;
+ tem->next = res;
+ res = tem;
+ }
+ return res;
+}
+
+static void distribute_space(node *n, int nspaces, hunits desired_space,
+ int force_reverse = 0)
+{
+ static int reverse = 0;
+ if (force_reverse || reverse)
+ n = node_list_reverse(n);
+ for (node *tem = n; tem; tem = tem->next)
+ tem->spread_space(&nspaces, &desired_space);
+ if (force_reverse || reverse)
+ (void)node_list_reverse(n);
+ if (!force_reverse)
+ reverse = !reverse;
+ assert(desired_space.is_zero() && nspaces == 0);
+}
+
+void environment::possibly_break_line(int forced)
+{
+ if (!fill || current_tab || current_field || dummy)
+ return;
+ while (line != 0 && (forced || width_total > target_text_length)) {
+ hyphenate_line();
+ breakpoint *bp = choose_breakpoint();
+ if (bp == 0)
+ // we'll find one eventually
+ return;
+ node *pre, *post;
+ node **ndp = &line;
+ while (*ndp != bp->nd)
+ ndp = &(*ndp)->next;
+ bp->nd->split(bp->index, &pre, &post);
+ *ndp = post;
+ hunits extra_space_width = H0;
+ switch(adjust_mode) {
+ case ADJUST_BOTH:
+ if (bp->nspaces != 0)
+ extra_space_width = target_text_length - bp->width;
+ break;
+ case ADJUST_CENTER:
+ saved_indent += (target_text_length - bp->width)/2;
+ break;
+ case ADJUST_RIGHT:
+ saved_indent += target_text_length - bp->width;
+ break;
+ }
+ distribute_space(pre, bp->nspaces, extra_space_width);
+ hunits output_width = bp->width + extra_space_width;
+ input_line_start -= output_width;
+ if (bp->hyphenated)
+ hyphen_line_count++;
+ else
+ hyphen_line_count = 0;
+ delete bp;
+ space_total = 0;
+ width_total = 0;
+ node *first_non_discardable = 0;
+ for (node *tem = line; tem != 0; tem = tem->next)
+ if (!tem->discardable())
+ first_non_discardable = tem;
+ node *to_be_discarded;
+ if (first_non_discardable) {
+ to_be_discarded = first_non_discardable->next;
+ first_non_discardable->next = 0;
+ for (tem = line; tem != 0; tem = tem->next) {
+ width_total += tem->width();
+ space_total += tem->nspaces();
+ }
+ discarding = 0;
+ }
+ else {
+ discarding = 1;
+ to_be_discarded = line;
+ line = 0;
+ }
+ // Do output_line() here so that line will be 0 iff the
+ // the environment will be empty.
+ output_line(pre, output_width);
+ while (to_be_discarded != 0) {
+ tem = to_be_discarded;
+ to_be_discarded = to_be_discarded->next;
+ input_line_start -= tem->width();
+ delete tem;
+ }
+ if (line != 0) {
+ if (have_temporary_indent) {
+ saved_indent = temporary_indent;
+ have_temporary_indent = 0;
+ }
+ else
+ saved_indent = indent;
+ target_text_length = line_length - saved_indent;
+ }
+ }
+}
+
+/*
+Do the break at the end of input after the end macro (if any).
+
+Unix troff behaves as follows: if the last line is
+
+foo bar\c
+
+it will output foo on the current page, and bar on the next page;
+if the last line is
+
+foo\c
+
+or
+
+foo bar
+
+everything will be output on the current page. This behaviour must be
+considered a bug.
+
+The problem is that some macro packages rely on this. For example,
+the ATK macros have an end macro that emits \c if it needs to print a
+table of contents but doesn't do a 'bp in the end macro; instead the
+'bp is done in the bottom of page trap. This works with Unix troff,
+provided that the current environment is not empty at the end of the
+input file.
+
+The following will make macro packages that do that sort of thing work
+even if the current environment is empty at the end of the input file.
+If the last input line used \c and this line occurred in the end macro,
+then we'll force everything out on the current page, but we'll make
+sure that the environment isn't empty so that we won't exit at the
+bottom of this page.
+*/
+
+void environment::final_break()
+{
+ if (prev_line_interrupted == 2) {
+ do_break();
+ add_node(new transparent_dummy_node);
+ }
+ else
+ do_break();
+}
+
+void environment::do_break()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ topdiv->begin_page();
+ return;
+ }
+ if (current_tab)
+ wrap_up_tab();
+ if (line) {
+ line = new space_node(H0, line); // this is so that hyphenation works
+ space_total++;
+ possibly_break_line();
+ }
+ while (line != 0 && line->discardable()) {
+ width_total -= line->width();
+ space_total -= line->nspaces();
+ node *tem = line;
+ line = line->next;
+ delete tem;
+ }
+ discarding = 0;
+ input_line_start = H0;
+ if (line != 0) {
+ if (fill) {
+ switch (adjust_mode) {
+ case ADJUST_CENTER:
+ saved_indent += (target_text_length - width_total)/2;
+ break;
+ case ADJUST_RIGHT:
+ saved_indent += target_text_length - width_total;
+ break;
+ }
+ }
+ node *tem = line;
+ line = 0;
+ output_line(tem, width_total);
+ hyphen_line_count = 0;
+ }
+ prev_line_interrupted = 0;
+#ifdef WIDOW_CONTROL
+ mark_last_line();
+ output_pending_lines();
+#endif /* WIDOW_CONTROL */
+}
+
+int environment::is_empty()
+{
+ return !current_tab && line == 0 && pending_lines == 0;
+}
+
+void break_request()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ tok.next();
+}
+
+void title()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_title();
+ return;
+ }
+ node *part[3];
+ hunits part_width[3];
+ part[0] = part[1] = part[2] = 0;
+ environment env(curenv);
+ environment *oldenv = curenv;
+ curenv = &env;
+ read_title_parts(part, part_width);
+ curenv = oldenv;
+ curenv->size = env.size;
+ curenv->prev_size = env.prev_size;
+ curenv->requested_size = env.requested_size;
+ curenv->prev_requested_size = env.prev_requested_size;
+ curenv->char_height = env.char_height;
+ curenv->char_slant = env.char_slant;
+ curenv->fontno = env.fontno;
+ curenv->prev_fontno = env.prev_fontno;
+ node *n = 0;
+ node *p = part[2];
+ while (p != 0) {
+ node *tem = p;
+ p = p->next;
+ tem->next = n;
+ n = tem;
+ }
+ hunits title_length(curenv->title_length);
+ hunits f = title_length - part_width[1];
+ hunits f2 = f/2;
+ n = new hmotion_node(f2 - part_width[2], n);
+ p = part[1];
+ while (p != 0) {
+ node *tem = p;
+ p = p->next;
+ tem->next = n;
+ n = tem;
+ }
+ n = new hmotion_node(f - f2 - part_width[0], n);
+ p = part[0];
+ while (p != 0) {
+ node *tem = p;
+ p = p->next;
+ tem->next = n;
+ n = tem;
+ }
+ curenv->output_title(n, !curenv->fill, curenv->vertical_spacing,
+ curenv->line_spacing, title_length);
+ curenv->hyphen_line_count = 0;
+ tok.next();
+}
+
+void adjust()
+{
+ curenv->adjust_mode |= 1;
+ if (has_arg()) {
+ switch (tok.ch()) {
+ case 'l':
+ curenv->adjust_mode = ADJUST_LEFT;
+ break;
+ case 'r':
+ curenv->adjust_mode = ADJUST_RIGHT;
+ break;
+ case 'c':
+ curenv->adjust_mode = ADJUST_CENTER;
+ break;
+ case 'b':
+ case 'n':
+ curenv->adjust_mode = ADJUST_BOTH;
+ break;
+ default:
+ int n;
+ if (get_integer(&n)) {
+ if (n < 0)
+ warning(WARN_RANGE, "negative adjustment mode");
+ else if (n > 5) {
+ curenv->adjust_mode = 5;
+ warning(WARN_RANGE, "adjustment mode `%1' out of range", n);
+ }
+ else
+ curenv->adjust_mode = n;
+ }
+ }
+ }
+ skip_line();
+}
+
+void no_adjust()
+{
+ curenv->adjust_mode &= ~1;
+ skip_line();
+}
+
+void input_trap()
+{
+ curenv->input_trap_count = 0;
+ int n;
+ if (has_arg() && get_integer(&n)) {
+ if (n <= 0)
+ warning(WARN_RANGE,
+ "number of lines for input trap must be greater than zero");
+ else {
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ curenv->input_trap_count = n;
+ curenv->input_trap = s;
+ }
+ }
+ }
+ skip_line();
+}
+
+/* tabs */
+
+// must not be R or C or L or a legitimate part of a number expression
+const char TAB_REPEAT_CHAR = 'T';
+
+struct tab {
+ tab *next;
+ hunits pos;
+ tab_type type;
+ tab(hunits, tab_type);
+ enum { BLOCK = 1024 };
+ static tab *free_list;
+ void *operator new(size_t);
+ void operator delete(void *);
+};
+
+tab *tab::free_list = 0;
+
+void *tab::operator new(size_t n)
+{
+ assert(n == sizeof(tab));
+ if (!free_list) {
+ free_list = (tab *)new char[sizeof(tab)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ tab *p = free_list;
+ free_list = (tab *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+#ifdef __GNUG__
+/* cfront can't cope with this. */
+inline
+#endif
+void tab::operator delete(void *p)
+{
+ if (p) {
+ ((tab *)p)->next = free_list;
+ free_list = (tab *)p;
+ }
+}
+
+tab::tab(hunits x, tab_type t) : next(0), pos(x), type(t)
+{
+}
+
+tab_stops::tab_stops(hunits distance, tab_type type)
+ : initial_list(0)
+{
+ repeated_list = new tab(distance, type);
+}
+
+tab_stops::~tab_stops()
+{
+ clear();
+}
+
+tab_type tab_stops::distance_to_next_tab(hunits curpos, hunits *distance)
+{
+ hunits lastpos = 0;
+ for (tab *tem = initial_list; tem && tem->pos <= curpos; tem = tem->next)
+ lastpos = tem->pos;
+ if (tem) {
+ *distance = tem->pos - curpos;
+ return tem->type;
+ }
+ if (repeated_list == 0)
+ return TAB_NONE;
+ hunits base = lastpos;
+ for (;;) {
+ for (tem = repeated_list; tem && tem->pos + base <= curpos; tem = tem->next)
+ lastpos = tem->pos;
+ if (tem) {
+ *distance = tem->pos + base - curpos;
+ return tem->type;
+ }
+ assert(lastpos > 0);
+ base += lastpos;
+ }
+ return TAB_NONE;
+}
+
+const char *tab_stops::to_string()
+{
+ static char *buf = 0;
+ static int buf_size = 0;
+ // figure out a maximum on the amount of space we can need
+ int count = 0;
+ for (tab *p = initial_list; p; p = p->next)
+ ++count;
+ for (p = repeated_list; p; p = p->next)
+ ++count;
+ // (10 for digits + 1 for u + 1 for 'C' or 'R') + 2 for ' &' + 1 for '\0'
+ int need = count*12 + 3;
+ if (buf == 0 || need > buf_size) {
+ if (buf)
+ a_delete buf;
+ buf_size = need;
+ buf = new char[buf_size];
+ }
+ char *ptr = buf;
+ for (p = initial_list; p; p = p->next) {
+ strcpy(ptr, itoa(p->pos.to_units()));
+ ptr = strchr(ptr, '\0');
+ *ptr++ = 'u';
+ *ptr = '\0';
+ switch (p->type) {
+ case TAB_LEFT:
+ break;
+ case TAB_RIGHT:
+ *ptr++ = 'R';
+ break;
+ case TAB_CENTER:
+ *ptr++ = 'C';
+ break;
+ case TAB_NONE:
+ default:
+ assert(0);
+ }
+ }
+ if (repeated_list)
+ *ptr++ = TAB_REPEAT_CHAR;
+ for (p = repeated_list; p; p = p->next) {
+ strcpy(ptr, itoa(p->pos.to_units()));
+ ptr = strchr(ptr, '\0');
+ *ptr++ = 'u';
+ *ptr = '\0';
+ switch (p->type) {
+ case TAB_LEFT:
+ break;
+ case TAB_RIGHT:
+ *ptr++ = 'R';
+ break;
+ case TAB_CENTER:
+ *ptr++ = 'C';
+ break;
+ case TAB_NONE:
+ default:
+ assert(0);
+ }
+ }
+ *ptr++ = '\0';
+ return buf;
+}
+
+tab_stops::tab_stops() : initial_list(0), repeated_list(0)
+{
+}
+
+tab_stops::tab_stops(const tab_stops &ts)
+ : initial_list(0), repeated_list(0)
+{
+ tab **p = &initial_list;
+ tab *t = ts.initial_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+ p = &repeated_list;
+ t = ts.repeated_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+}
+
+void tab_stops::clear()
+{
+ while (initial_list) {
+ tab *tem = initial_list;
+ initial_list = initial_list->next;
+ delete tem;
+ }
+ while (repeated_list) {
+ tab *tem = repeated_list;
+ repeated_list = repeated_list->next;
+ delete tem;
+ }
+}
+
+void tab_stops::add_tab(hunits pos, tab_type type, int repeated)
+{
+ for (tab **p = repeated ? &repeated_list : &initial_list; *p; p = &(*p)->next)
+ ;
+ *p = new tab(pos, type);
+}
+
+
+void tab_stops::operator=(const tab_stops &ts)
+{
+ clear();
+ tab **p = &initial_list;
+ tab *t = ts.initial_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+ p = &repeated_list;
+ t = ts.repeated_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+}
+
+void set_tabs()
+{
+ hunits pos;
+ hunits prev_pos = 0;
+ int first = 1;
+ int repeated = 0;
+ tab_stops tabs;
+ while (has_arg()) {
+ if (tok.ch() == TAB_REPEAT_CHAR) {
+ tok.next();
+ repeated = 1;
+ prev_pos = 0;
+ }
+ if (!get_hunits(&pos, 'm', prev_pos))
+ break;
+ tab_type type = TAB_LEFT;
+ if (tok.ch() == 'C') {
+ tok.next();
+ type = TAB_CENTER;
+ }
+ else if (tok.ch() == 'R') {
+ tok.next();
+ type = TAB_RIGHT;
+ }
+ else if (tok.ch() == 'L') {
+ tok.next();
+ }
+ if (pos <= prev_pos && !first)
+ warning(WARN_RANGE,
+ "positions of tab stops must be strictly increasing");
+ else {
+ tabs.add_tab(pos, type, repeated);
+ prev_pos = pos;
+ first = 0;
+ }
+ }
+ curenv->tabs = tabs;
+ skip_line();
+}
+
+const char *environment::get_tabs()
+{
+ return tabs.to_string();
+}
+
+#if 0
+tab_stops saved_tabs;
+
+void tabs_save()
+{
+ saved_tabs = curenv->tabs;
+ skip_line();
+}
+
+void tabs_restore()
+{
+ curenv->tabs = saved_tabs;
+ skip_line();
+}
+#endif
+
+tab_type environment::distance_to_next_tab(hunits *distance)
+{
+ return curenv->tabs.distance_to_next_tab(get_input_line_position(), distance);
+}
+
+void field_characters()
+{
+ field_delimiter_char = get_optional_char();
+ if (field_delimiter_char)
+ padding_indicator_char = get_optional_char();
+ else
+ padding_indicator_char = 0;
+ skip_line();
+}
+
+void environment::wrap_up_tab()
+{
+ if (!current_tab)
+ return;
+ if (line == 0)
+ start_line();
+ hunits tab_amount;
+ switch (current_tab) {
+ case TAB_RIGHT:
+ tab_amount = tab_distance - tab_width;
+ line = make_tab_node(tab_amount, line);
+ break;
+ case TAB_CENTER:
+ tab_amount = tab_distance - tab_width/2;
+ line = make_tab_node(tab_amount, line);
+ break;
+ case TAB_NONE:
+ case TAB_LEFT:
+ default:
+ assert(0);
+ }
+ width_total += tab_amount;
+ width_total += tab_width;
+ if (current_field) {
+ if (tab_precedes_field) {
+ pre_field_width += tab_amount;
+ tab_precedes_field = 0;
+ }
+ field_distance -= tab_amount;
+ field_spaces += tab_field_spaces;
+ }
+ if (tab_contents != 0) {
+ for (node *tem = tab_contents; tem->next != 0; tem = tem->next)
+ ;
+ tem->next = line;
+ line = tab_contents;
+ }
+ tab_field_spaces = 0;
+ tab_contents = 0;
+ tab_width = H0;
+ tab_distance = H0;
+ current_tab = TAB_NONE;
+}
+
+node *environment::make_tab_node(hunits d, node *next)
+{
+ if (leader_node != 0 && d < 0) {
+ error("motion generated by leader cannot be negative");
+ delete leader_node;
+ leader_node = 0;
+ }
+ if (!leader_node)
+ return new hmotion_node(d, next);
+ node *n = new hline_node(d, leader_node, next);
+ leader_node = 0;
+ return n;
+}
+
+void environment::handle_tab(int is_leader)
+{
+ hunits d;
+ if (current_tab)
+ wrap_up_tab();
+ charinfo *ci = is_leader ? leader_char : tab_char;
+ delete leader_node;
+ leader_node = ci ? make_char_node(ci) : 0;
+ tab_type t = distance_to_next_tab(&d);
+ switch (t) {
+ case TAB_NONE:
+ return;
+ case TAB_LEFT:
+ add_node(make_tab_node(d));
+ return;
+ case TAB_RIGHT:
+ case TAB_CENTER:
+ tab_width = 0;
+ tab_distance = d;
+ tab_contents = 0;
+ current_tab = t;
+ tab_field_spaces = 0;
+ return;
+ default:
+ assert(0);
+ }
+}
+
+void environment::start_field()
+{
+ assert(!current_field);
+ hunits d;
+ if (distance_to_next_tab(&d) != TAB_NONE) {
+ pre_field_width = get_text_length();
+ field_distance = d;
+ current_field = 1;
+ field_spaces = 0;
+ tab_field_spaces = 0;
+ for (node *p = line; p; p = p->next)
+ if (p->nspaces()) {
+ p->freeze_space();
+ space_total--;
+ }
+ tab_precedes_field = current_tab != TAB_NONE;
+ }
+ else
+ error("zero field width");
+}
+
+void environment::wrap_up_field()
+{
+ if (!current_tab && field_spaces == 0)
+ add_padding();
+ hunits padding = field_distance - (get_text_length() - pre_field_width);
+ if (current_tab && tab_field_spaces != 0) {
+ hunits tab_padding = scale(padding,
+ tab_field_spaces,
+ field_spaces + tab_field_spaces);
+ padding -= tab_padding;
+ distribute_space(tab_contents, tab_field_spaces, tab_padding, 1);
+ tab_field_spaces = 0;
+ tab_width += tab_padding;
+ }
+ if (field_spaces != 0) {
+ distribute_space(line, field_spaces, padding, 1);
+ width_total += padding;
+ if (current_tab) {
+ // the start of the tab has been moved to the right by padding, so
+ tab_distance -= padding;
+ if (tab_distance <= H0) {
+ // use the next tab stop instead
+ current_tab = tabs.distance_to_next_tab(get_input_line_position()
+ - tab_width,
+ &tab_distance);
+ if (current_tab == TAB_NONE || current_tab == TAB_LEFT) {
+ width_total += tab_width;
+ if (current_tab == TAB_LEFT) {
+ line = make_tab_node(tab_distance, line);
+ width_total += tab_distance;
+ current_tab = TAB_NONE;
+ }
+ if (tab_contents != 0) {
+ for (node *tem = tab_contents; tem->next != 0; tem = tem->next)
+ ;
+ tem->next = line;
+ line = tab_contents;
+ tab_contents = 0;
+ }
+ tab_width = H0;
+ tab_distance = H0;
+ }
+ }
+ }
+ }
+ current_field = 0;
+}
+
+void environment::add_padding()
+{
+ if (current_tab) {
+ tab_contents = new space_node(H0, tab_contents);
+ tab_field_spaces++;
+ }
+ else {
+ if (line == 0)
+ start_line();
+ line = new space_node(H0, line);
+ field_spaces++;
+ }
+}
+
+typedef int (environment::*INT_FUNCP)();
+typedef vunits (environment::*VUNITS_FUNCP)();
+typedef hunits (environment::*HUNITS_FUNCP)();
+typedef const char *(environment::*STRING_FUNCP)();
+
+class int_env_reg : public reg {
+ INT_FUNCP func;
+ public:
+ int_env_reg(INT_FUNCP);
+ const char *get_string();
+ int get_value(units *val);
+};
+
+class vunits_env_reg : public reg {
+ VUNITS_FUNCP func;
+ public:
+ vunits_env_reg(VUNITS_FUNCP f);
+ const char *get_string();
+ int get_value(units *val);
+};
+
+
+class hunits_env_reg : public reg {
+ HUNITS_FUNCP func;
+ public:
+ hunits_env_reg(HUNITS_FUNCP f);
+ const char *get_string();
+ int get_value(units *val);
+};
+
+class string_env_reg : public reg {
+ STRING_FUNCP func;
+public:
+ string_env_reg(STRING_FUNCP);
+ const char *get_string();
+};
+
+int_env_reg::int_env_reg(INT_FUNCP f) : func(f)
+{
+}
+
+int int_env_reg::get_value(units *val)
+{
+ *val = (curenv->*func)();
+ return 1;
+}
+
+const char *int_env_reg::get_string()
+{
+ return itoa((curenv->*func)());
+}
+
+vunits_env_reg::vunits_env_reg(VUNITS_FUNCP f) : func(f)
+{
+}
+
+int vunits_env_reg::get_value(units *val)
+{
+ *val = (curenv->*func)().to_units();
+ return 1;
+}
+
+const char *vunits_env_reg::get_string()
+{
+ return itoa((curenv->*func)().to_units());
+}
+
+hunits_env_reg::hunits_env_reg(HUNITS_FUNCP f) : func(f)
+{
+}
+
+int hunits_env_reg::get_value(units *val)
+{
+ *val = (curenv->*func)().to_units();
+ return 1;
+}
+
+const char *hunits_env_reg::get_string()
+{
+ return itoa((curenv->*func)().to_units());
+}
+
+string_env_reg::string_env_reg(STRING_FUNCP f) : func(f)
+{
+}
+
+const char *string_env_reg::get_string()
+{
+ return (curenv->*func)();
+}
+
+class horizontal_place_reg : public general_reg {
+public:
+ horizontal_place_reg();
+ int get_value(units *);
+ void set_value(units);
+};
+
+horizontal_place_reg::horizontal_place_reg()
+{
+}
+
+int horizontal_place_reg::get_value(units *res)
+{
+ *res = curenv->get_input_line_position().to_units();
+ return 1;
+}
+
+void horizontal_place_reg::set_value(units n)
+{
+ curenv->set_input_line_position(hunits(n));
+}
+
+const char *environment::get_font_family_string()
+{
+ return family->nm.contents();
+}
+
+const char *environment::get_name_string()
+{
+ return name.contents();
+}
+
+// Convert a quantity in scaled points to ascii decimal fraction.
+
+const char *sptoa(int sp)
+{
+ assert(sp > 0);
+ assert(sizescale > 0);
+ if (sizescale == 1)
+ return itoa(sp);
+ if (sp % sizescale == 0)
+ return itoa(sp/sizescale);
+ // See if 1/sizescale is exactly representable as a decimal fraction,
+ // ie its only prime factors are 2 and 5.
+ int n = sizescale;
+ int power2 = 0;
+ while ((n & 1) == 0) {
+ n >>= 1;
+ power2++;
+ }
+ int power5 = 0;
+ while ((n % 5) == 0) {
+ n /= 5;
+ power5++;
+ }
+ if (n == 1) {
+ int decimal_point = power5 > power2 ? power5 : power2;
+ if (decimal_point <= 10) {
+ int factor = 1;
+ int t;
+ for (t = decimal_point - power2; --t >= 0;)
+ factor *= 2;
+ for (t = decimal_point - power5; --t >= 0;)
+ factor *= 5;
+ if (factor == 1 || sp <= INT_MAX/factor)
+ return iftoa(sp*factor, decimal_point);
+ }
+ }
+ double s = double(sp)/double(sizescale);
+ double factor = 10.0;
+ double val = s;
+ int decimal_point = 0;
+ do {
+ double v = ceil(s*factor);
+ if (v > INT_MAX)
+ break;
+ val = v;
+ factor *= 10.0;
+ } while (++decimal_point < 10);
+ return iftoa(int(val), decimal_point);
+}
+
+const char *environment::get_point_size_string()
+{
+ return sptoa(curenv->get_point_size());
+}
+
+const char *environment::get_requested_point_size_string()
+{
+ return sptoa(curenv->get_requested_point_size());
+}
+
+#define init_int_env_reg(name, func) \
+ number_reg_dictionary.define(name, new int_env_reg(&environment::func))
+
+#define init_vunits_env_reg(name, func) \
+ number_reg_dictionary.define(name, new vunits_env_reg(&environment::func))
+
+#define init_hunits_env_reg(name, func) \
+ number_reg_dictionary.define(name, new hunits_env_reg(&environment::func))
+
+#define init_string_env_reg(name, func) \
+ number_reg_dictionary.define(name, new string_env_reg(&environment::func))
+
+void init_env_requests()
+{
+ init_request("it", input_trap);
+ init_request("ad", adjust);
+ init_request("na", no_adjust);
+ init_request("ev", environment_switch);
+ init_request("lt", title_length);
+ init_request("ps", point_size);
+ init_request("ft", font_change);
+ init_request("fam", family_change);
+ init_request("ss", space_size);
+ init_request("fi", fill);
+ init_request("nf", no_fill);
+ init_request("ce", center);
+ init_request("rj", right_justify);
+ init_request("vs", vertical_spacing);
+ init_request("ls", line_spacing);
+ init_request("ll", line_length);
+ init_request("in", indent);
+ init_request("ti", temporary_indent);
+ init_request("ul", underline);
+ init_request("cu", underline);
+ init_request("cc", control_char);
+ init_request("c2", no_break_control_char);
+ init_request("br", break_request);
+ init_request("tl", title);
+ init_request("ta", set_tabs);
+ init_request("fc", field_characters);
+ init_request("mc", margin_character);
+ init_request("nn", no_number);
+ init_request("nm", number_lines);
+ init_request("tc", tab_character);
+ init_request("lc", leader_character);
+ init_request("hy", hyphenate_request);
+ init_request("hc", hyphen_char);
+ init_request("nh", no_hyphenate);
+ init_request("hlm", hyphen_line_max_request);
+#ifdef WIDOW_CONTROL
+ init_request("wdc", widow_control_request);
+#endif /* WIDOW_CONTROL */
+#if 0
+ init_request("tas", tabs_save);
+ init_request("tar", tabs_restore);
+#endif
+ init_request("hys", hyphenation_space_request);
+ init_request("hym", hyphenation_margin_request);
+ init_int_env_reg(".f", get_font);
+ init_int_env_reg(".b", get_bold);
+ init_hunits_env_reg(".i", get_indent);
+ init_hunits_env_reg(".in", get_saved_indent);
+ init_int_env_reg(".j", get_adjust_mode);
+ init_hunits_env_reg(".k", get_text_length);
+ init_hunits_env_reg(".l", get_line_length);
+ init_hunits_env_reg(".ll", get_saved_line_length);
+ init_int_env_reg(".L", get_line_spacing);
+ init_hunits_env_reg(".n", get_prev_text_length);
+ init_string_env_reg(".s", get_point_size_string);
+ init_string_env_reg(".sr", get_requested_point_size_string);
+ init_int_env_reg(".ps", get_point_size);
+ init_int_env_reg(".psr", get_requested_point_size);
+ init_int_env_reg(".u", get_fill);
+ init_vunits_env_reg(".v", get_vertical_spacing);
+ init_hunits_env_reg(".w", get_prev_char_width);
+ init_int_env_reg(".ss", get_space_size);
+ init_int_env_reg(".sss", get_sentence_space_size);
+ init_string_env_reg(".fam", get_font_family_string);
+ init_string_env_reg(".ev", get_name_string);
+ init_int_env_reg(".hy", get_hyphenation_flags);
+ init_int_env_reg(".hlm", get_hyphen_line_max);
+ init_int_env_reg(".hlc", get_hyphen_line_count);
+ init_hunits_env_reg(".lt", get_title_length);
+ init_string_env_reg(".tabs", get_tabs);
+ init_hunits_env_reg(".csk", get_prev_char_skew);
+ init_vunits_env_reg(".cht", get_prev_char_height);
+ init_vunits_env_reg(".cdp", get_prev_char_depth);
+ init_int_env_reg(".ce", get_center_lines);
+ init_int_env_reg(".rj", get_right_justify_lines);
+ init_hunits_env_reg(".hys", get_hyphenation_space);
+ init_hunits_env_reg(".hym", get_hyphenation_margin);
+ number_reg_dictionary.define("ln", new variable_reg(&next_line_number));
+ number_reg_dictionary.define("ct", new variable_reg(&ct_reg_contents));
+ number_reg_dictionary.define("sb", new variable_reg(&sb_reg_contents));
+ number_reg_dictionary.define("st", new variable_reg(&st_reg_contents));
+ number_reg_dictionary.define("rsb", new variable_reg(&rsb_reg_contents));
+ number_reg_dictionary.define("rst", new variable_reg(&rst_reg_contents));
+ number_reg_dictionary.define("ssc", new variable_reg(&ssc_reg_contents));
+ number_reg_dictionary.define("skw", new variable_reg(&skw_reg_contents));
+ number_reg_dictionary.define("hp", new horizontal_place_reg);
+}
+
+// Hyphenation - TeX's hyphenation algorithm with a less fancy implementation.
+
+struct trie_node;
+
+class trie {
+ trie_node *tp;
+ virtual void do_match(int len, void *val) = 0;
+ virtual void do_delete(void *) = 0;
+ void delete_trie_node(trie_node *);
+public:
+ trie() : tp(0) {}
+ virtual ~trie(); // virtual to shut up g++
+ void insert(const char *, int, void *);
+ // find calls do_match for each match it finds
+ void find(const char *pat, int patlen);
+ void clear();
+};
+
+class hyphen_trie : private trie {
+ int *h;
+ void do_match(int i, void *v);
+ void do_delete(void *v);
+ void insert_pattern(const char *pat, int patlen, int *num);
+public:
+ hyphen_trie() {}
+ ~hyphen_trie() {}
+ void hyphenate(const char *word, int len, int *hyphens);
+ void read_patterns_file(const char *name);
+};
+
+
+struct hyphenation_language {
+ symbol name;
+ dictionary exceptions;
+ hyphen_trie patterns;
+ hyphenation_language(symbol nm) : name(nm), exceptions(501) {}
+ ~hyphenation_language() { }
+};
+
+dictionary language_dictionary(5);
+hyphenation_language *current_language = 0;
+
+static void set_hyphenation_language()
+{
+ symbol nm = get_name(1);
+ if (!nm.is_null()) {
+ current_language = (hyphenation_language *)language_dictionary.lookup(nm);
+ if (!current_language) {
+ current_language = new hyphenation_language(nm);
+ (void)language_dictionary.lookup(nm, (void *)current_language);
+ }
+ }
+ skip_line();
+}
+
+const int WORD_MAX = 1024;
+
+static void hyphen_word()
+{
+ if (!current_language) {
+ error("no current hyphenation language");
+ skip_line();
+ return;
+ }
+ char buf[WORD_MAX + 1];
+ unsigned char pos[WORD_MAX + 2];
+ for (;;) {
+ tok.skip();
+ if (tok.newline() || tok.eof())
+ break;
+ int i = 0;
+ int npos = 0;
+ while (i < WORD_MAX && !tok.space() && !tok.newline() && !tok.eof()) {
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0) {
+ skip_line();
+ return;
+ }
+ tok.next();
+ if (ci->get_ascii_code() == '-') {
+ if (i > 0 && (npos == 0 || pos[npos - 1] != i))
+ pos[npos++] = i;
+ }
+ else {
+ int c = ci->get_hyphenation_code();
+ if (c == 0)
+ break;
+ buf[i++] = c;
+ }
+ }
+ if (i > 0) {
+ pos[npos] = 0;
+ buf[i] = 0;
+ unsigned char *tem = new unsigned char[npos + 1];
+ memcpy(tem, pos, npos+1);
+ tem = (unsigned char *)current_language->exceptions.lookup(symbol(buf),
+ tem);
+ if (tem)
+ a_delete tem;
+ }
+ }
+ skip_line();
+}
+
+struct trie_node {
+ char c;
+ trie_node *down;
+ trie_node *right;
+ void *val;
+ trie_node(char, trie_node *);
+};
+
+trie_node::trie_node(char ch, trie_node *p)
+: c(ch), right(p), down(0), val(0)
+{
+}
+
+trie::~trie()
+{
+ clear();
+}
+
+void trie::clear()
+{
+ delete_trie_node(tp);
+ tp = 0;
+}
+
+
+void trie::delete_trie_node(trie_node *p)
+{
+ if (p) {
+ delete_trie_node(p->down);
+ delete_trie_node(p->right);
+ if (p->val)
+ do_delete(p->val);
+ delete p;
+ }
+}
+
+void trie::insert(const char *pat, int patlen, void *val)
+{
+ trie_node **p = &tp;
+ assert(patlen > 0 && pat != 0);
+ for (;;) {
+ while (*p != 0 && (*p)->c < pat[0])
+ p = &((*p)->right);
+ if (*p == 0 || (*p)->c != pat[0])
+ *p = new trie_node(pat[0], *p);
+ if (--patlen == 0) {
+ (*p)->val = val;
+ break;
+ }
+ ++pat;
+ p = &((*p)->down);
+ }
+}
+
+void trie::find(const char *pat, int patlen)
+{
+ trie_node *p = tp;
+ for (int i = 0; p != 0 && i < patlen; i++) {
+ while (p != 0 && p->c < pat[i])
+ p = p->right;
+ if (p != 0 && p->c == pat[i]) {
+ if (p->val != 0)
+ do_match(i+1, p->val);
+ p = p->down;
+ }
+ else
+ break;
+ }
+}
+
+struct operation {
+ operation *next;
+ short distance;
+ short num;
+ operation(int, int, operation *);
+};
+
+operation::operation(int i, int j, operation *op)
+: num(i), distance(j), next(op)
+{
+}
+
+void hyphen_trie::insert_pattern(const char *pat, int patlen, int *num)
+{
+ operation *op = 0;
+ for (int i = 0; i < patlen+1; i++)
+ if (num[i] != 0)
+ op = new operation(num[i], patlen - i, op);
+ insert(pat, patlen, op);
+}
+
+void hyphen_trie::hyphenate(const char *word, int len, int *hyphens)
+{
+ for (int j = 0; j < len+1; j++)
+ hyphens[j] = 0;
+ for (j = 0; j < len - 1; j++) {
+ h = hyphens + j;
+ find(word + j, len - j);
+ }
+}
+
+inline int max(int m, int n)
+{
+ return m > n ? m : n;
+}
+
+void hyphen_trie::do_match(int i, void *v)
+{
+ operation *op = (operation *)v;
+ while (op != 0) {
+ h[i - op->distance] = max(h[i - op->distance], op->num);
+ op = op->next;
+ }
+}
+
+void hyphen_trie::do_delete(void *v)
+{
+ operation *op = (operation *)v;
+ while (op) {
+ operation *tem = op;
+ op = tem->next;
+ delete tem;
+ }
+}
+
+void hyphen_trie::read_patterns_file(const char *name)
+{
+ clear();
+ char buf[WORD_MAX];
+ int num[WORD_MAX+1];
+ errno = 0;
+ char *path = 0;
+ FILE *fp = macro_path.open_file(name, &path);
+ if (fp == 0) {
+ error("can't find hyphenation patterns file `%1'", name);
+ return;
+ }
+ int c = getc(fp);
+ for (;;) {
+ for (;;) {
+ if (c == '%') {
+ do {
+ c = getc(fp);
+ } while (c != EOF && c != '\n');
+ }
+ if (c == EOF || !csspace(c))
+ break;
+ c = getc(fp);
+ }
+ if (c == EOF)
+ break;
+ int i = 0;
+ num[0] = 0;
+ do {
+ if (csdigit(c))
+ num[i] = c - '0';
+ else {
+ buf[i++] = c;
+ num[i] = 0;
+ }
+ c = getc(fp);
+ } while (i < WORD_MAX && c != EOF && !csspace(c) && c != '%');
+ insert_pattern(buf, i, num);
+ }
+ fclose(fp);
+ a_delete path;
+ return;
+}
+
+void hyphenate(hyphen_list *h, unsigned flags)
+{
+ if (!current_language)
+ return;
+ while (h && h->hyphenation_code == 0)
+ h = h->next;
+ int len = 0;
+ char hbuf[WORD_MAX+2];
+ char *buf = hbuf + 1;
+ for (hyphen_list *tem = h; tem && len < WORD_MAX; tem = tem->next) {
+ if (tem->hyphenation_code != 0)
+ buf[len++] = tem->hyphenation_code;
+ else
+ break;
+ }
+ if (len > 2) {
+ buf[len] = 0;
+ unsigned char *pos = (unsigned char *)current_language->exceptions.lookup(buf);
+ if (pos != 0) {
+ int j = 0;
+ int i = 1;
+ for (tem = h; tem != 0; tem = tem->next, i++)
+ if (pos[j] == i) {
+ tem->hyphen = 1;
+ j++;
+ }
+ }
+ else {
+ hbuf[0] = hbuf[len+1] = '.';
+ int num[WORD_MAX+3];
+ current_language->patterns.hyphenate(hbuf, len+2, num);
+ int i;
+ num[2] = 0;
+ if (flags & 8)
+ num[3] = 0;
+ if (flags & 4)
+ --len;
+ for (i = 2, tem = h; i < len && tem; tem = tem->next, i++)
+ if (num[i] & 1)
+ tem->hyphen = 1;
+ }
+ }
+}
+
+static void hyphenation_patterns_file()
+{
+ symbol name = get_long_name(1);
+ if (!name.is_null()) {
+ if (!current_language)
+ error("no current hyphenation language");
+ else
+ current_language->patterns.read_patterns_file(name.contents());
+ }
+ skip_line();
+}
+
+class hyphenation_language_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *hyphenation_language_reg::get_string()
+{
+ return current_language ? current_language->name.contents() : "";
+}
+
+void init_hyphen_requests()
+{
+ init_request("hw", hyphen_word);
+ init_request("hla", set_hyphenation_language);
+ init_request("hpf", hyphenation_patterns_file);
+ number_reg_dictionary.define(".hla", new hyphenation_language_reg);
+}
diff --git a/gnu/usr.bin/groff/troff/env.h b/gnu/usr.bin/groff/troff/env.h
new file mode 100644
index 000000000000..14441e1f3aef
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/env.h
@@ -0,0 +1,327 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct size_range {
+ int min;
+ int max;
+};
+
+class font_size {
+ static size_range *size_table;
+ static int nranges;
+ int p;
+public:
+ font_size();
+ font_size(int points);
+ int to_points();
+ int to_scaled_points();
+ int to_units();
+ int operator==(font_size);
+ int operator!=(font_size);
+ static void init_size_table(int *sizes);
+};
+
+inline font_size::font_size() : p(0)
+{
+}
+
+inline int font_size::operator==(font_size fs)
+{
+ return p == fs.p;
+}
+
+inline int font_size::operator!=(font_size fs)
+{
+ return p != fs.p;
+}
+
+inline int font_size::to_scaled_points()
+{
+ return p;
+}
+
+inline int font_size::to_points()
+{
+ return p/sizescale;
+}
+
+struct environment;
+
+hunits env_digit_width(environment *);
+hunits env_space_width(environment *);
+hunits env_sentence_space_width(environment *);
+hunits env_narrow_space_width(environment *);
+hunits env_half_narrow_space_width(environment *);
+
+struct tab;
+
+enum tab_type { TAB_NONE, TAB_LEFT, TAB_CENTER, TAB_RIGHT };
+
+class tab_stops {
+ tab *initial_list;
+ tab *repeated_list;
+public:
+ tab_stops();
+ tab_stops(hunits distance, tab_type type);
+ tab_stops(const tab_stops &);
+ ~tab_stops();
+ void operator=(const tab_stops &);
+ tab_type distance_to_next_tab(hunits pos, hunits *distance);
+ void clear();
+ void add_tab(hunits pos, tab_type type, int repeated);
+ const char *to_string();
+};
+
+const unsigned MARGIN_CHARACTER_ON = 1;
+const unsigned MARGIN_CHARACTER_NEXT = 2;
+
+struct charinfo;
+struct node;
+struct breakpoint;
+struct font_family;
+struct pending_output_line;
+
+class environment {
+ int dummy; // dummy environment used for \w
+ hunits prev_line_length;
+ hunits line_length;
+ hunits prev_title_length;
+ hunits title_length;
+ font_size prev_size;
+ font_size size;
+ int requested_size;
+ int prev_requested_size;
+ int char_height;
+ int char_slant;
+ int prev_fontno;
+ int fontno;
+ font_family *prev_family;
+ font_family *family;
+ int space_size; // in 36ths of an em
+ int sentence_space_size; // same but for spaces at the end of sentences
+ int adjust_mode;
+ int fill;
+ int interrupted;
+ int prev_line_interrupted;
+ int center_lines;
+ int right_justify_lines;
+ vunits prev_vertical_spacing;
+ vunits vertical_spacing;
+ int prev_line_spacing;
+ int line_spacing;
+ hunits prev_indent;
+ hunits indent;
+ hunits temporary_indent;
+ int have_temporary_indent;
+ hunits saved_indent;
+ hunits target_text_length;
+ int pre_underline_fontno;
+ int underline_lines;
+ symbol input_trap;
+ int input_trap_count;
+ node *line; // in reverse order
+ hunits prev_text_length;
+ hunits width_total;
+ int space_total;
+ hunits input_line_start;
+ tab_stops tabs;
+ node *tab_contents;
+ hunits tab_width;
+ hunits tab_distance;
+ tab_type current_tab;
+ node *leader_node;
+ charinfo *tab_char;
+ charinfo *leader_char;
+ int current_field; // is there a current field?
+ hunits field_distance;
+ hunits pre_field_width;
+ int field_spaces;
+ int tab_field_spaces;
+ int tab_precedes_field;
+ int discarding;
+ int spread_flag; // set by \p
+ unsigned margin_character_flags;
+ node *margin_character_node;
+ hunits margin_character_distance;
+ node *numbering_nodes;
+ hunits line_number_digit_width;
+ int number_text_separation; // in digit spaces
+ int line_number_indent; // in digit spaces
+ int line_number_multiple;
+ int no_number_count;
+ unsigned hyphenation_flags;
+ int hyphen_line_count;
+ int hyphen_line_max;
+ hunits hyphenation_space;
+ hunits hyphenation_margin;
+ int composite; // used for construction of composite char?
+ pending_output_line *pending_lines;
+#ifdef WIDOW_CONTROL
+ int widow_control;
+#endif /* WIDOW_CONTROL */
+
+ tab_type distance_to_next_tab(hunits *);
+ void start_line();
+ void output_line(node *, hunits);
+ void output(node *nd, int retain_size, vunits vs, int ls, hunits width);
+ void output_title(node *nd, int retain_size, vunits vs, int ls,
+ hunits width);
+#ifdef WIDOW_CONTROL
+ void mark_last_line();
+#endif /* WIDOW_CONTROL */
+ void possibly_break_line(int forced = 0);
+ breakpoint *choose_breakpoint();
+ void hyphenate_line();
+ void start_field();
+ void wrap_up_field();
+ void add_padding();
+ node *make_tab_node(hunits d, node *next = 0);
+ node *get_prev_char();
+public:
+ const symbol name;
+ unsigned char control_char;
+ unsigned char no_break_control_char;
+ charinfo *hyphen_indicator_char;
+
+ environment(symbol);
+ environment(const environment *); // for temporary environment
+ ~environment();
+ int is_dummy() { return dummy; }
+ int is_empty();
+ int is_composite() { return composite; }
+ void set_composite() { composite = 1; }
+ vunits get_vertical_spacing(); // .v
+ int get_line_spacing(); // .L
+ int get_point_size() { return size.to_scaled_points(); }
+ font_size get_font_size() { return size; }
+ int get_size() { return size.to_units(); }
+ int get_requested_point_size() { return requested_size; }
+ int get_char_height() { return char_height; }
+ int get_char_slant() { return char_slant; }
+ hunits get_digit_width();
+ int get_font() { return fontno; }; // .f
+ font_family *get_family() { return family; }
+ int get_bold(); // .b
+ int get_adjust_mode(); // .j
+ int get_fill(); // .u
+ hunits get_indent(); // .i
+ hunits get_temporary_indent();
+ hunits get_line_length(); // .l
+ hunits get_saved_line_length(); // .ll
+ hunits get_saved_indent(); // .in
+ hunits get_title_length();
+ hunits get_prev_char_width(); // .w
+ hunits get_prev_char_skew();
+ vunits get_prev_char_height();
+ vunits get_prev_char_depth();
+ hunits get_text_length(); // .k
+ hunits get_prev_text_length(); // .n
+ hunits get_space_width() { return env_space_width(this); }
+ int get_space_size() { return space_size; } // in ems/36
+ int get_sentence_space_size() { return sentence_space_size; }
+ hunits get_narrow_space_width() { return env_narrow_space_width(this); }
+ hunits get_half_narrow_space_width()
+ { return env_half_narrow_space_width(this); }
+ hunits get_input_line_position();
+ const char *get_tabs();
+ int get_hyphenation_flags();
+ int get_hyphen_line_max();
+ int get_hyphen_line_count();
+ hunits get_hyphenation_space();
+ hunits get_hyphenation_margin();
+ int get_center_lines();
+ int get_right_justify_lines();
+ int get_prev_line_interrupted() { return prev_line_interrupted; }
+ node *make_char_node(charinfo *);
+ node *extract_output_line();
+ void width_registers();
+ void wrap_up_tab();
+ void set_font(int);
+ void set_font(symbol);
+ void set_family(symbol);
+ void set_size(int);
+ void set_char_height(int);
+ void set_char_slant(int);
+ void set_input_line_position(hunits); // used by \n(hp
+ void interrupt();
+ void spread() { spread_flag = 1; }
+ void do_break(); // .br
+ void final_break();
+ void newline();
+ void handle_tab(int is_leader = 0); // do a tab or leader
+ void add_node(node *);
+ void add_char(charinfo *);
+ void add_hyphen_indicator();
+ void add_italic_correction();
+ void space();
+ void space_newline();
+ const char *get_font_family_string();
+ const char *get_name_string();
+ const char *get_point_size_string();
+ const char *get_requested_point_size_string();
+ void output_pending_lines();
+
+ friend void title_length();
+ friend void space_size();
+ friend void fill();
+ friend void no_fill();
+ friend void adjust();
+ friend void no_adjust();
+ friend void center();
+ friend void right_justify();
+ friend void vertical_spacing();
+ friend void line_spacing();
+ friend void line_length();
+ friend void indent();
+ friend void temporary_indent();
+ friend void underline();
+ friend void input_trap();
+ friend void set_tabs();
+ friend void margin_character();
+ friend void no_number();
+ friend void number_lines();
+ friend void leader_character();
+ friend void tab_character();
+ friend void hyphenate_request();
+ friend void no_hyphenate();
+ friend void hyphen_line_max_request();
+ friend void hyphenation_space_request();
+ friend void hyphenation_margin_request();
+ friend void line_width();
+#if 0
+ friend void tabs_save();
+ friend void tabs_restore();
+#endif
+ friend void title();
+#ifdef WIDOW_CONTROL
+ friend void widow_control_request();
+#endif /* WIDOW_CONTROL */
+};
+
+extern environment *curenv;
+extern void pop_env();
+extern void push_env(int);
+
+void init_environments();
+void read_hyphen_file(const char *name);
+
+extern int break_flag;
+extern symbol default_family;
+extern int translate_space_to_dummy;
diff --git a/gnu/usr.bin/groff/troff/hvunits.h b/gnu/usr.bin/groff/troff/hvunits.h
new file mode 100644
index 000000000000..4a1c5fd6d093
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/hvunits.h
@@ -0,0 +1,340 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+class vunits {
+ int n;
+public:
+ vunits();
+ vunits(units);
+ units to_units();
+ int is_zero();
+ vunits& operator+=(const vunits&);
+ vunits& operator-=(const vunits&);
+ friend inline vunits scale(vunits n, units x, units y); // scale n by x/y
+ friend inline vunits scale(vunits n, vunits x, vunits y);
+ friend inline vunits operator +(const vunits&, const vunits&);
+ friend inline vunits operator -(const vunits&, const vunits&);
+ friend inline vunits operator -(const vunits&);
+ friend inline int operator /(const vunits&, const vunits&);
+ friend inline vunits operator /(const vunits&, int);
+ friend inline vunits operator *(const vunits&, int);
+ friend inline vunits operator *(int, const vunits&);
+ friend inline int operator <(const vunits&, const vunits&);
+ friend inline int operator >(const vunits&, const vunits&);
+ friend inline int operator <=(const vunits&, const vunits&);
+ friend inline int operator >=(const vunits&, const vunits&);
+ friend inline int operator ==(const vunits&, const vunits&);
+ friend inline int operator !=(const vunits&, const vunits&);
+};
+
+extern vunits V0;
+
+
+class hunits {
+ int n;
+public:
+ hunits();
+ hunits(units);
+ units to_units();
+ int is_zero();
+ hunits& operator+=(const hunits&);
+ hunits& operator-=(const hunits&);
+ friend inline hunits scale(hunits n, units x, units y); // scale n by x/y
+ friend inline hunits scale(hunits n, double x);
+ friend inline hunits operator +(const hunits&, const hunits&);
+ friend inline hunits operator -(const hunits&, const hunits&);
+ friend inline hunits operator -(const hunits&);
+ friend inline int operator /(const hunits&, const hunits&);
+ friend inline hunits operator /(const hunits&, int);
+ friend inline hunits operator *(const hunits&, int);
+ friend inline hunits operator *(int, const hunits&);
+ friend inline int operator <(const hunits&, const hunits&);
+ friend inline int operator >(const hunits&, const hunits&);
+ friend inline int operator <=(const hunits&, const hunits&);
+ friend inline int operator >=(const hunits&, const hunits&);
+ friend inline int operator ==(const hunits&, const hunits&);
+ friend inline int operator !=(const hunits&, const hunits&);
+};
+
+extern hunits H0;
+
+extern int get_vunits(vunits *, unsigned char si);
+extern int get_hunits(hunits *, unsigned char si);
+extern int get_vunits(vunits *, unsigned char si, vunits prev_value);
+extern int get_hunits(hunits *, unsigned char si, hunits prev_value);
+
+inline vunits:: vunits() : n(0)
+{
+}
+
+inline units vunits::to_units()
+{
+ return n*vresolution;
+}
+
+inline int vunits::is_zero()
+{
+ return n == 0;
+}
+
+inline vunits operator +(const vunits & x, const vunits & y)
+{
+ vunits r;
+ r = x;
+ r.n += y.n;
+ return r;
+}
+
+inline vunits operator -(const vunits & x, const vunits & y)
+{
+ vunits r;
+ r = x;
+ r.n -= y.n;
+ return r;
+}
+
+inline vunits operator -(const vunits & x)
+{
+ vunits r;
+ r.n = -x.n;
+ return r;
+}
+
+inline int operator /(const vunits & x, const vunits & y)
+{
+ return x.n/y.n;
+}
+
+inline vunits operator /(const vunits & x, int n)
+{
+ vunits r;
+ r = x;
+ r.n /= n;
+ return r;
+}
+
+inline vunits operator *(const vunits & x, int n)
+{
+ vunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline vunits operator *(int n, const vunits & x)
+{
+ vunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline int operator <(const vunits & x, const vunits & y)
+{
+ return x.n < y.n;
+}
+
+inline int operator >(const vunits & x, const vunits & y)
+{
+ return x.n > y.n;
+}
+
+inline int operator <=(const vunits & x, const vunits & y)
+{
+ return x.n <= y.n;
+}
+
+inline int operator >=(const vunits & x, const vunits & y)
+{
+ return x.n >= y.n;
+}
+
+inline int operator ==(const vunits & x, const vunits & y)
+{
+ return x.n == y.n;
+}
+
+inline int operator !=(const vunits & x, const vunits & y)
+{
+ return x.n != y.n;
+}
+
+
+inline vunits& vunits::operator+=(const vunits & x)
+{
+ n += x.n;
+ return *this;
+}
+
+inline vunits& vunits::operator-=(const vunits & x)
+{
+ n -= x.n;
+ return *this;
+}
+
+inline hunits:: hunits() : n(0)
+{
+}
+
+inline units hunits::to_units()
+{
+ return n*hresolution;
+}
+
+inline int hunits::is_zero()
+{
+ return n == 0;
+}
+
+inline hunits operator +(const hunits & x, const hunits & y)
+{
+ hunits r;
+ r = x;
+ r.n += y.n;
+ return r;
+}
+
+inline hunits operator -(const hunits & x, const hunits & y)
+{
+ hunits r;
+ r = x;
+ r.n -= y.n;
+ return r;
+}
+
+inline hunits operator -(const hunits & x)
+{
+ hunits r;
+ r = x;
+ r.n = -x.n;
+ return r;
+}
+
+inline int operator /(const hunits & x, const hunits & y)
+{
+ return x.n/y.n;
+}
+
+inline hunits operator /(const hunits & x, int n)
+{
+ hunits r;
+ r = x;
+ r.n /= n;
+ return r;
+}
+
+inline hunits operator *(const hunits & x, int n)
+{
+ hunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline hunits operator *(int n, const hunits & x)
+{
+ hunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline int operator <(const hunits & x, const hunits & y)
+{
+ return x.n < y.n;
+}
+
+inline int operator >(const hunits & x, const hunits & y)
+{
+ return x.n > y.n;
+}
+
+inline int operator <=(const hunits & x, const hunits & y)
+{
+ return x.n <= y.n;
+}
+
+inline int operator >=(const hunits & x, const hunits & y)
+{
+ return x.n >= y.n;
+}
+
+inline int operator ==(const hunits & x, const hunits & y)
+{
+ return x.n == y.n;
+}
+
+inline int operator !=(const hunits & x, const hunits & y)
+{
+ return x.n != y.n;
+}
+
+
+inline hunits& hunits::operator+=(const hunits & x)
+{
+ n += x.n;
+ return *this;
+}
+
+inline hunits& hunits::operator-=(const hunits & x)
+{
+ n -= x.n;
+ return *this;
+}
+
+inline hunits scale(hunits n, units x, units y)
+{
+ hunits r;
+ r.n = scale(n.n, x, y);
+ return r;
+}
+
+inline vunits scale(vunits n, units x, units y)
+{
+ vunits r;
+ r.n = scale(n.n, x, y);
+ return r;
+}
+
+inline vunits scale(vunits n, vunits x, vunits y)
+{
+ vunits r;
+ r.n = scale(n.n, x.n, y.n);
+ return r;
+}
+
+inline hunits scale(hunits n, double x)
+{
+ hunits r;
+ r.n = int(n.n*x);
+ return r;
+}
+
+inline units scale(units n, double x)
+{
+ return int(n*x);
+}
+
+inline units points_to_units(units n)
+{
+ return scale(n, units_per_inch, 72);
+}
+
diff --git a/gnu/usr.bin/groff/troff/hyphen.us b/gnu/usr.bin/groff/troff/hyphen.us
new file mode 100644
index 000000000000..d86c3d58a7c2
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/hyphen.us
@@ -0,0 +1,4449 @@
+% Hyphenation patterns for US English.
+% 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
diff --git a/gnu/usr.bin/groff/troff/input.cc b/gnu/usr.bin/groff/troff/input.cc
new file mode 100644
index 000000000000..609ee78edf29
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/input.cc
@@ -0,0 +1,5824 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "reg.h"
+#include "token.h"
+#include "div.h"
+#include "charinfo.h"
+#include "font.h"
+#include "searchpath.h"
+#include "macropath.h"
+#include "defs.h"
+
+// Needed for getpid().
+#include "posix.h"
+
+#define USAGE_EXIT_CODE 1
+#define MACRO_PREFIX "tmac."
+#define STARTUP_FILE "troffrc"
+#define DEFAULT_INPUT_STACK_LIMIT 1000
+
+#ifndef DEFAULT_WARNING_MASK
+// warnings that are enabled by default
+#define DEFAULT_WARNING_MASK \
+ (WARN_CHAR|WARN_NUMBER|WARN_BREAK|WARN_SPACE|WARN_FONT)
+#endif
+
+// initial size of buffer for reading names; expanded as necessary
+#define ABUF_SIZE 16
+
+#ifdef COLUMN
+void init_column_requests();
+#endif /* COLUMN */
+
+static node *read_draw_node();
+void handle_first_page_transition();
+static void push_token(const token &);
+void copy_file();
+#ifdef COLUMN
+void vjustify();
+#endif /* COLUMN */
+void transparent();
+void transparent_file();
+
+const char *program_name = 0;
+token tok;
+int break_flag = 0;
+static int backtrace_flag = 0;
+char *pipe_command = 0;
+charinfo *charset_table[256];
+
+static int warning_mask = DEFAULT_WARNING_MASK;
+static int inhibit_errors = 0;
+
+static void enable_warning(const char *);
+static void disable_warning(const char *);
+
+static int escape_char = '\\';
+static symbol end_macro_name;
+static int compatible_flag = 0;
+static void process_input_stack();
+int ascii_output_flag = 0;
+int suppress_output_flag = 0;
+
+int tcommand_flag = 0;
+
+static int get_copy(node**, int = 0);
+static symbol read_escape_name();
+static void interpolate_string(symbol);
+static void interpolate_macro(symbol);
+static void interpolate_number_format(symbol);
+static void interpolate_environment_variable(symbol);
+
+static void interpolate_arg(symbol);
+static request_or_macro *lookup_request(symbol);
+static int get_delim_number(units *, int);
+static int get_delim_number(units *, int, units);
+static int get_line_arg(units *res, int si, charinfo **cp);
+static int read_size(int *);
+static symbol get_delim_name();
+static void init_registers();
+
+struct input_iterator;
+input_iterator *make_temp_iterator(const char *);
+const char *input_char_description(int);
+
+const int ESCAPE_QUESTION = 015;
+const int BEGIN_TRAP = 016;
+const int END_TRAP = 017;
+const int PAGE_EJECTOR = 020;
+const int ESCAPE_NEWLINE = 021;
+const int ESCAPE_AMPERSAND = 022;
+const int ESCAPE_UNDERSCORE = 023;
+const int ESCAPE_BAR = 024;
+const int ESCAPE_CIRCUMFLEX = 025;
+const int ESCAPE_LEFT_BRACE = 026;
+const int ESCAPE_RIGHT_BRACE = 027;
+const int ESCAPE_LEFT_QUOTE = 030;
+const int ESCAPE_RIGHT_QUOTE = 031;
+const int ESCAPE_HYPHEN = 032;
+const int ESCAPE_BANG = 033;
+const int ESCAPE_c = 034;
+const int ESCAPE_e = 035;
+const int ESCAPE_PERCENT = 036;
+const int ESCAPE_SPACE = 037;
+
+const int TITLE_REQUEST = 0200;
+const int COPY_FILE_REQUEST = 0201;
+const int TRANSPARENT_FILE_REQUEST = 0202;
+#ifdef COLUMN
+const int VJUSTIFY_REQUEST = 0203;
+#endif /* COLUMN */
+const int ESCAPE_E = 0204;
+const int LAST_PAGE_EJECTOR = 0205;
+const int ESCAPE_RIGHT_PARENTHESIS = 0206;
+
+void set_escape_char()
+{
+ if (has_arg()) {
+ if (tok.ch() == 0) {
+ error("bad escape character");
+ escape_char = '\\';
+ }
+ else
+ escape_char = tok.ch();
+ }
+ else
+ escape_char = '\\';
+ skip_line();
+}
+
+void escape_off()
+{
+ escape_char = 0;
+ skip_line();
+}
+
+class input_iterator {
+public:
+ input_iterator();
+ virtual ~input_iterator();
+ int get(node **);
+ friend class input_stack;
+protected:
+ const unsigned char *ptr;
+ const unsigned char *eptr;
+ input_iterator *next;
+private:
+ virtual int fill(node **);
+ virtual int peek();
+ virtual int has_args() { return 0; }
+ virtual int nargs() { return 0; }
+ virtual input_iterator *get_arg(int) { return NULL; }
+ virtual int get_location(int, const char **, int *)
+ { return 0; }
+ virtual void backtrace() {}
+ virtual int set_location(const char *, int)
+ { return 0; }
+ virtual int next_file(FILE *, const char *) { return 0; }
+ virtual void shift(int) {}
+ virtual int is_boundary();
+ virtual int internal_level() { return 0; }
+ virtual int is_file() { return 0; }
+};
+
+input_iterator::input_iterator()
+: ptr(0), eptr(0)
+{
+}
+
+input_iterator::~input_iterator()
+{
+}
+
+int input_iterator::fill(node **)
+{
+ return EOF;
+}
+
+int input_iterator::peek()
+{
+ return EOF;
+}
+
+int input_iterator::is_boundary()
+{
+ return 0;
+}
+
+inline int input_iterator::get(node **p)
+{
+ return ptr < eptr ? *ptr++ : fill(p);
+}
+
+
+class input_boundary : public input_iterator {
+public:
+ int is_boundary() { return 1; }
+};
+
+class file_iterator : public input_iterator {
+ FILE *fp;
+ int lineno;
+ const char *filename;
+ int newline_flag;
+ enum { BUF_SIZE = 512 };
+ unsigned char buf[BUF_SIZE];
+public:
+ file_iterator(FILE *, const char *);
+ ~file_iterator();
+ int fill(node **);
+ int peek();
+ int get_location(int, const char **, int *);
+ void backtrace();
+ int set_location(const char *, int);
+ int next_file(FILE *, const char *);
+ int is_file();
+};
+
+file_iterator::file_iterator(FILE *f, const char *fn)
+: fp(f), filename(fn), lineno(1), newline_flag(0)
+{
+}
+
+file_iterator::~file_iterator()
+{
+ if (fp != stdin)
+ fclose(fp);
+ else
+ clearerr(stdin);
+}
+
+int file_iterator::is_file()
+{
+ return 1;
+}
+
+int file_iterator::next_file(FILE *f, const char *s)
+{
+ if (fp != stdin)
+ fclose(fp);
+ else
+ clearerr(stdin);
+ filename = s;
+ fp = f;
+ lineno = 1;
+ newline_flag = 0;
+ ptr = 0;
+ eptr = 0;
+ return 1;
+}
+
+int file_iterator::fill(node **)
+{
+ if (newline_flag)
+ lineno++;
+ newline_flag = 0;
+ unsigned char *p = buf;
+ ptr = p;
+ unsigned char *e = p + BUF_SIZE;
+ while (p < e) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ else {
+ *p++ = c;
+ if (c == '\n') {
+ newline_flag = 1;
+ break;
+ }
+ }
+ }
+ if (p > buf) {
+ eptr = p;
+ return *ptr++;
+ }
+ else {
+ eptr = p;
+ return EOF;
+ }
+}
+
+int file_iterator::peek()
+{
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ c = getc(fp);
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ return c;
+}
+
+int file_iterator::get_location(int /*allow_macro*/,
+ const char **filenamep, int *linenop)
+{
+ *linenop = lineno;
+ if (filename != 0 && strcmp(filename, "-") == 0)
+ *filenamep = "<standard input>";
+ else
+ *filenamep = filename;
+ return 1;
+}
+
+void file_iterator::backtrace()
+{
+ errprint("%1:%2: backtrace: file `%1'\n", filename, lineno);
+}
+
+int file_iterator::set_location(const char *f, int ln)
+{
+ if (f)
+ filename = f;
+ lineno = ln;
+ return 1;
+}
+
+input_iterator nil_iterator;
+
+class input_stack {
+public:
+ static int get(node **);
+ static int peek();
+ static void push(input_iterator *);
+ static input_iterator *get_arg(int);
+ static int nargs();
+ static int get_location(int, const char **, int *);
+ static int set_location(const char *, int);
+ static void backtrace();
+ static void backtrace_all();
+ static void next_file(FILE *, const char *);
+ static void end_file();
+ static void shift(int n);
+ static void add_boundary();
+ static void remove_boundary();
+ static int get_level();
+ static void clear();
+
+ static int limit;
+private:
+ static input_iterator *top;
+ static int level;
+
+ static int finish_get(node **);
+ static int finish_peek();
+};
+
+input_iterator *input_stack::top = &nil_iterator;
+int input_stack::level = 0;
+int input_stack::limit = DEFAULT_INPUT_STACK_LIMIT;
+
+inline int input_stack::get_level()
+{
+ return level + top->internal_level();
+}
+
+inline int input_stack::get(node **np)
+{
+ return (top->ptr < top->eptr) ? *top->ptr++ : finish_get(np);
+}
+
+int input_stack::finish_get(node **np)
+{
+ for (;;) {
+ int c = top->fill(np);
+ if (c != EOF || top->is_boundary())
+ return c;
+ if (top == &nil_iterator)
+ break;
+ input_iterator *tem = top;
+ top = top->next;
+ level--;
+ delete tem;
+ if (top->ptr < top->eptr)
+ return *top->ptr++;
+ }
+ assert(level == 0);
+ return EOF;
+}
+
+inline int input_stack::peek()
+{
+ return (top->ptr < top->eptr) ? *top->ptr : finish_peek();
+}
+
+int input_stack::finish_peek()
+{
+ for (;;) {
+ int c = top->peek();
+ if (c != EOF || top->is_boundary())
+ return c;
+ if (top == &nil_iterator)
+ break;
+ input_iterator *tem = top;
+ top = top->next;
+ level--;
+ delete tem;
+ if (top->ptr < top->eptr)
+ return *top->ptr;
+ }
+ assert(level == 0);
+ return EOF;
+}
+
+void input_stack::add_boundary()
+{
+ push(new input_boundary);
+}
+
+void input_stack::remove_boundary()
+{
+ assert(top->is_boundary());
+ input_iterator *temp = top->next;
+ delete top;
+ top = temp;
+ level--;
+}
+
+void input_stack::push(input_iterator *in)
+{
+ if (in == 0)
+ return;
+ if (++level > limit && limit > 0)
+ fatal("input stack limit exceeded (probable infinite loop)");
+ in->next = top;
+ top = in;
+}
+
+input_iterator *input_stack::get_arg(int i)
+{
+ input_iterator *p;
+ for (p = top; p != NULL; p = p->next)
+ if (p->has_args())
+ return p->get_arg(i);
+ return 0;
+}
+
+void input_stack::shift(int n)
+{
+ for (input_iterator *p = top; p; p = p->next)
+ if (p->has_args()) {
+ p->shift(n);
+ return;
+ }
+}
+
+int input_stack::nargs()
+{
+ for (input_iterator *p =top; p != 0; p = p->next)
+ if (p->has_args())
+ return p->nargs();
+ return 0;
+}
+
+int input_stack::get_location(int allow_macro, const char **filenamep, int *linenop)
+{
+ for (input_iterator *p = top; p; p = p->next)
+ if (p->get_location(allow_macro, filenamep, linenop))
+ return 1;
+ return 0;
+}
+
+void input_stack::backtrace()
+{
+ const char *f;
+ int n;
+ // only backtrace down to (not including) the topmost file
+ for (input_iterator *p = top;
+ p && !p->get_location(0, &f, &n);
+ p = p->next)
+ p->backtrace();
+}
+
+void input_stack::backtrace_all()
+{
+ for (input_iterator *p = top; p; p = p->next)
+ p->backtrace();
+}
+
+int input_stack::set_location(const char *filename, int lineno)
+{
+ for (input_iterator *p = top; p; p = p->next)
+ if (p->set_location(filename, lineno))
+ return 1;
+ return 0;
+}
+
+void input_stack::next_file(FILE *fp, const char *s)
+{
+ for (input_iterator **pp = &top; *pp != &nil_iterator; pp = &(*pp)->next)
+ if ((*pp)->next_file(fp, s))
+ return;
+ if (++level > limit && limit > 0)
+ fatal("input stack limit exceeded");
+ *pp = new file_iterator(fp, s);
+ (*pp)->next = &nil_iterator;
+}
+
+void input_stack::end_file()
+{
+ for (input_iterator **pp = &top; *pp != &nil_iterator; pp = &(*pp)->next)
+ if ((*pp)->is_file()) {
+ input_iterator *tem = *pp;
+ *pp = (*pp)->next;
+ delete tem;
+ level--;
+ return;
+ }
+}
+
+void input_stack::clear()
+{
+ int nboundaries = 0;
+ while (top != &nil_iterator) {
+ if (top->is_boundary())
+ nboundaries++;
+ input_iterator *tem = top;
+ top = top->next;
+ level--;
+ delete tem;
+ }
+ // Keep while_request happy.
+ for (; nboundaries > 0; --nboundaries)
+ add_boundary();
+}
+
+void backtrace_request()
+{
+ input_stack::backtrace_all();
+ fflush(stderr);
+ skip_line();
+}
+
+void next_file()
+{
+ symbol nm = get_long_name(0);
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (nm.is_null())
+ input_stack::end_file();
+ else {
+ errno = 0;
+ FILE *fp = fopen(nm.contents(), "r");
+ if (!fp)
+ error("can't open `%1': %2", nm.contents(), strerror(errno));
+ else
+ input_stack::next_file(fp, nm.contents());
+ }
+ tok.next();
+}
+
+void shift()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ input_stack::shift(n);
+ skip_line();
+}
+
+static int get_char_for_escape_name()
+{
+ int c = get_copy(NULL);
+ switch (c) {
+ case EOF:
+ error("end of input in escape name");
+ return '\0';
+ default:
+ if (!illegal_input_char(c))
+ break;
+ // fall through
+ case ' ':
+ case '\n':
+ case '\t':
+ case '\001':
+ case '\b':
+ error("%1 is not allowed in an escape name", input_char_description(c));
+ return '\0';
+ }
+ return c;
+}
+
+static symbol read_two_char_escape_name()
+{
+ char buf[3];
+ buf[0] = get_char_for_escape_name();
+ if (buf[0] != '\0') {
+ buf[1] = get_char_for_escape_name();
+ if (buf[1] == '\0')
+ buf[0] = 0;
+ else
+ buf[2] = 0;
+ }
+ return symbol(buf);
+}
+
+static symbol read_long_escape_name()
+{
+ int start_level = input_stack::get_level();
+ char abuf[ABUF_SIZE];
+ char *buf = abuf;
+ int buf_size = ABUF_SIZE;
+ int i = 0;
+ for (;;) {
+ int c = get_char_for_escape_name();
+ if (c == 0) {
+ if (buf != abuf)
+ a_delete buf;
+ return NULL_SYMBOL;
+ }
+ if (i + 2 > buf_size) {
+ if (buf == abuf) {
+ buf = new char [ABUF_SIZE*2];
+ memcpy(buf, abuf, buf_size);
+ buf_size = ABUF_SIZE*2;
+ }
+ else {
+ char *old_buf = buf;
+ buf = new char[buf_size*2];
+ memcpy(buf, old_buf, buf_size);
+ buf_size *= 2;
+ a_delete old_buf;
+ }
+ }
+ if (c == ']' && input_stack::get_level() == start_level)
+ break;
+ buf[i++] = c;
+ }
+ buf[i] = 0;
+ if (buf == abuf) {
+ if (i == 0) {
+ error("empty escape name");
+ return NULL_SYMBOL;
+ }
+ return symbol(abuf);
+ }
+ else {
+ symbol s(buf);
+ a_delete buf;
+ return s;
+ }
+}
+
+static symbol read_escape_name()
+{
+ int c = get_char_for_escape_name();
+ if (c == 0)
+ return NULL_SYMBOL;
+ if (c == '(')
+ return read_two_char_escape_name();
+ if (c == '[' && !compatible_flag)
+ return read_long_escape_name();
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ return symbol(buf);
+}
+
+static symbol read_increment_and_escape_name(int *incp)
+{
+ int c = get_char_for_escape_name();
+ switch (c) {
+ case 0:
+ *incp = 0;
+ return NULL_SYMBOL;
+ case '(':
+ *incp = 0;
+ return read_two_char_escape_name();
+ case '+':
+ *incp = 1;
+ return read_escape_name();
+ case '-':
+ *incp = -1;
+ return read_escape_name();
+ case '[':
+ if (!compatible_flag) {
+ *incp = 0;
+ return read_long_escape_name();
+ }
+ break;
+ }
+ *incp = 0;
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ return symbol(buf);
+}
+
+static int get_copy(node **nd, int defining)
+{
+ for (;;) {
+ int c = input_stack::get(nd);
+ if (c == ESCAPE_NEWLINE) {
+ if (defining)
+ return c;
+ do {
+ c = input_stack::get(nd);
+ } while (c == ESCAPE_NEWLINE);
+ }
+ if (c != escape_char || escape_char <= 0)
+ return c;
+ c = input_stack::peek();
+ switch(c) {
+ case 0:
+ return escape_char;
+ case '"':
+ (void)input_stack::get(NULL);
+ while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ ;
+ return c;
+ case '#': // Like \" but newline is ignored.
+ (void)input_stack::get(NULL);
+ while ((c = input_stack::get(NULL)) != '\n')
+ if (c == EOF)
+ return EOF;
+ break;
+ case '$':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_arg(s);
+ break;
+ }
+ case '*':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_string(s);
+ break;
+ }
+ case 'a':
+ (void)input_stack::get(NULL);
+ return '\001';
+ case 'e':
+ (void)input_stack::get(NULL);
+ return ESCAPE_e;
+ case 'E':
+ (void)input_stack::get(NULL);
+ return ESCAPE_E;
+ case 'n':
+ {
+ (void)input_stack::get(NULL);
+ int inc;
+ symbol s = read_increment_and_escape_name(&inc);
+ if (!s.is_null())
+ interpolate_number_reg(s, inc);
+ break;
+ }
+ case 'g':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_number_format(s);
+ break;
+ }
+ case 't':
+ (void)input_stack::get(NULL);
+ return '\t';
+ case 'V':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_environment_variable(s);
+ break;
+ }
+ case '\n':
+ (void)input_stack::get(NULL);
+ if (defining)
+ return ESCAPE_NEWLINE;
+ break;
+ case ' ':
+ (void)input_stack::get(NULL);
+ return ESCAPE_SPACE;
+ case '|':
+ (void)input_stack::get(NULL);
+ return ESCAPE_BAR;
+ case '^':
+ (void)input_stack::get(NULL);
+ return ESCAPE_CIRCUMFLEX;
+ case '{':
+ (void)input_stack::get(NULL);
+ return ESCAPE_LEFT_BRACE;
+ case '}':
+ (void)input_stack::get(NULL);
+ return ESCAPE_RIGHT_BRACE;
+ case '`':
+ (void)input_stack::get(NULL);
+ return ESCAPE_LEFT_QUOTE;
+ case '\'':
+ (void)input_stack::get(NULL);
+ return ESCAPE_RIGHT_QUOTE;
+ case '-':
+ (void)input_stack::get(NULL);
+ return ESCAPE_HYPHEN;
+ case '_':
+ (void)input_stack::get(NULL);
+ return ESCAPE_UNDERSCORE;
+ case 'c':
+ (void)input_stack::get(NULL);
+ return ESCAPE_c;
+ case '!':
+ (void)input_stack::get(NULL);
+ return ESCAPE_BANG;
+ case '?':
+ (void)input_stack::get(NULL);
+ return ESCAPE_QUESTION;
+ case '&':
+ (void)input_stack::get(NULL);
+ return ESCAPE_AMPERSAND;
+ case ')':
+ (void)input_stack::get(NULL);
+ return ESCAPE_RIGHT_PARENTHESIS;
+ case '.':
+ (void)input_stack::get(NULL);
+ return c;
+ case '%':
+ (void)input_stack::get(NULL);
+ return ESCAPE_PERCENT;
+ default:
+ if (c == escape_char) {
+ (void)input_stack::get(NULL);
+ return c;
+ }
+ else
+ return escape_char;
+ }
+ }
+}
+
+class non_interpreted_char_node : public node {
+ unsigned char c;
+public:
+ non_interpreted_char_node(unsigned char);
+ node *copy();
+ int interpret(macro *);
+ int same(node *);
+ const char *type();
+};
+
+int non_interpreted_char_node::same(node *nd)
+{
+ return c == ((non_interpreted_char_node *)nd)->c;
+}
+
+const char *non_interpreted_char_node::type()
+{
+ return "non_interpreted_char_node";
+}
+
+non_interpreted_char_node::non_interpreted_char_node(unsigned char n) : c(n)
+{
+ assert(n != 0);
+}
+
+node *non_interpreted_char_node::copy()
+{
+ return new non_interpreted_char_node(c);
+}
+
+int non_interpreted_char_node::interpret(macro *mac)
+{
+ mac->append(c);
+ return 1;
+}
+
+static void do_width();
+static node *do_non_interpreted();
+static node *do_special();
+static void do_register();
+
+static node *do_overstrike()
+{
+ token start;
+ overstrike_node *on = new overstrike_node;
+ start.next();
+ tok.next();
+ while (tok != start) {
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ charinfo *ci = tok.get_char(1);
+ if (ci) {
+ node *n = curenv->make_char_node(ci);
+ if (n)
+ on->overstrike(n);
+ }
+ tok.next();
+ }
+ return on;
+}
+
+static node *do_bracket()
+{
+ token start;
+ bracket_node *bn = new bracket_node;
+ start.next();
+ tok.next();
+ while (tok != start) {
+ if (tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok.newline()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ input_stack::push(make_temp_iterator("\n"));
+ break;
+ }
+ charinfo *ci = tok.get_char(1);
+ if (ci) {
+ node *n = curenv->make_char_node(ci);
+ if (n)
+ bn->bracket(n);
+ }
+ tok.next();
+ }
+ return bn;
+}
+
+static int do_name_test()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ int bad_char = 0;
+ int some_char = 0;
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ if (!tok.ch())
+ bad_char = 1;
+ some_char = 1;
+ }
+ return some_char && !bad_char;
+}
+
+#if 0
+static node *do_zero_width()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ environment env(curenv);
+ environment *oldenv = curenv;
+ curenv = &env;
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ error("missing closing delimiter");
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ tok.process();
+ }
+ curenv = oldenv;
+ node *rev = env.extract_output_line();
+ node *n = 0;
+ while (rev) {
+ node *tem = rev;
+ rev = rev->next;
+ tem->next = n;
+ n = tem;
+ }
+ return new zero_width_node(n);
+}
+
+#else
+
+// It's undesirable for \Z to change environments, because then
+// \n(.w won't work as expected.
+
+static node *do_zero_width()
+{
+ node *rev = new dummy_node;
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ if (!tok.add_to_node_list(&rev))
+ error("illegal token in argument to \\Z");
+ }
+ node *n = 0;
+ while (rev) {
+ node *tem = rev;
+ rev = rev->next;
+ tem->next = n;
+ n = tem;
+ }
+ return new zero_width_node(n);
+}
+
+#endif
+
+token_node *node::get_token_node()
+{
+ return 0;
+}
+
+class token_node : public node {
+public:
+ token tk;
+ token_node(const token &t);
+ node *copy();
+ token_node *get_token_node();
+ int same(node *);
+ const char *type();
+};
+
+token_node::token_node(const token &t) : tk(t)
+{
+}
+
+node *token_node::copy()
+{
+ return new token_node(tk);
+}
+
+token_node *token_node::get_token_node()
+{
+ return this;
+}
+
+int token_node::same(node *nd)
+{
+ return tk == ((token_node *)nd)->tk;
+}
+
+const char *token_node::type()
+{
+ return "token_node";
+}
+
+token::token() : nd(0), type(TOKEN_EMPTY)
+{
+}
+
+token::~token()
+{
+ delete nd;
+}
+
+token::token(const token &t)
+: nm(t.nm), c(t.c), val(t.val), dim(t.dim), type(t.type)
+{
+ // Use two statements to work around bug in SGI C++.
+ node *tem = t.nd;
+ nd = tem ? tem->copy() : 0;
+}
+
+void token::operator=(const token &t)
+{
+ delete nd;
+ nm = t.nm;
+ // Use two statements to work around bug in SGI C++.
+ node *tem = t.nd;
+ nd = tem ? tem->copy() : 0;
+ c = t.c;
+ val = t.val;
+ dim = t.dim;
+ type = t.type;
+}
+
+void token::skip()
+{
+ while (space())
+ next();
+}
+
+int has_arg()
+{
+ while (tok.space())
+ tok.next();
+ return !tok.newline();
+}
+
+void token::make_space()
+{
+ type = TOKEN_SPACE;
+}
+
+void token::make_newline()
+{
+ type = TOKEN_NEWLINE;
+}
+
+void token::next()
+{
+ if (nd) {
+ delete nd;
+ nd = 0;
+ }
+ units x;
+ for (;;) {
+ node *n;
+ int cc = input_stack::get(&n);
+ if (cc != escape_char || escape_char == 0) {
+ handle_normal_char:
+ switch(cc) {
+ case EOF:
+ type = TOKEN_EOF;
+ return;
+ case TRANSPARENT_FILE_REQUEST:
+ case TITLE_REQUEST:
+ case COPY_FILE_REQUEST:
+#ifdef COLUMN
+ case VJUSTIFY_REQUEST:
+#endif /* COLUMN */
+ type = TOKEN_REQUEST;
+ c = cc;
+ return;
+ case BEGIN_TRAP:
+ type = TOKEN_BEGIN_TRAP;
+ return;
+ case END_TRAP:
+ type = TOKEN_END_TRAP;
+ return;
+ case LAST_PAGE_EJECTOR:
+ seen_last_page_ejector = 1;
+ // fall through
+ case PAGE_EJECTOR:
+ type = TOKEN_PAGE_EJECTOR;
+ return;
+ case ESCAPE_PERCENT:
+ ESCAPE_PERCENT:
+ type = TOKEN_HYPHEN_INDICATOR;
+ return;
+ case ESCAPE_SPACE:
+ ESCAPE_SPACE:
+ type = TOKEN_NODE;
+ nd = new space_char_hmotion_node(curenv->get_space_width());
+ return;
+ case ESCAPE_e:
+ ESCAPE_e:
+ type = TOKEN_ESCAPE;
+ return;
+ case ESCAPE_E:
+ goto handle_escape_char;
+ case ESCAPE_BAR:
+ ESCAPE_BAR:
+ type = TOKEN_NODE;
+ nd = new hmotion_node(curenv->get_narrow_space_width());
+ return;
+ case ESCAPE_CIRCUMFLEX:
+ ESCAPE_CIRCUMFLEX:
+ type = TOKEN_NODE;
+ nd = new hmotion_node(curenv->get_half_narrow_space_width());
+ return;
+ case ESCAPE_NEWLINE:
+ break;
+ case ESCAPE_LEFT_BRACE:
+ ESCAPE_LEFT_BRACE:
+ type = TOKEN_LEFT_BRACE;
+ return;
+ case ESCAPE_RIGHT_BRACE:
+ ESCAPE_RIGHT_BRACE:
+ type = TOKEN_RIGHT_BRACE;
+ return;
+ case ESCAPE_LEFT_QUOTE:
+ ESCAPE_LEFT_QUOTE:
+ type = TOKEN_SPECIAL;
+ nm = symbol("ga");
+ return;
+ case ESCAPE_RIGHT_QUOTE:
+ ESCAPE_RIGHT_QUOTE:
+ type = TOKEN_SPECIAL;
+ nm = symbol("aa");
+ return;
+ case ESCAPE_HYPHEN:
+ ESCAPE_HYPHEN:
+ type = TOKEN_SPECIAL;
+ nm = symbol("-");
+ return;
+ case ESCAPE_UNDERSCORE:
+ ESCAPE_UNDERSCORE:
+ type = TOKEN_SPECIAL;
+ nm = symbol("ul");
+ return;
+ case ESCAPE_c:
+ ESCAPE_c:
+ type = TOKEN_INTERRUPT;
+ return;
+ case ESCAPE_BANG:
+ ESCAPE_BANG:
+ type = TOKEN_TRANSPARENT;
+ return;
+ case ESCAPE_QUESTION:
+ ESCAPE_QUESTION:
+ nd = do_non_interpreted();
+ if (nd) {
+ type = TOKEN_NODE;
+ return;
+ }
+ break;
+ case ESCAPE_AMPERSAND:
+ ESCAPE_AMPERSAND:
+ type = TOKEN_DUMMY;
+ return;
+ case ESCAPE_RIGHT_PARENTHESIS:
+ ESCAPE_RIGHT_PARENTHESIS:
+ type = TOKEN_NODE;
+ nd = new transparent_dummy_node;
+ return;
+ case '\b':
+ type = TOKEN_BACKSPACE;
+ return;
+ case ' ':
+ type = TOKEN_SPACE;
+ return;
+ case '\t':
+ type = TOKEN_TAB;
+ return;
+ case '\n':
+ type = TOKEN_NEWLINE;
+ return;
+ case '\001':
+ type = TOKEN_LEADER;
+ return;
+ case 0:
+ {
+ assert(n != 0);
+ token_node *tn = n->get_token_node();
+ if (tn) {
+ *this = tn->tk;
+ delete tn;
+ }
+ else {
+ nd = n;
+ type = TOKEN_NODE;
+ }
+ }
+ return;
+ default:
+ type = TOKEN_CHAR;
+ c = cc;
+ return;
+ }
+ }
+ else {
+ handle_escape_char:
+ cc = input_stack::get(NULL);
+ switch(cc) {
+ case '(':
+ nm = read_two_char_escape_name();
+ type = TOKEN_SPECIAL;
+ return;
+ case EOF:
+ type = TOKEN_EOF;
+ error("end of input after escape character");
+ return;
+ case '`':
+ goto ESCAPE_LEFT_QUOTE;
+ case '\'':
+ goto ESCAPE_RIGHT_QUOTE;
+ case '-':
+ goto ESCAPE_HYPHEN;
+ case '_':
+ goto ESCAPE_UNDERSCORE;
+ case '%':
+ goto ESCAPE_PERCENT;
+ case ' ':
+ goto ESCAPE_SPACE;
+ case '0':
+ nd = new hmotion_node(curenv->get_digit_width());
+ type = TOKEN_NODE;
+ return;
+ case '|':
+ goto ESCAPE_BAR;
+ case '^':
+ goto ESCAPE_CIRCUMFLEX;
+ case '/':
+ type = TOKEN_ITALIC_CORRECTION;
+ return;
+ case ',':
+ type = TOKEN_NODE;
+ nd = new left_italic_corrected_node;
+ return;
+ case '&':
+ goto ESCAPE_AMPERSAND;
+ case ')':
+ goto ESCAPE_RIGHT_PARENTHESIS;
+ case '!':
+ goto ESCAPE_BANG;
+ case '?':
+ goto ESCAPE_QUESTION;
+ case '~':
+ nd = new unbreakable_space_node(curenv->get_space_width());
+ type = TOKEN_NODE;
+ return;
+ case '"':
+ while ((cc = input_stack::get(NULL)) != '\n' && cc != EOF)
+ ;
+ if (cc == '\n')
+ type = TOKEN_NEWLINE;
+ else
+ type = TOKEN_EOF;
+ return;
+ case '#': // Like \" but newline is ignored.
+ while ((cc = input_stack::get(NULL)) != '\n')
+ if (cc == EOF) {
+ type = TOKEN_EOF;
+ return;
+ }
+ break;
+ case '$':
+ {
+ symbol nm = read_escape_name();
+ if (!nm.is_null())
+ interpolate_arg(nm);
+ break;
+ }
+ case '*':
+ {
+ symbol nm = read_escape_name();
+ if (!nm.is_null())
+ interpolate_string(nm);
+ break;
+ }
+ case 'a':
+ nd = new non_interpreted_char_node('\001');
+ type = TOKEN_NODE;
+ return;
+ case 'A':
+ c = '0' + do_name_test();
+ type = TOKEN_CHAR;
+ return;
+ case 'b':
+ nd = do_bracket();
+ type = TOKEN_NODE;
+ return;
+ case 'c':
+ goto ESCAPE_c;
+ case 'C':
+ nm = get_delim_name();
+ if (nm.is_null())
+ break;
+ type = TOKEN_SPECIAL;
+ return;
+ case 'd':
+ type = TOKEN_NODE;
+ nd = new vmotion_node(curenv->get_size()/2);
+ return;
+ case 'D':
+ nd = read_draw_node();
+ if (!nd)
+ break;
+ type = TOKEN_NODE;
+ return;
+ case 'e':
+ goto ESCAPE_e;
+ case 'E':
+ goto handle_escape_char;
+ case 'f':
+ {
+ symbol s = read_escape_name();
+ if (s.is_null())
+ break;
+ for (const char *p = s.contents(); *p != '\0'; p++)
+ if (!csdigit(*p))
+ break;
+ if (*p)
+ curenv->set_font(s);
+ else
+ curenv->set_font(atoi(s.contents()));
+ break;
+ }
+ case 'g':
+ {
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_number_format(s);
+ break;
+ }
+ case 'h':
+ if (!get_delim_number(&x, 'm'))
+ break;
+ type = TOKEN_NODE;
+ nd = new hmotion_node(x);
+ return;
+ case 'H':
+ if (get_delim_number(&x, 'z', curenv->get_requested_point_size()))
+ curenv->set_char_height(x);
+ break;
+ case 'k':
+ nm = read_escape_name();
+ if (nm.is_null())
+ break;
+ type = TOKEN_MARK_INPUT;
+ return;
+ case 'l':
+ case 'L':
+ {
+ charinfo *s = 0;
+ if (!get_line_arg(&x, (cc == 'l' ? 'm': 'v'), &s))
+ break;
+ if (s == 0)
+ s = get_charinfo(cc == 'l' ? "ru" : "br");
+ type = TOKEN_NODE;
+ node *n = curenv->make_char_node(s);
+ if (cc == 'l')
+ nd = new hline_node(x, n);
+ else
+ nd = new vline_node(x, n);
+ return;
+ }
+ case 'n':
+ {
+ int inc;
+ symbol nm = read_increment_and_escape_name(&inc);
+ if (!nm.is_null())
+ interpolate_number_reg(nm, inc);
+ break;
+ }
+ case 'N':
+ if (!get_delim_number(&val, 0))
+ break;
+ type = TOKEN_NUMBERED_CHAR;
+ return;
+ case 'o':
+ nd = do_overstrike();
+ type = TOKEN_NODE;
+ return;
+ case 'p':
+ type = TOKEN_SPREAD;
+ return;
+ case 'r':
+ type = TOKEN_NODE;
+ nd = new vmotion_node(-curenv->get_size());
+ return;
+ case 'R':
+ do_register();
+ break;
+ case 's':
+ if (read_size(&x))
+ curenv->set_size(x);
+ break;
+ case 'S':
+ if (get_delim_number(&x, 0))
+ curenv->set_char_slant(x);
+ break;
+ case 't':
+ type = TOKEN_NODE;
+ nd = new non_interpreted_char_node('\t');
+ return;
+ case 'u':
+ type = TOKEN_NODE;
+ nd = new vmotion_node(-curenv->get_size()/2);
+ return;
+ case 'v':
+ if (!get_delim_number(&x, 'v'))
+ break;
+ type = TOKEN_NODE;
+ nd = new vmotion_node(x);
+ return;
+ case 'V':
+ {
+ symbol nm = read_escape_name();
+ if (!nm.is_null())
+ interpolate_environment_variable(nm);
+ break;
+ }
+ case 'w':
+ do_width();
+ break;
+ case 'x':
+ if (!get_delim_number(&x, 'v'))
+ break;
+ type = TOKEN_NODE;
+ nd = new extra_size_node(x);
+ return;
+ case 'X':
+ nd = do_special();
+ if (!nd)
+ break;
+ type = TOKEN_NODE;
+ return;
+ case 'Y':
+ {
+ symbol s = read_escape_name();
+ if (s.is_null())
+ break;
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m) {
+ error("can't transparently throughput a request");
+ break;
+ }
+ nd = new special_node(*m);
+ type = TOKEN_NODE;
+ return;
+ }
+ case 'z':
+ {
+ next();
+ if (type == TOKEN_NODE)
+ nd = new zero_width_node(nd);
+ else {
+ charinfo *ci = get_char(1);
+ if (ci == 0)
+ break;
+ node *gn = curenv->make_char_node(ci);
+ if (gn == 0)
+ break;
+ nd = new zero_width_node(gn);
+ type = TOKEN_NODE;
+ }
+ return;
+ }
+ case 'Z':
+ nd = do_zero_width();
+ if (nd == 0)
+ break;
+ type = TOKEN_NODE;
+ return;
+ case '{':
+ goto ESCAPE_LEFT_BRACE;
+ case '}':
+ goto ESCAPE_RIGHT_BRACE;
+ case '\n':
+ break;
+ case '[':
+ if (!compatible_flag) {
+ nm = read_long_escape_name();
+ if (nm.is_null())
+ break;
+ type = TOKEN_SPECIAL;
+ return;
+ }
+ goto handle_normal_char;
+ default:
+ if (cc != escape_char && cc != '.')
+ warning(WARN_ESCAPE, "escape character ignored before %1",
+ input_char_description(cc));
+ goto handle_normal_char;
+ }
+ }
+ }
+}
+
+int token::operator==(const token &t)
+{
+ if (type != t.type)
+ return 0;
+ switch(type) {
+ case TOKEN_CHAR:
+ return c == t.c;
+ case TOKEN_SPECIAL:
+ return nm == t.nm;
+ case TOKEN_NUMBERED_CHAR:
+ return val == t.val;
+ default:
+ return 1;
+ }
+}
+
+int token::operator!=(const token &t)
+{
+ return !(*this == t);
+}
+
+// is token a suitable delimiter (like ')?
+
+int token::delimiter(int err)
+{
+ switch(type) {
+ case TOKEN_CHAR:
+ switch(c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case '/':
+ case '*':
+ case '%':
+ case '<':
+ case '>':
+ case '=':
+ case '&':
+ case ':':
+ case '(':
+ case ')':
+ case '.':
+ if (err)
+ error("cannot use character `%1' as a starting delimiter", char(c));
+ return 0;
+ default:
+ return 1;
+ }
+ case TOKEN_NODE:
+ case TOKEN_SPACE:
+ case TOKEN_TAB:
+ case TOKEN_NEWLINE:
+ if (err)
+ error("cannot use %1 as a starting delimiter", description());
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+const char *token::description()
+{
+ static char buf[4];
+ switch (type) {
+ case TOKEN_BACKSPACE:
+ return "a backspace character";
+ case TOKEN_CHAR:
+ buf[0] = '`';
+ buf[1] = c;
+ buf[2] = '\'';
+ buf[3] = '\0';
+ return buf;
+ case TOKEN_DUMMY:
+ return "`\\&'";
+ case TOKEN_ESCAPE:
+ return "`\\e'";
+ case TOKEN_HYPHEN_INDICATOR:
+ return "`\\%'";
+ case TOKEN_INTERRUPT:
+ return "`\\c'";
+ case TOKEN_ITALIC_CORRECTION:
+ return "`\\/'";
+ case TOKEN_LEADER:
+ return "a leader character";
+ case TOKEN_LEFT_BRACE:
+ return "`\\{'";
+ case TOKEN_MARK_INPUT:
+ return "`\\k'";
+ case TOKEN_NEWLINE:
+ return "newline";
+ case TOKEN_NODE:
+ return "a node";
+ case TOKEN_NUMBERED_CHAR:
+ return "`\\N'";
+ case TOKEN_RIGHT_BRACE:
+ return "`\\}'";
+ case TOKEN_SPACE:
+ return "a space";
+ case TOKEN_SPECIAL:
+ return "a special character";
+ case TOKEN_SPREAD:
+ return "`\\p'";
+ case TOKEN_TAB:
+ return "a tab character";
+ case TOKEN_TRANSPARENT:
+ return "`\\!'";
+ case TOKEN_EOF:
+ return "end of input";
+ default:
+ break;
+ }
+ return "a magic token";
+}
+
+void skip_line()
+{
+ while (!tok.newline())
+ if (tok.eof())
+ return;
+ else
+ tok.next();
+ tok.next();
+}
+
+void compatible()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ compatible_flag = n != 0;
+ else
+ compatible_flag = 1;
+ skip_line();
+}
+
+static void empty_name_warning(int required)
+{
+ if (tok.newline() || tok.eof()) {
+ if (required)
+ warning(WARN_MISSING, "missing name");
+ }
+ else if (tok.right_brace() || tok.tab()) {
+ const char *start = tok.description();
+ do {
+ tok.next();
+ } while (tok.space() || tok.right_brace() || tok.tab());
+ if (!tok.newline() && !tok.eof())
+ error("%1 is not allowed before an argument", start);
+ else if (required)
+ warning(WARN_MISSING, "missing name");
+ }
+ else if (required)
+ error("name expected (got %1)", tok.description());
+ else
+ error("name expected (got %1): treated as missing", tok.description());
+}
+
+static void non_empty_name_warning()
+{
+ if (!tok.newline() && !tok.eof() && !tok.space() && !tok.tab()
+ && !tok.right_brace()
+ // We don't want to give a warning for .el\{
+ && !tok.left_brace())
+ error("%1 is not allowed in a name", tok.description());
+}
+
+symbol get_name(int required)
+{
+ if (compatible_flag) {
+ char buf[3];
+ tok.skip();
+ if ((buf[0] = tok.ch()) != 0) {
+ tok.next();
+ if ((buf[1] = tok.ch()) != 0) {
+ buf[2] = 0;
+ tok.make_space();
+ }
+ else
+ non_empty_name_warning();
+ return symbol(buf);
+ }
+ else {
+ empty_name_warning(required);
+ return NULL_SYMBOL;
+ }
+ }
+ else
+ return get_long_name(required);
+}
+
+symbol get_long_name(int required)
+{
+ while (tok.space())
+ tok.next();
+ char abuf[ABUF_SIZE];
+ char *buf = abuf;
+ int buf_size = ABUF_SIZE;
+ int i = 0;
+ for (;;) {
+ if (i + 1 > buf_size) {
+ if (buf == abuf) {
+ buf = new char [ABUF_SIZE*2];
+ memcpy(buf, abuf, buf_size);
+ buf_size = ABUF_SIZE*2;
+ }
+ else {
+ char *old_buf = buf;
+ buf = new char[buf_size*2];
+ memcpy(buf, old_buf, buf_size);
+ buf_size *= 2;
+ a_delete old_buf;
+ }
+ }
+ if ((buf[i] = tok.ch()) == 0)
+ break;
+ i++;
+ tok.next();
+ }
+ if (i == 0) {
+ empty_name_warning(required);
+ return NULL_SYMBOL;
+ }
+ non_empty_name_warning();
+ if (buf == abuf)
+ return symbol(buf);
+ else {
+ symbol s(buf);
+ a_delete buf;
+ return s;
+ }
+}
+
+NO_RETURN void exit_troff()
+{
+ exit_started = 1;
+ topdiv->set_last_page();
+ if (!end_macro_name.is_null()) {
+ spring_trap(end_macro_name);
+ tok.next();
+ process_input_stack();
+ }
+ curenv->final_break();
+ tok.next();
+ process_input_stack();
+ end_diversions();
+ done_end_macro = 1;
+ topdiv->set_ejecting();
+ static unsigned char buf[2] = { LAST_PAGE_EJECTOR, '\0' };
+ input_stack::push(make_temp_iterator((char *)buf));
+ topdiv->space(topdiv->get_page_length(), 1);
+ tok.next();
+ process_input_stack();
+ seen_last_page_ejector = 1; // should be set already
+ topdiv->set_ejecting();
+ push_page_ejector();
+ topdiv->space(topdiv->get_page_length(), 1);
+ tok.next();
+ process_input_stack();
+ // This will only happen if a trap-invoked macro starts a diversion,
+ // or if vertical position traps have been disabled.
+ cleanup_and_exit(0);
+}
+
+// This implements .ex. The input stack must be cleared before calling
+// exit_troff().
+
+void exit_request()
+{
+ input_stack::clear();
+ if (exit_started)
+ tok.next();
+ else
+ exit_troff();
+}
+
+void end_macro()
+{
+ end_macro_name = get_name();
+ skip_line();
+}
+
+void do_request()
+{
+ int saved_compatible_flag = compatible_flag;
+ compatible_flag = 0;
+ symbol nm = get_name();
+ if (nm.is_null())
+ skip_line();
+ else
+ interpolate_macro(nm);
+ compatible_flag = saved_compatible_flag;
+}
+
+inline int possibly_handle_first_page_transition()
+{
+ if (topdiv->before_first_page && curdiv == topdiv && !curenv->is_dummy()) {
+ handle_first_page_transition();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int transparent_translate(int cc)
+{
+ if (!illegal_input_char(cc)) {
+ charinfo *ci = charset_table[cc];
+ switch (ci->get_special_translation(1)) {
+ case charinfo::TRANSLATE_SPACE:
+ return ' ';
+ case charinfo::TRANSLATE_DUMMY:
+ return ESCAPE_AMPERSAND;
+ case charinfo::TRANSLATE_HYPHEN_INDICATOR:
+ return ESCAPE_PERCENT;
+ }
+ // This is realy ugly.
+ ci = ci->get_translation(1);
+ if (ci) {
+ int c = ci->get_ascii_code();
+ if (c != '\0')
+ return c;
+ error("can't translate %1 to special character `%2'"
+ " in transparent throughput",
+ input_char_description(cc),
+ ci->nm.contents());
+ }
+ }
+ return cc;
+}
+
+class int_stack {
+ struct int_stack_element {
+ int n;
+ int_stack_element *next;
+ } *top;
+public:
+ int_stack();
+ ~int_stack();
+ void push(int);
+ int is_empty();
+ int pop();
+};
+
+int_stack::int_stack()
+{
+ top = 0;
+}
+
+int_stack::~int_stack()
+{
+ while (top != 0) {
+ int_stack_element *temp = top;
+ top = top->next;
+ delete temp;
+ }
+
+}
+
+int int_stack::is_empty()
+{
+ return top == 0;
+}
+
+void int_stack::push(int n)
+{
+ int_stack_element *p = new int_stack_element;
+ p->next = top;
+ p->n = n;
+ top = p;
+}
+
+
+int int_stack::pop()
+{
+ assert(top != 0);
+ int_stack_element *p = top;
+ top = top->next;
+ int n = p->n;
+ delete p;
+ return n;
+}
+
+int node::reread(int *)
+{
+ return 0;
+}
+
+int diverted_space_node::reread(int *bolp)
+{
+ if (curenv->get_fill())
+ blank_line();
+ else
+ curdiv->space(n);
+ *bolp = 1;
+ return 1;
+}
+
+int diverted_copy_file_node::reread(int *bolp)
+{
+ curdiv->copy_file(filename.contents());
+ *bolp = 1;
+ return 1;
+}
+
+static void process_input_stack()
+{
+ int_stack trap_bol_stack;
+ int bol = 1;
+ for (;;) {
+ int suppress_next = 0;
+ switch (tok.type) {
+ case token::TOKEN_CHAR:
+ {
+ unsigned char ch = tok.c;
+ if (bol &&
+ (ch == curenv->control_char
+ || ch == curenv->no_break_control_char)) {
+ break_flag = ch == curenv->control_char;
+ // skip tabs as well as spaces here
+ do {
+ tok.next();
+ } while (tok.white_space());
+ symbol nm = get_name();
+ if (nm.is_null())
+ skip_line();
+ else
+ interpolate_macro(nm);
+ suppress_next = 1;
+ }
+ else {
+ if (possibly_handle_first_page_transition())
+ ;
+ else {
+ for (;;) {
+ curenv->add_char(charset_table[ch]);
+ tok.next();
+ if (tok.type != token::TOKEN_CHAR)
+ break;
+ ch = tok.c;
+ }
+ suppress_next = 1;
+ bol = 0;
+ }
+ }
+ break;
+ }
+ case token::TOKEN_TRANSPARENT:
+ {
+ if (bol) {
+ if (possibly_handle_first_page_transition())
+ ;
+ else {
+ int cc;
+ do {
+ node *n;
+ cc = get_copy(&n);
+ if (cc != EOF)
+ if (cc != '\0')
+ curdiv->transparent_output(transparent_translate(cc));
+ else
+ curdiv->transparent_output(n);
+ } while (cc != '\n' && cc != EOF);
+ if (cc == EOF)
+ curdiv->transparent_output('\n');
+ }
+ }
+ break;
+ }
+ case token::TOKEN_NEWLINE:
+ {
+ if (bol && !curenv->get_prev_line_interrupted())
+ blank_line();
+ else {
+ curenv->newline();
+ bol = 1;
+ }
+ break;
+ }
+ case token::TOKEN_REQUEST:
+ {
+ int request_code = tok.c;
+ tok.next();
+ switch (request_code) {
+ case TITLE_REQUEST:
+ title();
+ break;
+ case COPY_FILE_REQUEST:
+ copy_file();
+ break;
+ case TRANSPARENT_FILE_REQUEST:
+ transparent_file();
+ break;
+#ifdef COLUMN
+ case VJUSTIFY_REQUEST:
+ vjustify();
+ break;
+#endif /* COLUMN */
+ default:
+ assert(0);
+ break;
+ }
+ suppress_next = 1;
+ break;
+ }
+ case token::TOKEN_SPACE:
+ {
+ if (possibly_handle_first_page_transition())
+ ;
+ else if (bol && !curenv->get_prev_line_interrupted()) {
+ int nspaces = 0;
+ do {
+ nspaces += tok.nspaces();
+ tok.next();
+ } while (tok.space());
+ if (tok.newline())
+ blank_line();
+ else {
+ push_token(tok);
+ curenv->do_break();
+ curenv->add_node(new hmotion_node(curenv->get_space_width()*nspaces));
+ bol = 0;
+ }
+ }
+ else {
+ curenv->space();
+ bol = 0;
+ }
+ break;
+ }
+ case token::TOKEN_EOF:
+ return;
+ case token::TOKEN_NODE:
+ {
+ if (possibly_handle_first_page_transition())
+ ;
+ else if (tok.nd->reread(&bol)) {
+ delete tok.nd;
+ tok.nd = 0;
+ }
+ else {
+ curenv->add_node(tok.nd);
+ tok.nd = 0;
+ bol = 0;
+ }
+ break;
+ }
+ case token::TOKEN_PAGE_EJECTOR:
+ {
+ continue_page_eject();
+ // I think we just want to preserve bol.
+ // bol = 1;
+ break;
+ }
+ case token::TOKEN_BEGIN_TRAP:
+ {
+ trap_bol_stack.push(bol);
+ bol = 1;
+ break;
+ }
+ case token::TOKEN_END_TRAP:
+ {
+ if (trap_bol_stack.is_empty())
+ error("spurious end trap token detected!");
+ else
+ bol = trap_bol_stack.pop();
+
+ /* I'm not totally happy about this. But I can't think of any other
+ way to do it. Doing an output_pending_lines() whenever a
+ TOKEN_END_TRAP is detected doesn't work: for example,
+
+ .wh -1i x
+ .de x
+ 'bp
+ ..
+ .wh -.5i y
+ .de y
+ .tl ''-%-''
+ ..
+ .br
+ .ll .5i
+ .sp |\n(.pu-1i-.5v
+ a\%very\%very\%long\%word
+
+ will print all but the first lines from the word immediately
+ after the footer, rather than on the next page. */
+
+ if (trap_bol_stack.is_empty())
+ curenv->output_pending_lines();
+ break;
+ }
+ default:
+ {
+ bol = 0;
+ tok.process();
+ break;
+ }
+ }
+ if (!suppress_next)
+ tok.next();
+ trap_sprung_flag = 0;
+ }
+}
+
+#ifdef WIDOW_CONTROL
+
+void flush_pending_lines()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ curenv->output_pending_lines();
+ tok.next();
+}
+
+#endif /* WIDOW_CONTROL */
+
+request_or_macro::request_or_macro()
+{
+}
+
+macro *request_or_macro::to_macro()
+{
+ return 0;
+}
+
+request::request(REQUEST_FUNCP pp) : p(pp)
+{
+}
+
+void request::invoke(symbol)
+{
+ (*p)();
+}
+
+struct char_block {
+ enum { SIZE = 128 };
+ unsigned char s[SIZE];
+ char_block *next;
+ char_block();
+};
+
+char_block::char_block()
+: next(0)
+{
+}
+
+class char_list {
+public:
+ char_list();
+ ~char_list();
+ void append(unsigned char);
+ int length();
+private:
+ unsigned char *ptr;
+ int len;
+ char_block *head;
+ char_block *tail;
+ friend class macro_header;
+ friend class string_iterator;
+};
+
+char_list::char_list()
+: head(0), tail(0), ptr(0), len(0)
+{
+}
+
+char_list::~char_list()
+{
+ while (head != 0) {
+ char_block *tem = head;
+ head = head->next;
+ delete tem;
+ }
+}
+
+int char_list::length()
+{
+ return len;
+}
+
+void char_list::append(unsigned char c)
+{
+ if (tail == 0) {
+ head = tail = new char_block;
+ ptr = tail->s;
+ }
+ else {
+ if (ptr >= tail->s + char_block::SIZE) {
+ tail->next = new char_block;
+ tail = tail->next;
+ ptr = tail->s;
+ }
+ }
+ *ptr++ = c;
+ len++;
+}
+
+class node_list {
+ node *head;
+ node *tail;
+public:
+ node_list();
+ ~node_list();
+ void append(node *);
+ int length();
+ node *extract();
+
+ friend class macro_header;
+ friend class string_iterator;
+};
+
+void node_list::append(node *n)
+{
+ if (head == 0) {
+ n->next = 0;
+ head = tail = n;
+ }
+ else {
+ n->next = 0;
+ tail = tail->next = n;
+ }
+}
+
+int node_list::length()
+{
+ int total = 0;
+ for (node *n = head; n != 0; n = n->next)
+ ++total;
+ return total;
+}
+
+node_list::node_list()
+{
+ head = tail = 0;
+}
+
+node *node_list::extract()
+{
+ node *temp = head;
+ head = tail = 0;
+ return temp;
+}
+
+
+node_list::~node_list()
+{
+ delete_node_list(head);
+}
+
+struct macro_header {
+ int count;
+ char_list cl;
+ node_list nl;
+ macro_header() { count = 1; }
+ macro_header *copy(int);
+};
+
+
+macro::~macro()
+{
+ if (p != 0 && --(p->count) <= 0)
+ delete p;
+}
+
+macro::macro()
+{
+ if (!input_stack::get_location(1, &filename, &lineno)) {
+ filename = 0;
+ lineno = 0;
+ }
+ length = 0;
+ p = 0;
+}
+
+macro::macro(const macro &m)
+: filename(m.filename), lineno(m.lineno), p(m.p), length(m.length)
+{
+ if (p != 0)
+ p->count++;
+}
+
+macro &macro::operator=(const macro &m)
+{
+ // don't assign object
+ if (m.p != 0)
+ m.p->count++;
+ if (p != 0 && --(p->count) <= 0)
+ delete p;
+ p = m.p;
+ filename = m.filename;
+ lineno = m.lineno;
+ length = m.length;
+ return *this;
+}
+
+void macro::append(unsigned char c)
+{
+ assert(c != 0);
+ if (p == 0)
+ p = new macro_header;
+ if (p->cl.length() != length) {
+ macro_header *tem = p->copy(length);
+ if (--(p->count) <= 0)
+ delete p;
+ p = tem;
+ }
+ p->cl.append(c);
+ ++length;
+}
+
+void macro::append(node *n)
+{
+ assert(n != 0);
+ if (p == 0)
+ p = new macro_header;
+ if (p->cl.length() != length) {
+ macro_header *tem = p->copy(length);
+ if (--(p->count) <= 0)
+ delete p;
+ p = tem;
+ }
+ p->cl.append(0);
+ p->nl.append(n);
+ ++length;
+}
+
+void macro::print_size()
+{
+ errprint("%1", length);
+}
+
+// make a copy of the first n bytes
+
+macro_header *macro_header::copy(int n)
+{
+ macro_header *p = new macro_header;
+ char_block *bp = cl.head;
+ unsigned char *ptr = bp->s;
+ node *nd = nl.head;
+ while (--n >= 0) {
+ if (ptr >= bp->s + char_block::SIZE) {
+ bp = bp->next;
+ ptr = bp->s;
+ }
+ int c = *ptr++;
+ p->cl.append(c);
+ if (c == 0) {
+ p->nl.append(nd->copy());
+ nd = nd->next;
+ }
+ }
+ return p;
+}
+
+void print_macros()
+{
+ object_dictionary_iterator iter(request_dictionary);
+ request_or_macro *rm;
+ symbol s;
+ while (iter.get(&s, (object **)&rm)) {
+ assert(!s.is_null());
+ macro *m = rm->to_macro();
+ if (m) {
+ errprint("%1\t", s.contents());
+ m->print_size();
+ errprint("\n");
+ }
+ }
+ fflush(stderr);
+ skip_line();
+}
+
+class string_iterator : public input_iterator {
+ macro mac;
+ const char *how_invoked;
+ int newline_flag;
+ int lineno;
+ char_block *bp;
+ int count; // of characters remaining
+ node *nd;
+protected:
+ symbol nm;
+ string_iterator();
+public:
+ string_iterator(const macro &m, const char *p = 0, symbol s = NULL_SYMBOL);
+ int fill(node **);
+ int peek();
+ int get_location(int, const char **, int *);
+ void backtrace();
+};
+
+string_iterator::string_iterator(const macro &m, const char *p, symbol s)
+: lineno(1), mac(m), newline_flag(0), how_invoked(p), nm(s)
+{
+ count = mac.length;
+ if (count != 0) {
+ bp = mac.p->cl.head;
+ nd = mac.p->nl.head;
+ ptr = eptr = bp->s;
+ }
+ else {
+ bp = 0;
+ nd = 0;
+ ptr = eptr = 0;
+ }
+}
+
+string_iterator::string_iterator()
+{
+ bp = 0;
+ nd = 0;
+ ptr = eptr = 0;
+ newline_flag = 0;
+ how_invoked = 0;
+ lineno = 1;
+ count = 0;
+}
+
+int string_iterator::fill(node **np)
+{
+ if (newline_flag)
+ lineno++;
+ newline_flag = 0;
+ if (count <= 0)
+ return EOF;
+ const unsigned char *p = eptr;
+ if (p >= bp->s + char_block::SIZE) {
+ bp = bp->next;
+ p = bp->s;
+ }
+ if (*p == '\0') {
+ if (np)
+ *np = nd->copy();
+ nd = nd->next;
+ eptr = ptr = p + 1;
+ count--;
+ return 0;
+ }
+ const unsigned char *e = bp->s + char_block::SIZE;
+ if (e - p > count)
+ e = p + count;
+ ptr = p;
+ while (p < e) {
+ unsigned char c = *p;
+ if (c == '\n' || c == ESCAPE_NEWLINE) {
+ newline_flag = 1;
+ p++;
+ break;
+ }
+ if (c == '\0')
+ break;
+ p++;
+ }
+ eptr = p;
+ count -= p - ptr;
+ return *ptr++;
+}
+
+int string_iterator::peek()
+{
+ if (count <= 0)
+ return EOF;
+ const unsigned char *p = eptr;
+ if (count <= 0)
+ return EOF;
+ if (p >= bp->s + char_block::SIZE) {
+ p = bp->next->s;
+ }
+ return *p;
+}
+
+int string_iterator::get_location(int allow_macro,
+ const char **filep, int *linep)
+{
+ if (!allow_macro)
+ return 0;
+ if (mac.filename == 0)
+ return 0;
+ *filep = mac.filename;
+ *linep = mac.lineno + lineno - 1;
+ return 1;
+}
+
+void string_iterator::backtrace()
+{
+ if (mac.filename) {
+ errprint("%1:%2: backtrace", mac.filename, mac.lineno + lineno - 1);
+ if (how_invoked) {
+ if (!nm.is_null())
+ errprint(": %1 `%2'\n", how_invoked, nm.contents());
+ else
+ errprint(": %1\n", how_invoked);
+ }
+ else
+ errprint("\n");
+ }
+}
+
+class temp_iterator : public input_iterator {
+ unsigned char *base;
+ temp_iterator(const char *, int len);
+public:
+ ~temp_iterator();
+ friend input_iterator *make_temp_iterator(const char *);
+};
+
+#ifdef __GNUG__
+inline
+#endif
+temp_iterator::temp_iterator(const char *s, int len)
+{
+ base = new unsigned char[len];
+ memcpy(base, s, len);
+ ptr = base;
+ eptr = base + len;
+}
+
+temp_iterator::~temp_iterator()
+{
+ a_delete base;
+}
+
+class small_temp_iterator : public input_iterator {
+private:
+ small_temp_iterator(const char *, int);
+ ~small_temp_iterator();
+ enum { BLOCK = 16 };
+ static small_temp_iterator *free_list;
+ void *operator new(size_t);
+ void operator delete(void *);
+ enum { SIZE = 12 };
+ unsigned char buf[SIZE];
+ friend input_iterator *make_temp_iterator(const char *);
+};
+
+small_temp_iterator *small_temp_iterator::free_list = 0;
+
+void *small_temp_iterator::operator new(size_t n)
+{
+ assert(n == sizeof(small_temp_iterator));
+ if (!free_list) {
+ free_list = (small_temp_iterator *)new char[sizeof(small_temp_iterator)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ small_temp_iterator *p = free_list;
+ free_list = (small_temp_iterator *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+#ifdef __GNUG__
+inline
+#endif
+void small_temp_iterator::operator delete(void *p)
+{
+ if (p) {
+ ((small_temp_iterator *)p)->next = free_list;
+ free_list = (small_temp_iterator *)p;
+ }
+}
+
+small_temp_iterator::~small_temp_iterator()
+{
+}
+
+
+#ifdef __GNUG__
+inline
+#endif
+small_temp_iterator::small_temp_iterator(const char *s, int len)
+{
+ for (int i = 0; i < len; i++)
+ buf[i] = s[i];
+ ptr = buf;
+ eptr = buf + len;
+}
+
+input_iterator *make_temp_iterator(const char *s)
+{
+ if (s == 0)
+ return new small_temp_iterator(s, 0);
+ else {
+ int n = strlen(s);
+ if (n <= small_temp_iterator::SIZE)
+ return new small_temp_iterator(s, n);
+ else
+ return new temp_iterator(s, n);
+ }
+}
+
+// this is used when macros are interpolated using the .macro_name notation
+
+struct arg_list {
+ macro mac;
+ arg_list *next;
+ arg_list(const macro &);
+ ~arg_list();
+};
+
+arg_list::arg_list(const macro &m) : mac(m), next(0)
+{
+}
+
+arg_list::~arg_list()
+{
+}
+
+class macro_iterator : public string_iterator {
+ arg_list *args;
+ int argc;
+public:
+ macro_iterator(symbol, macro &);
+ macro_iterator();
+ ~macro_iterator();
+ int has_args() { return 1; }
+ input_iterator *get_arg(int i);
+ int nargs() { return argc; }
+ void add_arg(const macro &m);
+ void shift(int n);
+};
+
+input_iterator *macro_iterator::get_arg(int i)
+{
+ if (i == 0)
+ return make_temp_iterator(nm.contents());
+ if (i > 0 && i <= argc) {
+ arg_list *p = args;
+ for (int j = 1; j < i; j++) {
+ assert(p != 0);
+ p = p->next;
+ }
+ return new string_iterator(p->mac);
+ }
+ else
+ return 0;
+}
+
+void macro_iterator::add_arg(const macro &m)
+{
+ for (arg_list **p = &args; *p; p = &((*p)->next))
+ ;
+ *p = new arg_list(m);
+ ++argc;
+}
+
+void macro_iterator::shift(int n)
+{
+ while (n > 0 && argc > 0) {
+ arg_list *tem = args;
+ args = args->next;
+ delete tem;
+ --argc;
+ --n;
+ }
+}
+
+// This gets used by eg .if '\?xxx\?''.
+
+int operator==(const macro &m1, const macro &m2)
+{
+ if (m1.length != m2.length)
+ return 0;
+ string_iterator iter1(m1);
+ string_iterator iter2(m2);
+ int n = m1.length;
+ while (--n >= 0) {
+ node *nd1 = 0;
+ int c1 = iter1.get(&nd1);
+ assert(c1 != EOF);
+ node *nd2 = 0;
+ int c2 = iter2.get(&nd2);
+ assert(c2 != EOF);
+ if (c1 != c2) {
+ if (c1 == 0)
+ delete nd1;
+ else if (c2 == 0)
+ delete nd2;
+ return 0;
+ }
+ if (c1 == 0) {
+ assert(nd1 != 0);
+ assert(nd2 != 0);
+ int are_same = nd1->type() == nd2->type() && nd1->same(nd2);
+ delete nd1;
+ delete nd2;
+ if (!are_same)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void interpolate_macro(symbol nm)
+{
+ request_or_macro *p = (request_or_macro *)request_dictionary.lookup(nm);
+ if (p == 0) {
+ int warned = 0;
+ const char *s = nm.contents();
+ if (strlen(s) > 2) {
+ request_or_macro *r;
+ char buf[3];
+ buf[0] = s[0];
+ buf[1] = s[1];
+ buf[2] = '\0';
+ r = (request_or_macro *)request_dictionary.lookup(symbol(buf));
+ if (r) {
+ macro *m = r->to_macro();
+ if (!m || !m->empty())
+ warned = warning(WARN_SPACE,
+ "space required between `%1' and argument", buf);
+ }
+ }
+ if (!warned) {
+ warning(WARN_MAC, "`%1' not defined", nm.contents());
+ p = new macro;
+ request_dictionary.define(nm, p);
+ }
+ }
+ if (p)
+ p->invoke(nm);
+ else {
+ skip_line();
+ return;
+ }
+}
+
+static void decode_args(macro_iterator *mi)
+{
+ if (!tok.newline() && !tok.eof()) {
+ node *n;
+ int c = get_copy(&n);
+ for (;;) {
+ while (c == ' ')
+ c = get_copy(&n);
+ if (c == '\n' || c == EOF)
+ break;
+ macro arg;
+ int quote_input_level = 0;
+ if (c == '\"') {
+ quote_input_level = input_stack::get_level();
+ c = get_copy(&n);
+ }
+ while (c != EOF && c != '\n' && !(c == ' ' && quote_input_level == 0)) {
+ if (quote_input_level > 0 && c == '\"'
+ && (compatible_flag
+ || input_stack::get_level() == quote_input_level)) {
+ c = get_copy(&n);
+ if (c == '"') {
+ arg.append(c);
+ c = get_copy(&n);
+ }
+ else
+ break;
+ }
+ else {
+ if (c == 0)
+ arg.append(n);
+ else
+ arg.append(c);
+ c = get_copy(&n);
+ }
+ }
+ mi->add_arg(arg);
+ }
+ }
+}
+
+void macro::invoke(symbol nm)
+{
+ macro_iterator *mi = new macro_iterator(nm, *this);
+ decode_args(mi);
+ input_stack::push(mi);
+ tok.next();
+}
+
+macro *macro::to_macro()
+{
+ return this;
+}
+
+int macro::empty()
+{
+ return length == 0;
+}
+
+macro_iterator::macro_iterator(symbol s, macro &m)
+: string_iterator(m, "macro", s), args(0), argc(0)
+{
+}
+
+macro_iterator::macro_iterator() : args(0), argc(0)
+{
+}
+
+macro_iterator::~macro_iterator()
+{
+ while (args != 0) {
+ arg_list *tem = args;
+ args = args->next;
+ delete tem;
+ }
+}
+
+void read_request()
+{
+ macro_iterator *mi = new macro_iterator;
+ int had_prompt = 0;
+ if (!tok.newline() && !tok.eof()) {
+ int c = get_copy(NULL);
+ while (c == ' ')
+ c = get_copy(NULL);
+ while (c != EOF && c != '\n' && c != ' ') {
+ if (!illegal_input_char(c)) {
+ fputc(c, stderr);
+ had_prompt = 1;
+ }
+ c = get_copy(NULL);
+ }
+ if (c == ' ') {
+ tok.make_space();
+ decode_args(mi);
+ }
+ }
+ fputc(had_prompt ? ':' : '\007', stderr);
+ fflush(stderr);
+ input_stack::push(mi);
+ macro mac;
+ int nl = 0;
+ int c;
+ while ((c = getchar()) != EOF) {
+ if (illegal_input_char(c))
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ else {
+ if (c == '\n') {
+ if (nl)
+ break;
+ else
+ nl = 1;
+ }
+ else
+ nl = 0;
+ mac.append(c);
+ }
+ }
+ input_stack::push(new string_iterator(mac));
+ tok.next();
+}
+
+
+void do_define_string(int append)
+{
+ symbol nm;
+ node *n;
+ int c;
+ nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ if (tok.newline())
+ c = '\n';
+ else if (tok.tab())
+ c = '\t';
+ else if (!tok.space()) {
+ error("bad string definition");
+ skip_line();
+ return;
+ }
+ else
+ c = get_copy(&n);
+ while (c == ' ')
+ c = get_copy(&n);
+ if (c == '"')
+ c = get_copy(&n);
+ macro mac;
+ request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);
+ macro *mm = rm ? rm->to_macro() : 0;
+ if (append && mm)
+ mac = *mm;
+ while (c != '\n' && c != EOF) {
+ if (c == 0)
+ mac.append(n);
+ else
+ mac.append((unsigned char)c);
+ c = get_copy(&n);
+ }
+ if (!mm) {
+ mm = new macro;
+ request_dictionary.define(nm, mm);
+ }
+ *mm = mac;
+ tok.next();
+}
+
+void define_string()
+{
+ do_define_string(0);
+}
+
+void append_string()
+{
+ do_define_string(1);
+}
+
+void define_character()
+{
+ node *n;
+ int c;
+ tok.skip();
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0) {
+ skip_line();
+ return;
+ }
+ tok.next();
+ if (tok.newline())
+ c = '\n';
+ else if (tok.tab())
+ c = '\t';
+ else if (!tok.space()) {
+ error("bad character definition");
+ skip_line();
+ return;
+ }
+ else
+ c = get_copy(&n);
+ while (c == ' ' || c == '\t')
+ c = get_copy(&n);
+ if (c == '"')
+ c = get_copy(&n);
+ macro *m = new macro;
+ while (c != '\n' && c != EOF) {
+ if (c == 0)
+ m->append(n);
+ else
+ m->append((unsigned char)c);
+ c = get_copy(&n);
+ }
+ m = ci->set_macro(m);
+ if (m)
+ delete m;
+ tok.next();
+}
+
+
+static void remove_character()
+{
+ tok.skip();
+ while (!tok.newline() && !tok.eof()) {
+ if (!tok.space() && !tok.tab()) {
+ charinfo *ci = tok.get_char(1);
+ if (!ci)
+ break;
+ macro *m = ci->set_macro(0);
+ if (m)
+ delete m;
+ }
+ tok.next();
+ }
+ skip_line();
+}
+
+static void interpolate_string(symbol nm)
+{
+ request_or_macro *p = lookup_request(nm);
+ macro *m = p->to_macro();
+ if (!m)
+ error("you can only invoke a string using \\*");
+ else {
+ string_iterator *si = new string_iterator(*m, "string", nm);
+ input_stack::push(si);
+ }
+}
+
+/* This class is used for the implementation of \$@. It is used for
+each of the closing double quotes. It artificially increases the
+input level by 2, so that the closing double quote will appear to have
+the same input level as the opening quote. */
+
+class end_quote_iterator : public input_iterator {
+ unsigned char buf[1];
+public:
+ end_quote_iterator();
+ ~end_quote_iterator() { }
+ int internal_level() { return 2; }
+};
+
+end_quote_iterator::end_quote_iterator()
+{
+ buf[0] = '"';
+ ptr = buf;
+ eptr = buf + 1;
+}
+
+static void interpolate_arg(symbol nm)
+{
+ const char *s = nm.contents();
+ if (!s || *s == '\0')
+ error("missing argument name");
+ else if (s[1] == 0 && csdigit(s[0]))
+ input_stack::push(input_stack::get_arg(s[0] - '0'));
+ else if (s[0] == '*' && s[1] == '\0') {
+ for (int i = input_stack::nargs(); i > 0; i--) {
+ input_stack::push(input_stack::get_arg(i));
+ if (i != 1)
+ input_stack::push(make_temp_iterator(" "));
+ }
+ }
+ else if (s[0] == '@' && s[1] == '\0') {
+ for (int i = input_stack::nargs(); i > 0; i--) {
+ input_stack::push(new end_quote_iterator);
+ input_stack::push(input_stack::get_arg(i));
+ input_stack::push(make_temp_iterator(i == 1 ? "\"" : " \""));
+ }
+ }
+ else {
+ for (const char *p = s; *p && csdigit(*p); p++)
+ ;
+ if (*p)
+ error("bad argument name `%1'", s);
+ else
+ input_stack::push(input_stack::get_arg(atoi(s)));
+ }
+}
+
+void handle_first_page_transition()
+{
+ push_token(tok);
+ topdiv->begin_page();
+}
+
+// We push back a token by wrapping it up in a token_node, and
+// wrapping that up in a string_iterator.
+
+static void push_token(const token &t)
+{
+ macro m;
+ m.append(new token_node(t));
+ input_stack::push(new string_iterator(m));
+}
+
+void push_page_ejector()
+{
+ static char buf[2] = { PAGE_EJECTOR, '\0' };
+ input_stack::push(make_temp_iterator(buf));
+}
+
+void handle_initial_request(unsigned char code)
+{
+ char buf[2];
+ buf[0] = code;
+ buf[1] = '\0';
+ macro mac;
+ mac.append(new token_node(tok));
+ input_stack::push(new string_iterator(mac));
+ input_stack::push(make_temp_iterator(buf));
+ topdiv->begin_page();
+ tok.next();
+}
+
+void handle_initial_title()
+{
+ handle_initial_request(TITLE_REQUEST);
+}
+
+int trap_sprung_flag = 0;
+int postpone_traps_flag = 0;
+symbol postponed_trap;
+
+void spring_trap(symbol nm)
+{
+ assert(!nm.is_null());
+ trap_sprung_flag = 1;
+ if (postpone_traps_flag) {
+ postponed_trap = nm;
+ return;
+ }
+ static char buf[2] = { BEGIN_TRAP, 0 };
+ static char buf2[2] = { END_TRAP, '\0' };
+ input_stack::push(make_temp_iterator(buf2));
+ request_or_macro *p = lookup_request(nm);
+ macro *m = p->to_macro();
+ if (m)
+ input_stack::push(new string_iterator(*m, "trap-invoked macro", nm));
+ else
+ error("you can't invoke a request with a trap");
+ input_stack::push(make_temp_iterator(buf));
+}
+
+void postpone_traps()
+{
+ postpone_traps_flag = 1;
+}
+
+int unpostpone_traps()
+{
+ postpone_traps_flag = 0;
+ if (!postponed_trap.is_null()) {
+ spring_trap(postponed_trap);
+ postponed_trap = NULL_SYMBOL;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+// this should be local to define_macro, but cfront 1.2 doesn't support that
+static symbol dot_symbol(".");
+
+enum define_mode { DEFINE_NORMAL, DEFINE_APPEND, DEFINE_IGNORE };
+
+void do_define_macro(define_mode mode)
+{
+ symbol nm;
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ }
+ symbol term = get_name(); // the request that terminates the definition
+ if (term.is_null())
+ term = dot_symbol;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ const char *start_filename;
+ int start_lineno;
+ int have_start_location = input_stack::get_location(0, &start_filename,
+ &start_lineno);
+ node *n;
+ // doing this here makes the line numbers come out right
+ int c = get_copy(&n, 1);
+ macro mac;
+ macro *mm = 0;
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ request_or_macro *rm =
+ (request_or_macro *)request_dictionary.lookup(nm);
+ if (rm)
+ mm = rm->to_macro();
+ if (mm && mode == DEFINE_APPEND)
+ mac = *mm;
+ }
+ int bol = 1;
+ for (;;) {
+ while (c == ESCAPE_NEWLINE) {
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND)
+ mac.append(c);
+ c = get_copy(&n, 1);
+ }
+ if (bol && c == '.') {
+ const char *s = term.contents();
+ int d;
+ // see if it matches term
+ for (int i = 0; s[i] != 0; i++) {
+ d = get_copy(&n);
+ if ((unsigned char)s[i] != d)
+ break;
+ }
+ if (s[i] == 0
+ && ((i == 2 && compatible_flag)
+ || (d = get_copy(&n)) == ' '
+ || d == '\n')) { // we found it
+ if (d == '\n')
+ tok.make_newline();
+ else
+ tok.make_space();
+ if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) {
+ if (!mm) {
+ mm = new macro;
+ request_dictionary.define(nm, mm);
+ }
+ *mm = mac;
+ }
+ if (term != dot_symbol)
+ interpolate_macro(term);
+ else
+ skip_line();
+ return;
+ }
+ if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) {
+ mac.append(c);
+ for (int j = 0; j < i; j++)
+ mac.append(s[j]);
+ }
+ c = d;
+ }
+ if (c == EOF) {
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ if (have_start_location)
+ error_with_file_and_line(start_filename, start_lineno,
+ "end of file while defining macro `%1'",
+ nm.contents());
+ else
+ error("end of file while defining macro `%1'", nm.contents());
+ }
+ else {
+ if (have_start_location)
+ error_with_file_and_line(start_filename, start_lineno,
+ "end of file while ignoring input lines");
+ else
+ error("end of file while ignoring input lines");
+ }
+ tok.next();
+ return;
+ }
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ if (c == 0)
+ mac.append(n);
+ else
+ mac.append(c);
+ }
+ bol = (c == '\n');
+ c = get_copy(&n, 1);
+ }
+}
+
+void define_macro()
+{
+ do_define_macro(DEFINE_NORMAL);
+}
+
+void append_macro()
+{
+ do_define_macro(DEFINE_APPEND);
+}
+
+void ignore()
+{
+ do_define_macro(DEFINE_IGNORE);
+}
+
+void remove_macro()
+{
+ for (;;) {
+ symbol s = get_name();
+ if (s.is_null())
+ break;
+ request_dictionary.remove(s);
+ }
+ skip_line();
+}
+
+void rename_macro()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null())
+ request_dictionary.rename(s1, s2);
+ }
+ skip_line();
+}
+
+void alias_macro()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null()) {
+ if (!request_dictionary.alias(s1, s2))
+ warning(WARN_MAC, "`%1' not defined", s2.contents());
+ }
+ }
+ skip_line();
+}
+
+void chop_macro()
+{
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m)
+ error("cannot chop request");
+ else if (m->length == 0)
+ error("cannot chop empty macro");
+ else
+ m->length -= 1;
+ }
+ skip_line();
+}
+
+void asciify_macro()
+{
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m)
+ error("cannot asciify request");
+ else {
+ macro am;
+ string_iterator iter(*m);
+ for (;;) {
+ node *nd;
+ int c = iter.get(&nd);
+ if (c == EOF)
+ break;
+ if (c != 0)
+ am.append(c);
+ else
+ nd->asciify(&am);
+ }
+ *m = am;
+ }
+ }
+ skip_line();
+}
+
+static void interpolate_environment_variable(symbol nm)
+{
+ const char *s = getenv(nm.contents());
+ if (s && *s)
+ input_stack::push(make_temp_iterator(s));
+}
+
+void interpolate_number_reg(symbol nm, int inc)
+{
+ reg *r = lookup_number_reg(nm);
+ if (inc < 0)
+ r->decrement();
+ else if (inc > 0)
+ r->increment();
+ input_stack::push(make_temp_iterator(r->get_string()));
+}
+
+static void interpolate_number_format(symbol nm)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r)
+ input_stack::push(make_temp_iterator(r->get_format()));
+}
+
+static int get_delim_number(units *n, int si, int prev_value)
+{
+ token start;
+ start.next();
+ if (start.delimiter(1)) {
+ tok.next();
+ if (get_number(n, si, prev_value)) {
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int get_delim_number(units *n, int si)
+{
+ token start;
+ start.next();
+ if (start.delimiter(1)) {
+ tok.next();
+ if (get_number(n, si)) {
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int get_line_arg(units *n, int si, charinfo **cp)
+{
+ token start;
+ start.next();
+ if (start.delimiter(1)) {
+ tok.next();
+ if (get_number(n, si)) {
+ if (tok.dummy())
+ tok.next();
+ if (start != tok) {
+ *cp = tok.get_char(1);
+ tok.next();
+ }
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int read_size(int *x)
+{
+ tok.next();
+ int c = tok.ch();
+ int inc = 0;
+ if (c == '-') {
+ inc = -1;
+ tok.next();
+ c = tok.ch();
+ }
+ else if (c == '+') {
+ inc = 1;
+ tok.next();
+ c = tok.ch();
+ }
+ int val;
+ int bad = 0;
+ if (c == '(') {
+ tok.next();
+ c = tok.ch();
+ if (!inc) {
+ // allow an increment either before or after the left parenthesis
+ if (c == '-') {
+ inc = -1;
+ tok.next();
+ c = tok.ch();
+ }
+ else if (c == '+') {
+ inc = 1;
+ tok.next();
+ c = tok.ch();
+ }
+ }
+ if (!csdigit(c))
+ bad = 1;
+ else {
+ val = c - '0';
+ tok.next();
+ c = tok.ch();
+ if (!csdigit(c))
+ bad = 1;
+ else {
+ val = val*10 + (c - '0');
+ val *= sizescale;
+ }
+ }
+ }
+ else if (csdigit(c)) {
+ val = c - '0';
+ if (!inc && c != '0' && c < '4') {
+ tok.next();
+ c = tok.ch();
+ if (!csdigit(c))
+ bad = 1;
+ else
+ val = val*10 + (c - '0');
+ }
+ val *= sizescale;
+ }
+ else if (!tok.delimiter(1))
+ return 0;
+ else {
+ token start(tok);
+ tok.next();
+ if (!(inc
+ ? get_number(&val, 'z')
+ : get_number(&val, 'z', curenv->get_requested_point_size())))
+ return 0;
+ if (!(start.ch() == '[' && tok.ch() == ']') && start != tok) {
+ if (start.ch() == '[')
+ error("missing `]'");
+ else
+ error("missing closing delimiter");
+ return 0;
+ }
+ }
+ if (!bad) {
+ switch (inc) {
+ case 0:
+ *x = val;
+ break;
+ case 1:
+ *x = curenv->get_requested_point_size() + val;
+ break;
+ case -1:
+ *x = curenv->get_requested_point_size() - val;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+ }
+ else {
+ error("bad digit in point size");
+ return 0;
+ }
+}
+
+static symbol get_delim_name()
+{
+ token start;
+ start.next();
+ if (start.eof()) {
+ error("end of input at start of delimited name");
+ return NULL_SYMBOL;
+ }
+ if (start.newline()) {
+ error("can't delimit name with a newline");
+ return NULL_SYMBOL;
+ }
+ int start_level = input_stack::get_level();
+ char abuf[ABUF_SIZE];
+ char *buf = abuf;
+ int buf_size = ABUF_SIZE;
+ int i = 0;
+ for (;;) {
+ if (i + 1 > buf_size) {
+ if (buf == abuf) {
+ buf = new char [ABUF_SIZE*2];
+ memcpy(buf, abuf, buf_size);
+ buf_size = ABUF_SIZE*2;
+ }
+ else {
+ char *old_buf = buf;
+ buf = new char[buf_size*2];
+ memcpy(buf, old_buf, buf_size);
+ buf_size *= 2;
+ a_delete old_buf;
+ }
+ }
+ tok.next();
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ if ((buf[i] = tok.ch()) == 0) {
+ error("missing delimiter (got %1)", tok.description());
+ if (buf != abuf)
+ a_delete buf;
+ return NULL_SYMBOL;
+ }
+ i++;
+ }
+ buf[i] = '\0';
+ if (buf == abuf) {
+ if (i == 0) {
+ error("empty delimited name");
+ return NULL_SYMBOL;
+ }
+ else
+ return symbol(buf);
+ }
+ else {
+ symbol s(buf);
+ a_delete buf;
+ return s;
+ }
+}
+
+
+// Implement \R
+
+static void do_register()
+{
+ token start;
+ start.next();
+ if (!start.delimiter(1))
+ return;
+ tok.next();
+ symbol nm = get_long_name(1);
+ if (nm.is_null())
+ return;
+ while (tok.space())
+ tok.next();
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ int prev_value;
+ if (!r || !r->get_value(&prev_value))
+ prev_value = 0;
+ int val;
+ if (!get_number(&val, 'u', prev_value))
+ return;
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ if (r)
+ r->set_value(val);
+ else
+ set_number_reg(nm, val);
+}
+
+// this implements the \w escape sequence
+
+static void do_width()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ environment env(curenv);
+ environment *oldenv = curenv;
+ curenv = &env;
+ for (;;) {
+ tok.next();
+ if (tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok.newline()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ input_stack::push(make_temp_iterator("\n"));
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ tok.process();
+ }
+ env.wrap_up_tab();
+ units x = env.get_input_line_position().to_units();
+ input_stack::push(make_temp_iterator(itoa(x)));
+ env.width_registers();
+ curenv = oldenv;
+}
+
+charinfo *page_character;
+
+void set_page_character()
+{
+ page_character = get_optional_char();
+ skip_line();
+}
+
+static const symbol percent_symbol("%");
+
+void read_title_parts(node **part, hunits *part_width)
+{
+ tok.skip();
+ if (tok.newline() || tok.eof())
+ return;
+ token start(tok);
+ int start_level = input_stack::get_level();
+ tok.next();
+ for (int i = 0; i < 3; i++) {
+ while (!tok.newline() && !tok.eof()) {
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level)) {
+ tok.next();
+ break;
+ }
+ if (page_character != 0 && tok.get_char() == page_character)
+ interpolate_number_reg(percent_symbol, 0);
+ else
+ tok.process();
+ tok.next();
+ }
+ curenv->wrap_up_tab();
+ part_width[i] = curenv->get_input_line_position();
+ part[i] = curenv->extract_output_line();
+ }
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+}
+
+class non_interpreted_node : public node {
+ macro mac;
+public:
+ non_interpreted_node(const macro &);
+ int interpret(macro *);
+ node *copy();
+ int same(node *);
+ const char *type();
+};
+
+non_interpreted_node::non_interpreted_node(const macro &m) : mac(m)
+{
+}
+
+int non_interpreted_node::same(node *nd)
+{
+ return mac == ((non_interpreted_node *)nd)->mac;
+}
+
+const char *non_interpreted_node::type()
+{
+ return "non_interpreted_node";
+}
+
+node *non_interpreted_node::copy()
+{
+ return new non_interpreted_node(mac);
+}
+
+int non_interpreted_node::interpret(macro *m)
+{
+ string_iterator si(mac);
+ node *n;
+ for (;;) {
+ int c = si.get(&n);
+ if (c == EOF)
+ break;
+ if (c == 0)
+ m->append(n);
+ else
+ m->append(c);
+ }
+ return 1;
+}
+
+static node *do_non_interpreted()
+{
+ node *n;
+ int c;
+ macro mac;
+ while ((c = get_copy(&n)) != ESCAPE_QUESTION && c != EOF && c != '\n')
+ if (c == 0)
+ mac.append(n);
+ else
+ mac.append(c);
+ if (c == EOF || c == '\n') {
+ error("missing \\?");
+ return 0;
+ }
+ return new non_interpreted_node(mac);
+}
+
+node *do_special()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ macro mac;
+ for (tok.next();
+ tok != start || input_stack::get_level() != start_level;
+ tok.next()) {
+ if (tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ return 0;
+ }
+ if (tok.newline()) {
+ input_stack::push(make_temp_iterator("\n"));
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ unsigned char c;
+ if (tok.space())
+ c = ' ';
+ else if (tok.tab())
+ c = '\t';
+ else if (tok.leader())
+ c = '\001';
+ else if (tok.backspace())
+ c = '\b';
+ else
+ c = tok.ch();
+ if (c == '\0')
+ error("%1 is illegal within \\X", tok.description());
+ else
+ mac.append(c);
+ }
+ return new special_node(mac);
+}
+
+void special_node::tprint(troff_output_file *out)
+{
+ tprint_start(out);
+ string_iterator iter(mac);
+ for (;;) {
+ int c = iter.get(NULL);
+ if (c == EOF)
+ break;
+ for (const char *s = ::asciify(c); *s; s++)
+ tprint_char(out, *s);
+ }
+ tprint_end(out);
+}
+
+int get_file_line(const char **filename, int *lineno)
+{
+ return input_stack::get_location(0, filename, lineno);
+}
+
+void line_file()
+{
+ int n;
+ if (get_integer(&n)) {
+ const char *filename = 0;
+ if (has_arg()) {
+ symbol s = get_long_name();
+ filename = s.contents();
+ }
+ (void)input_stack::set_location(filename, n-1);
+ }
+ skip_line();
+}
+
+static int nroff_mode = 0;
+
+static void nroff_request()
+{
+ nroff_mode = 1;
+ skip_line();
+}
+
+static void troff_request()
+{
+ nroff_mode = 0;
+ skip_line();
+}
+
+static void skip_alternative()
+{
+ int level = 0;
+ // ensure that ``.if 0\{'' works as expected
+ if (tok.left_brace())
+ level++;
+ int c;
+ for (;;) {
+ c = input_stack::get(NULL);
+ if (c == EOF)
+ break;
+ if (c == ESCAPE_LEFT_BRACE)
+ ++level;
+ else if (c == ESCAPE_RIGHT_BRACE)
+ --level;
+ else if (c == escape_char && escape_char > 0)
+ switch(input_stack::get(NULL)) {
+ case '{':
+ ++level;
+ break;
+ case '}':
+ --level;
+ break;
+ case '"':
+ while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ ;
+ }
+ /*
+ Note that the level can properly be < 0, eg
+
+ .if 1 \{\
+ .if 0 \{\
+ .\}\}
+
+ So don't give an error message in this case.
+ */
+ if (level <= 0 && c == '\n')
+ break;
+ }
+ tok.next();
+}
+
+static void begin_alternative()
+{
+ while (tok.space() || tok.left_brace())
+ tok.next();
+}
+
+
+static int_stack if_else_stack;
+
+int do_if_request()
+{
+ int invert = 0;
+ while (tok.space())
+ tok.next();
+ while (tok.ch() == '!') {
+ tok.next();
+ invert = !invert;
+ }
+ int result;
+ unsigned char c = tok.ch();
+ if (c == 't') {
+ tok.next();
+ result = !nroff_mode;
+ }
+ else if (c == 'n') {
+ tok.next();
+ result = nroff_mode;
+ }
+ else if (c == 'v') {
+ tok.next();
+ result = 0;
+ }
+ else if (c == 'o') {
+ result = (topdiv->get_page_number() & 1);
+ tok.next();
+ }
+ else if (c == 'e') {
+ result = !(topdiv->get_page_number() & 1);
+ tok.next();
+ }
+ else if (c == 'd' || c == 'r') {
+ tok.next();
+ symbol nm = get_name(1);
+ if (nm.is_null()) {
+ skip_alternative();
+ return 0;
+ }
+ result = (c == 'd'
+ ? request_dictionary.lookup(nm) != 0
+ : number_reg_dictionary.lookup(nm) != 0);
+ }
+ else if (c == 'c') {
+ tok.next();
+ tok.skip();
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0) {
+ skip_alternative();
+ return 0;
+ }
+ result = character_exists(ci, curenv);
+ tok.next();
+ }
+ else if (tok.space())
+ result = 0;
+ else if (tok.delimiter()) {
+ token delim = tok;
+ int delim_level = input_stack::get_level();
+ environment env1(curenv);
+ environment env2(curenv);
+ environment *oldenv = curenv;
+ curenv = &env1;
+ for (int i = 0; i < 2; i++) {
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ tok.next();
+ curenv = oldenv;
+ return 0;
+ }
+ if (tok == delim
+ && (compatible_flag || input_stack::get_level() == delim_level))
+ break;
+ tok.process();
+ }
+ curenv = &env2;
+ }
+ node *n1 = env1.extract_output_line();
+ node *n2 = env2.extract_output_line();
+ result = same_node_list(n1, n2);
+ delete_node_list(n1);
+ delete_node_list(n2);
+ tok.next();
+ curenv = oldenv;
+ }
+ else {
+ units n;
+ if (!get_number(&n, 'u')) {
+ skip_alternative();
+ return 0;
+ }
+ else
+ result = n > 0;
+ }
+ if (invert)
+ result = !result;
+ if (result)
+ begin_alternative();
+ else
+ skip_alternative();
+ return result;
+}
+
+void if_else_request()
+{
+ if_else_stack.push(do_if_request());
+}
+
+void if_request()
+{
+ do_if_request();
+}
+
+void else_request()
+{
+ if (if_else_stack.is_empty()) {
+ warning(WARN_EL, "unbalanced .el request");
+ skip_alternative();
+ }
+ else {
+ if (if_else_stack.pop())
+ skip_alternative();
+ else
+ begin_alternative();
+ }
+}
+
+static int while_depth = 0;
+static int while_break_flag = 0;
+
+void while_request()
+{
+ macro mac;
+ int escaped = 0;
+ int level = 0;
+ mac.append(new token_node(tok));
+ for (;;) {
+ node *n;
+ int c = input_stack::get(&n);
+ if (c == EOF)
+ break;
+ if (c == 0) {
+ escaped = 0;
+ mac.append(n);
+ }
+ else if (escaped) {
+ if (c == '{')
+ level += 1;
+ else if (c == '}')
+ level -= 1;
+ escaped = 0;
+ mac.append(c);
+ }
+ else {
+ if (c == ESCAPE_LEFT_BRACE)
+ level += 1;
+ else if (c == ESCAPE_RIGHT_BRACE)
+ level -= 1;
+ else if (c == escape_char)
+ escaped = 1;
+ mac.append(c);
+ if (c == '\n' && level <= 0)
+ break;
+ }
+ }
+ if (level != 0)
+ error("unbalanced \\{ \\}");
+ else {
+ while_depth++;
+ input_stack::add_boundary();
+ for (;;) {
+ input_stack::push(new string_iterator(mac, "while loop"));
+ tok.next();
+ if (!do_if_request()) {
+ while (input_stack::get(NULL) != EOF)
+ ;
+ break;
+ }
+ process_input_stack();
+ if (while_break_flag) {
+ while_break_flag = 0;
+ break;
+ }
+ }
+ input_stack::remove_boundary();
+ while_depth--;
+ }
+ tok.next();
+}
+
+void while_break_request()
+{
+ if (!while_depth) {
+ error("no while loop");
+ skip_line();
+ }
+ else {
+ while_break_flag = 1;
+ while (input_stack::get(NULL) != EOF)
+ ;
+ tok.next();
+ }
+}
+
+void while_continue_request()
+{
+ if (!while_depth) {
+ error("no while loop");
+ skip_line();
+ }
+ else {
+ while (input_stack::get(NULL) != EOF)
+ ;
+ tok.next();
+ }
+}
+
+// .so
+
+void source()
+{
+ symbol nm = get_long_name(1);
+ if (nm.is_null())
+ skip_line();
+ else {
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ errno = 0;
+ FILE *fp = fopen(nm.contents(), "r");
+ if (fp)
+ input_stack::push(new file_iterator(fp, nm.contents()));
+ else
+ error("can't open `%1': %2", nm.contents(), strerror(errno));
+ tok.next();
+ }
+}
+
+const char *asciify(int c)
+{
+ static char buf[3];
+ buf[0] = escape_char == '\0' ? '\\' : escape_char;
+ buf[1] = buf[2] = '\0';
+ switch (c) {
+ case ESCAPE_QUESTION:
+ buf[1] = '?';
+ break;
+ case ESCAPE_AMPERSAND:
+ buf[1] = '&';
+ break;
+ case ESCAPE_UNDERSCORE:
+ buf[1] = '_';
+ break;
+ case ESCAPE_BAR:
+ buf[1] = '|';
+ break;
+ case ESCAPE_CIRCUMFLEX:
+ buf[1] = '^';
+ break;
+ case ESCAPE_LEFT_BRACE:
+ buf[1] = '{';
+ break;
+ case ESCAPE_RIGHT_BRACE:
+ buf[1] = '}';
+ break;
+ case ESCAPE_LEFT_QUOTE:
+ buf[1] = '`';
+ break;
+ case ESCAPE_RIGHT_QUOTE:
+ buf[1] = '\'';
+ break;
+ case ESCAPE_HYPHEN:
+ buf[1] = '-';
+ break;
+ case ESCAPE_BANG:
+ buf[1] = '!';
+ break;
+ case ESCAPE_c:
+ buf[1] = 'c';
+ break;
+ case ESCAPE_e:
+ buf[1] = 'e';
+ break;
+ case ESCAPE_E:
+ buf[1] = 'E';
+ break;
+ case ESCAPE_PERCENT:
+ buf[1] = '%';
+ break;
+ case ESCAPE_SPACE:
+ buf[1] = ' ';
+ break;
+ default:
+ if (illegal_input_char(c))
+ buf[0] = '\0';
+ else
+ buf[0] = c;
+ break;
+ }
+ return buf;
+}
+
+
+const char *input_char_description(int c)
+{
+ switch (c) {
+ case '\n':
+ return "a newline character";
+ case '\b':
+ return "a backspace character";
+ case '\001':
+ return "a leader character";
+ case '\t':
+ return "a tab character ";
+ case ' ':
+ return "a space character";
+ case '\0':
+ return "a node";
+ }
+ static char buf[sizeof("magic character code ") + 1 + INT_DIGITS];
+ if (illegal_input_char(c)) {
+ const char *s = asciify(c);
+ if (*s) {
+ buf[0] = '`';
+ strcpy(buf + 1, s);
+ strcat(buf, "'");
+ return buf;
+ }
+ sprintf(buf, "magic character code %d", c);
+ return buf;
+ }
+ if (csprint(c)) {
+ buf[0] = '`';
+ buf[1] = c;
+ buf[2] = '\'';
+ return buf;
+ }
+ sprintf(buf, "character code %d", c);
+ return buf;
+}
+
+// .tm
+
+void terminal()
+{
+ if (!tok.newline() && !tok.eof()) {
+ int c;
+ while ((c = get_copy(NULL)) == ' ' || c == '\t')
+ ;
+ for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ fputs(asciify(c), stderr);
+ }
+ fputc('\n', stderr);
+ fflush(stderr);
+ tok.next();
+}
+
+dictionary stream_dictionary(20);
+
+void do_open(int append)
+{
+ symbol stream = get_name(1);
+ if (!stream.is_null()) {
+ symbol filename = get_long_name(1);
+ if (!filename.is_null()) {
+ errno = 0;
+ FILE *fp = fopen(filename.contents(), append ? "a" : "w");
+ if (!fp) {
+ error("can't open `%1' for %2: %3",
+ filename.contents(),
+ append ? "appending" : "writing",
+ strerror(errno));
+ fp = (FILE *)stream_dictionary.remove(stream);
+ }
+ else
+ fp = (FILE *)stream_dictionary.lookup(stream, fp);
+ if (fp)
+ fclose(fp);
+ }
+ }
+ skip_line();
+}
+
+void open_request()
+{
+ do_open(0);
+}
+
+void opena_request()
+{
+ do_open(1);
+}
+
+void close_request()
+{
+ symbol stream = get_name(1);
+ if (!stream.is_null()) {
+ FILE *fp = (FILE *)stream_dictionary.remove(stream);
+ if (!fp)
+ error("no stream named `%1'", stream.contents());
+ else
+ fclose(fp);
+ }
+ skip_line();
+}
+
+void write_request()
+{
+ symbol stream = get_name(1);
+ if (stream.is_null()) {
+ skip_line();
+ return;
+ }
+ FILE *fp = (FILE *)stream_dictionary.lookup(stream);
+ if (!fp) {
+ error("no stream named `%1'", stream.contents());
+ skip_line();
+ return;
+ }
+ int c;
+ while ((c = get_copy(NULL)) == ' ')
+ ;
+ if (c == '"')
+ c = get_copy(NULL);
+ for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ fputs(asciify(c), fp);
+ fputc('\n', fp);
+ fflush(fp);
+ tok.next();
+}
+
+static void init_charset_table()
+{
+ char buf[16];
+ strcpy(buf, "char");
+ for (int i = 0; i < 256; i++) {
+ strcpy(buf + 4, itoa(i));
+ charset_table[i] = get_charinfo(symbol(buf));
+ charset_table[i]->set_ascii_code(i);
+ if (csalpha(i))
+ charset_table[i]->set_hyphenation_code(cmlower(i));
+ }
+ charset_table['.']->set_flags(charinfo::ENDS_SENTENCE);
+ charset_table['?']->set_flags(charinfo::ENDS_SENTENCE);
+ charset_table['!']->set_flags(charinfo::ENDS_SENTENCE);
+ charset_table['-']->set_flags(charinfo::BREAK_AFTER);
+ charset_table['"']->set_flags(charinfo::TRANSPARENT);
+ charset_table['\'']->set_flags(charinfo::TRANSPARENT);
+ charset_table[')']->set_flags(charinfo::TRANSPARENT);
+ charset_table[']']->set_flags(charinfo::TRANSPARENT);
+ charset_table['*']->set_flags(charinfo::TRANSPARENT);
+ get_charinfo(symbol("dg"))->set_flags(charinfo::TRANSPARENT);
+ get_charinfo(symbol("rq"))->set_flags(charinfo::TRANSPARENT);
+ get_charinfo(symbol("em"))->set_flags(charinfo::BREAK_AFTER);
+ get_charinfo(symbol("ul"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
+ get_charinfo(symbol("rn"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
+ get_charinfo(symbol("ru"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
+ get_charinfo(symbol("br"))->set_flags(charinfo::OVERLAPS_VERTICALLY);
+ page_character = charset_table['%'];
+}
+
+static
+void do_translate(int translate_transparent)
+{
+ tok.skip();
+ while (!tok.newline() && !tok.eof()) {
+ if (tok.space()) {
+ // This is a really bizarre troff feature.
+ tok.next();
+ translate_space_to_dummy = tok.dummy();
+ if (tok.newline() || tok.eof())
+ break;
+ tok.next();
+ continue;
+ }
+ charinfo *ci1 = tok.get_char(1);
+ if (ci1 == 0)
+ break;
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ ci1->set_special_translation(charinfo::TRANSLATE_SPACE,
+ translate_transparent);
+ break;
+ }
+ if (tok.space())
+ ci1->set_special_translation(charinfo::TRANSLATE_SPACE,
+ translate_transparent);
+ else if (tok.dummy())
+ ci1->set_special_translation(charinfo::TRANSLATE_DUMMY,
+ translate_transparent);
+ else if (tok.hyphen_indicator())
+ ci1->set_special_translation(charinfo::TRANSLATE_HYPHEN_INDICATOR,
+ translate_transparent);
+ else {
+ charinfo *ci2 = tok.get_char(1);
+ if (ci2 == 0)
+ break;
+ if (ci1 == ci2)
+ ci1->set_translation(0, translate_transparent);
+ else
+ ci1->set_translation(ci2, translate_transparent);
+ }
+ tok.next();
+ }
+ skip_line();
+}
+
+void translate()
+{
+ do_translate(1);
+}
+
+void translate_no_transparent()
+{
+ do_translate(0);
+}
+
+void char_flags()
+{
+ int flags;
+ if (get_integer(&flags))
+ while (has_arg()) {
+ charinfo *ci = tok.get_char(1);
+ if (ci) {
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ ci->set_flags(flags);
+ }
+ tok.next();
+ }
+ skip_line();
+}
+
+void hyphenation_code()
+{
+ tok.skip();
+ while (!tok.newline() && !tok.eof()) {
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0)
+ break;
+ tok.next();
+ tok.skip();
+ unsigned char c = tok.ch();
+ if (c == 0) {
+ error("hyphenation code must be ordinary character");
+ break;
+ }
+ if (csdigit(c)) {
+ error("hyphenation code cannot be digit");
+ break;
+ }
+ ci->set_hyphenation_code(c);
+ tok.next();
+ }
+ skip_line();
+}
+
+charinfo *token::get_char(int required)
+{
+ if (type == TOKEN_CHAR)
+ return charset_table[c];
+ if (type == TOKEN_SPECIAL)
+ return get_charinfo(nm);
+ if (type == TOKEN_NUMBERED_CHAR)
+ return get_charinfo_by_number(val);
+ if (type == TOKEN_ESCAPE) {
+ if (escape_char != 0)
+ return charset_table[escape_char];
+ else {
+ error("`\\e' used while no current escape character");
+ return 0;
+ }
+ }
+ if (required) {
+ if (type == TOKEN_EOF || type == TOKEN_NEWLINE)
+ warning(WARN_MISSING, "missing normal or special character");
+ else
+ error("normal or special character expected (got %1)", description());
+ }
+ return 0;
+}
+
+charinfo *get_optional_char()
+{
+ while (tok.space())
+ tok.next();
+ charinfo *ci = tok.get_char();
+ if (!ci) {
+ if (!tok.newline() && !tok.eof() && !tok.right_brace() && !tok.tab())
+ error("normal or special character expected (got %1): "
+ "treated as missing",
+ tok.description());
+ }
+ else
+ tok.next();
+ return ci;
+}
+
+int token::add_to_node_list(node **pp)
+{
+ hunits w;
+ node *n = 0;
+ switch (type) {
+ case TOKEN_CHAR:
+ *pp = (*pp)->add_char(charset_table[c], curenv, &w);
+ break;
+ case TOKEN_DUMMY:
+ n = new dummy_node;
+ break;
+ case TOKEN_ESCAPE:
+ if (escape_char != 0)
+ *pp = (*pp)->add_char(charset_table[escape_char], curenv, &w);
+ break;
+ case TOKEN_HYPHEN_INDICATOR:
+ *pp = (*pp)->add_discretionary_hyphen();
+ break;
+ case TOKEN_ITALIC_CORRECTION:
+ *pp = (*pp)->add_italic_correction(&w);
+ break;
+ case TOKEN_LEFT_BRACE:
+ break;
+ case TOKEN_MARK_INPUT:
+ set_number_reg(nm, curenv->get_input_line_position().to_units());
+ break;
+ case TOKEN_NODE:
+ n = nd;
+ nd = 0;
+ break;
+ case TOKEN_NUMBERED_CHAR:
+ *pp = (*pp)->add_char(get_charinfo_by_number(val), curenv, &w);
+ break;
+ case TOKEN_RIGHT_BRACE:
+ break;
+ case TOKEN_SPACE:
+ n = new hmotion_node(curenv->get_space_width());
+ break;
+ case TOKEN_SPECIAL:
+ *pp = (*pp)->add_char(get_charinfo(nm), curenv, &w);
+ break;
+ default:
+ return 0;
+ }
+ if (n) {
+ n->next = *pp;
+ *pp = n;
+ }
+ return 1;
+}
+
+void token::process()
+{
+ if (possibly_handle_first_page_transition())
+ return;
+ switch (type) {
+ case TOKEN_BACKSPACE:
+ curenv->add_node(new hmotion_node(-curenv->get_space_width()));
+ break;
+ case TOKEN_CHAR:
+ curenv->add_char(charset_table[c]);
+ break;
+ case TOKEN_DUMMY:
+ curenv->add_node(new dummy_node);
+ break;
+ case TOKEN_EOF:
+ assert(0);
+ break;
+ case TOKEN_EMPTY:
+ assert(0);
+ break;
+ case TOKEN_ESCAPE:
+ if (escape_char != 0)
+ curenv->add_char(charset_table[escape_char]);
+ break;
+ case TOKEN_BEGIN_TRAP:
+ case TOKEN_END_TRAP:
+ case TOKEN_PAGE_EJECTOR:
+ // these are all handled in process_input_stack()
+ break;
+ case TOKEN_HYPHEN_INDICATOR:
+ curenv->add_hyphen_indicator();
+ break;
+ case TOKEN_INTERRUPT:
+ curenv->interrupt();
+ break;
+ case TOKEN_ITALIC_CORRECTION:
+ curenv->add_italic_correction();
+ break;
+ case TOKEN_LEADER:
+ curenv->handle_tab(1);
+ break;
+ case TOKEN_LEFT_BRACE:
+ break;
+ case TOKEN_MARK_INPUT:
+ set_number_reg(nm, curenv->get_input_line_position().to_units());
+ break;
+ case TOKEN_NEWLINE:
+ curenv->newline();
+ break;
+ case TOKEN_NODE:
+ curenv->add_node(nd);
+ nd = 0;
+ break;
+ case TOKEN_NUMBERED_CHAR:
+ curenv->add_char(get_charinfo_by_number(val));
+ break;
+ case TOKEN_REQUEST:
+ // handled in process_input_stack
+ break;
+ case TOKEN_RIGHT_BRACE:
+ break;
+ case TOKEN_SPACE:
+ curenv->space();
+ break;
+ case TOKEN_SPECIAL:
+ curenv->add_char(get_charinfo(nm));
+ break;
+ case TOKEN_SPREAD:
+ curenv->spread();
+ break;
+ case TOKEN_TAB:
+ curenv->handle_tab(0);
+ break;
+ case TOKEN_TRANSPARENT:
+ break;
+ default:
+ assert(0);
+ }
+}
+
+class nargs_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *nargs_reg::get_string()
+{
+ return itoa(input_stack::nargs());
+}
+
+class lineno_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *lineno_reg::get_string()
+{
+ int line;
+ const char *file;
+ if (!input_stack::get_location(0, &file, &line))
+ line = 0;
+ return itoa(line);
+}
+
+
+class writable_lineno_reg : public general_reg {
+public:
+ writable_lineno_reg();
+ void set_value(units);
+ int get_value(units *);
+};
+
+writable_lineno_reg::writable_lineno_reg()
+{
+}
+
+int writable_lineno_reg::get_value(units *res)
+{
+ int line;
+ const char *file;
+ if (!input_stack::get_location(0, &file, &line))
+ return 0;
+ *res = line;
+ return 1;
+}
+
+void writable_lineno_reg::set_value(units n)
+{
+ input_stack::set_location(0, n);
+}
+
+class filename_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *filename_reg::get_string()
+{
+ int line;
+ const char *file;
+ if (input_stack::get_location(0, &file, &line))
+ return file;
+ else
+ return 0;
+}
+
+
+class constant_reg : public reg {
+ const char *s;
+public:
+ constant_reg(const char *);
+ const char *get_string();
+};
+
+constant_reg::constant_reg(const char *p) : s(p)
+{
+}
+
+const char *constant_reg::get_string()
+{
+ return s;
+}
+
+constant_int_reg::constant_int_reg(int *q) : p(q)
+{
+}
+
+const char *constant_int_reg::get_string()
+{
+ return itoa(*p);
+}
+
+void abort_request()
+{
+ int c;
+ while ((c = get_copy(0)) == ' ')
+ ;
+ if (c == EOF || c == '\n')
+ fputs("User Abort.", stderr);
+ else {
+ for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ fputs(asciify(c), stderr);
+ }
+ fputc('\n', stderr);
+ cleanup_and_exit(1);
+}
+
+char *read_string()
+{
+ int len = 256;
+ char *s = new char[len];
+ int c;
+ while ((c = get_copy(0)) == ' ')
+ ;
+ int i = 0;
+ while (c != '\n' && c != EOF) {
+ if (!illegal_input_char(c)) {
+ if (i + 2 > len) {
+ char *tem = s;
+ s = new char[len*2];
+ memcpy(s, tem, len);
+ len *= 2;
+ a_delete tem;
+ }
+ s[i++] = c;
+ }
+ c = get_copy(0);
+ }
+ s[i] = '\0';
+ tok.next();
+ if (i == 0) {
+ a_delete s;
+ return 0;
+ }
+ return s;
+}
+
+void pipe_output()
+{
+ if (the_output) {
+ error("can't pipe: output already started");
+ skip_line();
+ }
+ else {
+ if ((pipe_command = read_string()) == 0)
+ error("can't pipe to empty command");
+ }
+}
+
+static int system_status;
+
+void system_request()
+{
+ char *command = read_string();
+ if (!command)
+ error("empty command");
+ else {
+ system_status = system(command);
+ a_delete command;
+ }
+}
+
+void copy_file()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_request(COPY_FILE_REQUEST);
+ return;
+ }
+ symbol filename = get_long_name(1);
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (!filename.is_null())
+ curdiv->copy_file(filename.contents());
+ tok.next();
+}
+
+#ifdef COLUMN
+
+void vjustify()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_request(VJUSTIFY_REQUEST);
+ return;
+ }
+ symbol type = get_long_name(1);
+ if (!type.is_null())
+ curdiv->vjustify(type);
+ skip_line();
+}
+
+#endif /* COLUMN */
+
+void transparent_file()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_request(TRANSPARENT_FILE_REQUEST);
+ return;
+ }
+ symbol filename = get_long_name(1);
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (!filename.is_null()) {
+ errno = 0;
+ FILE *fp = fopen(filename.contents(), "r");
+ if (!fp)
+ error("can't open `%1': %2", filename.contents(), strerror(errno));
+ else {
+ int bol = 1;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ else {
+ curdiv->transparent_output(c);
+ bol = c == '\n';
+ }
+ }
+ if (!bol)
+ curdiv->transparent_output('\n');
+ fclose(fp);
+ }
+ }
+ tok.next();
+}
+
+class page_range {
+ int first;
+ int last;
+public:
+ page_range *next;
+ page_range(int, int, page_range *);
+ int contains(int n);
+};
+
+page_range::page_range(int i, int j, page_range *p)
+: first(i), last(j), next(p)
+{
+}
+
+int page_range::contains(int n)
+{
+ return n >= first && (last <= 0 || n <= last);
+}
+
+page_range *output_page_list = 0;
+
+int in_output_page_list(int n)
+{
+ if (!output_page_list)
+ return 1;
+ for (page_range *p = output_page_list; p; p = p->next)
+ if (p->contains(n))
+ return 1;
+ return 0;
+}
+
+static void parse_output_page_list(char *p)
+{
+ for (;;) {
+ int i;
+ if (*p == '-')
+ i = 1;
+ else if (csdigit(*p)) {
+ i = 0;
+ do
+ i = i*10 + *p++ - '0';
+ while (csdigit(*p));
+ }
+ else
+ break;
+ int j;
+ if (*p == '-') {
+ p++;
+ j = 0;
+ if (csdigit(*p)) {
+ do
+ j = j*10 + *p++ - '0';
+ while (csdigit(*p));
+ }
+ }
+ else
+ j = i;
+ output_page_list = new page_range(i, j, output_page_list);
+ if (*p != ',')
+ break;
+ ++p;
+ }
+ if (*p != '\0') {
+ error("bad output page list");
+ output_page_list = 0;
+ }
+}
+
+static FILE *open_mac_file(const char *mac, char **path)
+{
+ char *s = new char[strlen(mac)+strlen(MACRO_PREFIX)+1];
+ strcpy(s, MACRO_PREFIX);
+ strcat(s, mac);
+ FILE *fp = macro_path.open_file(s, path);
+ a_delete s;
+ return fp;
+}
+
+static void process_macro_file(const char *mac)
+{
+ char *path;
+ FILE *fp = open_mac_file(mac, &path);
+ if (!fp)
+ fatal("can't find macro file %1", mac);
+ const char *s = symbol(path).contents();
+ a_delete path;
+ input_stack::push(new file_iterator(fp, s));
+ tok.next();
+ process_input_stack();
+}
+
+static void process_startup_file()
+{
+ char *path;
+ FILE *fp = macro_path.open_file(STARTUP_FILE, &path);
+ if (fp) {
+ input_stack::push(new file_iterator(fp, symbol(path).contents()));
+ a_delete path;
+ tok.next();
+ process_input_stack();
+ }
+}
+
+void macro_source()
+{
+ symbol nm = get_long_name(1);
+ if (nm.is_null())
+ skip_line();
+ else {
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ char *path;
+ FILE *fp = macro_path.open_file(nm.contents(), &path);
+ if (fp) {
+ input_stack::push(new file_iterator(fp, symbol(path).contents()));
+ a_delete path;
+ }
+ else
+ error("can't find macro file `%1'", nm.contents());
+ tok.next();
+ }
+}
+
+static void process_input_file(const char *name)
+{
+ FILE *fp;
+ if (strcmp(name, "-") == 0) {
+ clearerr(stdin);
+ fp = stdin;
+ }
+ else {
+ errno = 0;
+ fp = fopen(name, "r");
+ if (!fp)
+ fatal("can't open `%1': %2", name, strerror(errno));
+ }
+ input_stack::push(new file_iterator(fp, name));
+ tok.next();
+ process_input_stack();
+}
+
+// make sure the_input is empty before calling this
+
+static int evaluate_expression(const char *expr, units *res)
+{
+ input_stack::push(make_temp_iterator(expr));
+ tok.next();
+ int success = get_number(res, 'u');
+ while (input_stack::get(NULL) != EOF)
+ ;
+ return success;
+}
+
+static void do_register_assignment(const char *s)
+{
+ const char *p = strchr(s, '=');
+ if (!p) {
+ char buf[2];
+ buf[0] = s[0];
+ buf[1] = 0;
+ units n;
+ if (evaluate_expression(s + 1, &n))
+ set_number_reg(buf, n);
+ }
+ else {
+ char *buf = new char[p - s + 1];
+ memcpy(buf, s, p - s);
+ buf[p - s] = 0;
+ units n;
+ if (evaluate_expression(p + 1, &n))
+ set_number_reg(buf, n);
+ a_delete buf;
+ }
+}
+
+static void set_string(const char *name, const char *value)
+{
+ macro *m = new macro;
+ for (const char *p = value; *p; p++)
+ if (!illegal_input_char((unsigned char)*p))
+ m->append(*p);
+ request_dictionary.define(name, m);
+}
+
+
+static void do_string_assignment(const char *s)
+{
+ const char *p = strchr(s, '=');
+ if (!p) {
+ char buf[2];
+ buf[0] = s[0];
+ buf[1] = 0;
+ set_string(buf, s + 1);
+ }
+ else {
+ char *buf = new char[p - s + 1];
+ memcpy(buf, s, p - s);
+ buf[p - s] = 0;
+ set_string(buf, p + 1);
+ a_delete buf;
+ }
+}
+
+struct string_list {
+ const char *s;
+ string_list *next;
+ string_list(const char *ss) : s(ss), next(0) {}
+};
+
+static void add_string(const char *s, string_list **p)
+{
+ while (*p)
+ p = &((*p)->next);
+ *p = new string_list(s);
+}
+
+void usage(const char *prog)
+{
+ errprint(
+"usage: %1 -abivzCER -wname -Wname -dcstring -mname -nN -olist -rcN\n"
+" -Tname -Fdir -Mdir [ files ]\n",
+ prog);
+ exit(USAGE_EXIT_CODE);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ string_list *macros = 0;
+ string_list *register_assignments = 0;
+ string_list *string_assignments = 0;
+ int iflag = 0;
+ int tflag = 0;
+ int fflag = 0;
+ int nflag = 0;
+ int no_rc = 0; // don't process troffrc
+ int next_page_number;
+ opterr = 0;
+ hresolution = vresolution = 1;
+ while ((c = getopt(argc, argv, "abivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:R"))
+ != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "GNU troff version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'T':
+ device = optarg;
+ tflag = 1;
+ break;
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'M':
+ macro_path.command_line_dir(optarg);
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'm':
+ add_string(optarg, &macros);
+ break;
+ case 'E':
+ inhibit_errors = 1;
+ break;
+ case 'R':
+ no_rc = 1;
+ break;
+ case 'w':
+ enable_warning(optarg);
+ break;
+ case 'W':
+ disable_warning(optarg);
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'b':
+ backtrace_flag = 1;
+ break;
+ case 'a':
+ ascii_output_flag = 1;
+ break;
+ case 'z':
+ suppress_output_flag = 1;
+ break;
+ case 'n':
+ if (sscanf(optarg, "%d", &next_page_number) == 1)
+ nflag++;
+ else
+ error("bad page number");
+ break;
+ case 'o':
+ parse_output_page_list(optarg);
+ break;
+ case 'd':
+ if (*optarg == '\0')
+ error("`-d' requires non-empty argument");
+ else
+ add_string(optarg, &string_assignments);
+ break;
+ case 'r':
+ if (*optarg == '\0')
+ error("`-r' requires non-empty argument");
+ else
+ add_string(optarg, &register_assignments);
+ break;
+ case 'f':
+ default_family = symbol(optarg);
+ fflag = 1;
+ break;
+ case 'q':
+ case 's':
+ case 't':
+ // silently ignore these
+ break;
+ case '?':
+ usage(argv[0]);
+ default:
+ assert(0);
+ }
+ set_string(".T", device);
+ init_charset_table();
+ if (!font::load_desc())
+ fatal("sorry, I can't continue");
+ units_per_inch = font::res;
+ hresolution = font::hor;
+ vresolution = font::vert;
+ sizescale = font::sizescale;
+ tcommand_flag = font::tcommand;
+ if (!fflag && font::family != 0 && *font::family != '\0')
+ default_family = symbol(font::family);
+ font_size::init_size_table(font::sizes);
+ int i;
+ int j = 1;
+ if (font::style_table) {
+ for (i = 0; font::style_table[i]; i++)
+ mount_style(j++, symbol(font::style_table[i]));
+ }
+ for (i = 0; font::font_name_table[i]; i++, j++)
+ // In the DESC file a font name of 0 (zero) means leave this
+ // position empty.
+ if (strcmp(font::font_name_table[i], "0") != 0)
+ mount_font(j, symbol(font::font_name_table[i]));
+ curdiv = topdiv = new top_level_diversion;
+ if (nflag)
+ topdiv->set_next_page_number(next_page_number);
+ init_input_requests();
+ init_env_requests();
+ init_div_requests();
+#ifdef COLUMN
+ init_column_requests();
+#endif /* COLUMN */
+ init_node_requests();
+ number_reg_dictionary.define(".T", new constant_reg(tflag ? "1" : "0"));
+ init_registers();
+ init_reg_requests();
+ init_hyphen_requests();
+ init_environments();
+ while (string_assignments) {
+ do_string_assignment(string_assignments->s);
+ string_list *tem = string_assignments;
+ string_assignments = string_assignments->next;
+ delete tem;
+ }
+ while (register_assignments) {
+ do_register_assignment(register_assignments->s);
+ string_list *tem = register_assignments;
+ register_assignments = register_assignments->next;
+ delete tem;
+ }
+ if (!no_rc)
+ process_startup_file();
+ while (macros) {
+ process_macro_file(macros->s);
+ string_list *tem = macros;
+ macros = macros->next;
+ delete tem;
+ }
+ for (i = optind; i < argc; i++)
+ process_input_file(argv[i]);
+ if (optind >= argc || iflag)
+ process_input_file("-");
+ exit_troff();
+}
+
+void warn_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n)) {
+ if (n & ~WARN_TOTAL) {
+ warning(WARN_RANGE, "warning mask must be between 0 and %1", WARN_TOTAL);
+ n &= WARN_TOTAL;
+ }
+ warning_mask = n;
+ }
+ else
+ warning_mask = WARN_TOTAL;
+ skip_line();
+}
+
+static void init_registers()
+{
+#ifdef LONG_FOR_TIME_T
+ long
+#else /* not LONG_FOR_TIME_T */
+ time_t
+#endif /* not LONG_FOR_TIME_T */
+ t = time(0);
+ // Use struct here to work around misfeature in old versions of g++.
+ struct tm *tt = localtime(&t);
+ set_number_reg("dw", int(tt->tm_wday + 1));
+ set_number_reg("dy", int(tt->tm_mday));
+ set_number_reg("mo", int(tt->tm_mon + 1));
+ set_number_reg("yr", int(tt->tm_year));
+ set_number_reg("$$", getpid());
+ number_reg_dictionary.define(".A",
+ new constant_reg(ascii_output_flag
+ ? "1"
+ : "0"));
+}
+
+void init_input_requests()
+{
+ init_request("ds", define_string);
+ init_request("as", append_string);
+ init_request("de", define_macro);
+ init_request("am", append_macro);
+ init_request("ig", ignore);
+ init_request("rm", remove_macro);
+ init_request("rn", rename_macro);
+ init_request("if", if_request);
+ init_request("ie", if_else_request);
+ init_request("el", else_request);
+ init_request("so", source);
+ init_request("nx", next_file);
+ init_request("pm", print_macros);
+ init_request("eo", escape_off);
+ init_request("ec", set_escape_char);
+ init_request("pc", set_page_character);
+ init_request("tm", terminal);
+ init_request("ex", exit_request);
+ init_request("em", end_macro);
+ init_request("tr", translate);
+ init_request("trnt", translate_no_transparent);
+ init_request("ab", abort_request);
+ init_request("pi", pipe_output);
+ init_request("cf", copy_file);
+ init_request("sy", system_request);
+ init_request("lf", line_file);
+ init_request("cflags", char_flags);
+ init_request("shift", shift);
+ init_request("rd", read_request);
+ init_request("cp", compatible);
+ init_request("char", define_character);
+ init_request("rchar", remove_character);
+ init_request("hcode", hyphenation_code);
+ init_request("while", while_request);
+ init_request("break", while_break_request);
+ init_request("continue", while_continue_request);
+ init_request("als", alias_macro);
+ init_request("backtrace", backtrace_request);
+ init_request("chop", chop_macro);
+ init_request("asciify", asciify_macro);
+ init_request("warn", warn_request);
+ init_request("open", open_request);
+ init_request("opena", opena_request);
+ init_request("close", close_request);
+ init_request("write", write_request);
+ init_request("trf", transparent_file);
+#ifdef WIDOW_CONTROL
+ init_request("fpl", flush_pending_lines);
+#endif /* WIDOW_CONTROL */
+ init_request("nroff", nroff_request);
+ init_request("troff", troff_request);
+#ifdef COLUMN
+ init_request("vj", vjustify);
+#endif /* COLUMN */
+ init_request("mso", macro_source);
+ init_request("do", do_request);
+ number_reg_dictionary.define("systat", new variable_reg(&system_status));
+ number_reg_dictionary.define("slimit",
+ new variable_reg(&input_stack::limit));
+ number_reg_dictionary.define(".$", new nargs_reg);
+ number_reg_dictionary.define(".c", new lineno_reg);
+ number_reg_dictionary.define("c.", new writable_lineno_reg);
+ number_reg_dictionary.define(".F", new filename_reg);
+ number_reg_dictionary.define(".C", new constant_int_reg(&compatible_flag));
+ number_reg_dictionary.define(".H", new constant_int_reg(&hresolution));
+ number_reg_dictionary.define(".V", new constant_int_reg(&vresolution));
+ number_reg_dictionary.define(".R", new constant_reg("10000"));
+ extern const char *major_version;
+ number_reg_dictionary.define(".x", new constant_reg(major_version));
+ extern const char *minor_version;
+ number_reg_dictionary.define(".y", new constant_reg(minor_version));
+ number_reg_dictionary.define(".g", new constant_reg("1"));
+ number_reg_dictionary.define(".warn", new constant_int_reg(&warning_mask));
+}
+
+object_dictionary request_dictionary(501);
+
+void init_request(const char *s, REQUEST_FUNCP f)
+{
+ request_dictionary.define(s, new request(f));
+}
+
+static request_or_macro *lookup_request(symbol nm)
+{
+ assert(!nm.is_null());
+ request_or_macro *p = (request_or_macro *)request_dictionary.lookup(nm);
+ if (p == 0) {
+ warning(WARN_MAC, "`%1' not defined", nm.contents());
+ p = new macro;
+ request_dictionary.define(nm, p);
+ }
+ return p;
+}
+
+
+node *charinfo_to_node_list(charinfo *ci, const environment *envp)
+{
+ // Don't interpret character definitions in compatible mode.
+ int old_compatible_flag = compatible_flag;
+ compatible_flag = 0;
+ int old_escape_char = escape_char;
+ escape_char = '\\';
+ macro *mac = ci->set_macro(0);
+ assert(mac != 0);
+ environment *oldenv = curenv;
+ environment env(envp);
+ curenv = &env;
+ curenv->set_composite();
+ token old_tok = tok;
+ input_stack::add_boundary();
+ string_iterator *si = new string_iterator(*mac, "composite character", ci->nm);
+ input_stack::push(si);
+ // we don't use process_input_stack, because we don't want to recognise
+ // requests
+ for (;;) {
+ tok.next();
+ if (tok.eof())
+ break;
+ if (tok.newline()) {
+ error("composite character mustn't contain newline");
+ while (!tok.eof())
+ tok.next();
+ break;
+ }
+ else
+ tok.process();
+ }
+ node *n = curenv->extract_output_line();
+ input_stack::remove_boundary();
+ ci->set_macro(mac);
+ tok = old_tok;
+ curenv = oldenv;
+ compatible_flag = old_compatible_flag;
+ escape_char = old_escape_char;
+ return n;
+}
+
+static node *read_draw_node()
+{
+ token start;
+ start.next();
+ if (!start.delimiter(1)){
+ do {
+ tok.next();
+ } while (tok != start && !tok.newline() && !tok.eof());
+ }
+ else {
+ tok.next();
+ if (tok == start)
+ error("missing argument");
+ else {
+ unsigned char type = tok.ch();
+ tok.next();
+ int maxpoints = 10;
+ hvpair *point = new hvpair[maxpoints];
+ int npoints = 0;
+ int no_last_v = 0;
+ int err = 0;
+ int i;
+ for (i = 0; tok != start; i++) {
+ if (i == maxpoints) {
+ hvpair *oldpoint = point;
+ point = new hvpair[maxpoints*2];
+ for (int j = 0; j < maxpoints; j++)
+ point[j] = oldpoint[j];
+ maxpoints *= 2;
+ a_delete oldpoint;
+ }
+ if (!get_hunits(&point[i].h, 'm')) {
+ err = 1;
+ break;
+ }
+ ++npoints;
+ tok.skip();
+ point[i].v = V0;
+ if (tok == start) {
+ no_last_v = 1;
+ break;
+ }
+ if (!get_vunits(&point[i].v, 'v')) {
+ err = 1;
+ break;
+ }
+ tok.skip();
+ }
+ while (tok != start && !tok.newline() && !tok.eof())
+ tok.next();
+ if (!err) {
+ switch (type) {
+ case 'l':
+ if (npoints != 1 || no_last_v) {
+ error("two arguments needed for line");
+ npoints = 1;
+ }
+ break;
+ case 'c':
+ if (npoints != 1 || !no_last_v) {
+ error("one argument needed for circle");
+ npoints = 1;
+ point[0].v = V0;
+ }
+ break;
+ case 'e':
+ if (npoints != 1 || no_last_v) {
+ error("two arguments needed for ellipse");
+ npoints = 1;
+ }
+ break;
+ case 'a':
+ if (npoints != 2 || no_last_v) {
+ error("four arguments needed for arc");
+ npoints = 2;
+ }
+ break;
+ case '~':
+ if (no_last_v)
+ error("even number of arguments needed for spline");
+ break;
+ default:
+ // silently pass it through
+ break;
+ }
+ draw_node *dn = new draw_node(type, point, npoints,
+ curenv->get_font_size());
+ a_delete point;
+ return dn;
+ }
+ else {
+ a_delete point;
+ }
+ }
+ }
+ return 0;
+}
+
+static struct {
+ const char *name;
+ int mask;
+} warning_table[] = {
+ "char", WARN_CHAR,
+ "range", WARN_RANGE,
+ "break", WARN_BREAK,
+ "delim", WARN_DELIM,
+ "el", WARN_EL,
+ "scale", WARN_SCALE,
+ "number", WARN_NUMBER,
+ "syntax", WARN_SYNTAX,
+ "tab", WARN_TAB,
+ "right-brace", WARN_RIGHT_BRACE,
+ "missing", WARN_MISSING,
+ "input", WARN_INPUT,
+ "escape", WARN_ESCAPE,
+ "space", WARN_SPACE,
+ "font", WARN_FONT,
+ "di", WARN_DI,
+ "mac", WARN_MAC,
+ "reg", WARN_REG,
+ "all", WARN_TOTAL & ~(WARN_DI | WARN_MAC | WARN_REG),
+ "w", WARN_TOTAL,
+ "default", DEFAULT_WARNING_MASK,
+};
+
+static int lookup_warning(const char *name)
+{
+ for (int i = 0;
+ i < sizeof(warning_table)/sizeof(warning_table[0]);
+ i++)
+ if (strcmp(name, warning_table[i].name) == 0)
+ return warning_table[i].mask;
+ return 0;
+}
+
+static void enable_warning(const char *name)
+{
+ int mask = lookup_warning(name);
+ if (mask)
+ warning_mask |= mask;
+ else
+ error("unknown warning `%1'", name);
+}
+
+static void disable_warning(const char *name)
+{
+ int mask = lookup_warning(name);
+ if (mask)
+ warning_mask &= ~mask;
+ else
+ error("unknown warning `%1'", name);
+}
+
+enum error_type { WARNING, ERROR, FATAL };
+
+static void do_error(error_type type,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ if (inhibit_errors && type < FATAL)
+ return;
+ if (backtrace_flag)
+ input_stack::backtrace();
+ if (!get_file_line(&filename, &lineno))
+ filename = 0;
+ if (filename)
+ errprint("%1:%2: ", filename, lineno);
+ else if (program_name)
+ fprintf(stderr, "%s: ", program_name);
+ switch (type) {
+ case FATAL:
+ fputs("fatal error: ", stderr);
+ break;
+ case ERROR:
+ break;
+ case WARNING:
+ fputs("warning: ", stderr);
+ break;
+ }
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+ if (type == FATAL)
+ cleanup_and_exit(1);
+}
+
+int warning(warning_type t,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ if ((t & warning_mask) != 0) {
+ do_error(WARNING, format, arg1, arg2, arg3);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void error(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(ERROR, format, arg1, arg2, arg3);
+}
+
+void fatal(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(FATAL, format, arg1, arg2, arg3);
+}
+
+void fatal_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ fprintf(stderr, "%s:%d: fatal error: ", filename, lineno);
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+ cleanup_and_exit(1);
+}
+
+void error_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ fprintf(stderr, "%s:%d: error: ", filename, lineno);
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+}
+
+dictionary charinfo_dictionary(501);
+
+charinfo *get_charinfo(symbol nm)
+{
+ void *p = charinfo_dictionary.lookup(nm);
+ if (p != 0)
+ return (charinfo *)p;
+ charinfo *cp = new charinfo(nm);
+ (void)charinfo_dictionary.lookup(nm, cp);
+ return cp;
+}
+
+int charinfo::next_index = 0;
+
+charinfo::charinfo(symbol s)
+: nm(s), hyphenation_code(0), translation(0), flags(0), ascii_code(0),
+ special_translation(TRANSLATE_NONE), mac(0), not_found(0),
+ transparent_translate(1)
+{
+ index = next_index++;
+}
+
+void charinfo::set_hyphenation_code(unsigned char c)
+{
+ hyphenation_code = c;
+}
+
+void charinfo::set_translation(charinfo *ci, int tt)
+{
+ translation = ci;
+ special_translation = TRANSLATE_NONE;
+ transparent_translate = tt;
+}
+
+void charinfo::set_special_translation(int c, int tt)
+{
+ special_translation = c;
+ translation = 0;
+ transparent_translate = tt;
+}
+
+void charinfo::set_ascii_code(unsigned char c)
+{
+ ascii_code = c;
+}
+
+macro *charinfo::set_macro(macro *m)
+{
+ macro *tem = mac;
+ mac = m;
+ return tem;
+}
+
+void charinfo::set_number(int n)
+{
+ number = n;
+ flags |= NUMBERED;
+}
+
+int charinfo::get_number()
+{
+ assert(flags & NUMBERED);
+ return number;
+}
+
+symbol UNNAMED_SYMBOL("---");
+
+// For numbered characters not between 0 and 255, we make a symbol out
+// of the number and store them in this dictionary.
+
+dictionary numbered_charinfo_dictionary(11);
+
+charinfo *get_charinfo_by_number(int n)
+{
+ static charinfo *number_table[256];
+
+ if (n >= 0 && n < 256) {
+ charinfo *ci = number_table[n];
+ if (!ci) {
+ ci = new charinfo(UNNAMED_SYMBOL);
+ ci->set_number(n);
+ number_table[n] = ci;
+ }
+ return ci;
+ }
+ else {
+ symbol ns(itoa(n));
+ charinfo *ci = (charinfo *)numbered_charinfo_dictionary.lookup(ns);
+ if (!ci) {
+ ci = new charinfo(UNNAMED_SYMBOL);
+ ci->set_number(n);
+ numbered_charinfo_dictionary.lookup(ns, ci);
+ }
+ return ci;
+ }
+}
+
+int font::name_to_index(const char *nm)
+{
+ charinfo *ci;
+ if (nm[1] == 0)
+ ci = charset_table[nm[0] & 0xff];
+ else if (nm[0] == '\\' && nm[2] == 0)
+ ci = get_charinfo(symbol(nm + 1));
+ else
+ ci = get_charinfo(symbol(nm));
+ if (ci == 0)
+ return -1;
+ else
+ return ci->get_index();
+}
+
+int font::number_to_index(int n)
+{
+ return get_charinfo_by_number(n)->get_index();
+}
diff --git a/gnu/usr.bin/groff/troff/node.cc b/gnu/usr.bin/groff/troff/node.cc
new file mode 100644
index 000000000000..6d36519d7516
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/node.cc
@@ -0,0 +1,4845 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "charinfo.h"
+#include "font.h"
+#include "reg.h"
+
+#define STORE_WIDTH 1
+
+symbol HYPHEN_SYMBOL("hy");
+
+// Character used when a hyphen is inserted at a line break.
+static charinfo *soft_hyphen_char;
+
+enum constant_space_type {
+ CONSTANT_SPACE_NONE,
+ CONSTANT_SPACE_RELATIVE,
+ CONSTANT_SPACE_ABSOLUTE
+ };
+
+struct special_font_list {
+ int n;
+ special_font_list *next;
+};
+
+special_font_list *global_special_fonts;
+static int global_ligature_mode = 1;
+static int global_kern_mode = 1;
+
+class track_kerning_function {
+ int non_zero;
+ units min_size;
+ hunits min_amount;
+ units max_size;
+ hunits max_amount;
+public:
+ track_kerning_function();
+ track_kerning_function(units, hunits, units, hunits);
+ int operator==(const track_kerning_function &);
+ int operator!=(const track_kerning_function &);
+ hunits compute(int point_size);
+};
+
+// embolden fontno when this is the current font
+
+struct conditional_bold {
+ conditional_bold *next;
+ int fontno;
+ hunits offset;
+ conditional_bold(int, hunits, conditional_bold * = 0);
+};
+
+struct tfont;
+
+class font_info {
+ tfont *last_tfont;
+ int number;
+ font_size last_size;
+ int last_height;
+ int last_slant;
+ symbol internal_name;
+ symbol external_name;
+ font *fm;
+ char is_bold;
+ hunits bold_offset;
+ track_kerning_function track_kern;
+ constant_space_type is_constant_spaced;
+ units constant_space;
+ int last_ligature_mode;
+ int last_kern_mode;
+ conditional_bold *cond_bold_list;
+ void flush();
+public:
+ special_font_list *sf;
+
+ font_info(symbol nm, int n, symbol enm, font *f);
+ int contains(charinfo *);
+ void set_bold(hunits);
+ void unbold();
+ void set_conditional_bold(int, hunits);
+ void conditional_unbold(int);
+ void set_track_kern(track_kerning_function &);
+ void set_constant_space(constant_space_type, units = 0);
+ int is_named(symbol);
+ symbol get_name();
+ tfont *get_tfont(font_size, int, int, int);
+ hunits get_space_width(font_size, int);
+ hunits get_narrow_space_width(font_size);
+ hunits get_half_narrow_space_width(font_size);
+ int get_bold(hunits *);
+ int is_special();
+ int is_style();
+};
+
+class tfont_spec {
+protected:
+ symbol name;
+ int input_position;
+ font *fm;
+ font_size size;
+ char is_bold;
+ char is_constant_spaced;
+ int ligature_mode;
+ int kern_mode;
+ hunits bold_offset;
+ hunits track_kern; // add this to the width
+ hunits constant_space_width;
+ int height;
+ int slant;
+public:
+ tfont_spec(symbol nm, int pos, font *, font_size, int, int);
+ tfont_spec plain();
+ int operator==(const tfont_spec &);
+ friend tfont *font_info::get_tfont(font_size fs, int, int, int);
+};
+
+class tfont : public tfont_spec {
+ static tfont *tfont_list;
+ tfont *next;
+ tfont *plain_version;
+public:
+ tfont(tfont_spec &);
+ int contains(charinfo *);
+ hunits get_width(charinfo *c);
+ int get_bold(hunits *);
+ int get_constant_space(hunits *);
+ hunits get_track_kern();
+ tfont *get_plain();
+ font_size get_size();
+ symbol get_name();
+ charinfo *get_lig(charinfo *c1, charinfo *c2);
+ int get_kern(charinfo *c1, charinfo *c2, hunits *res);
+ int get_input_position();
+ int get_character_type(charinfo *);
+ int get_height();
+ int get_slant();
+ vunits get_char_height(charinfo *);
+ vunits get_char_depth(charinfo *);
+ hunits get_char_skew(charinfo *);
+ hunits get_italic_correction(charinfo *);
+ hunits get_left_italic_correction(charinfo *);
+ hunits get_subscript_correction(charinfo *);
+ friend tfont *make_tfont(tfont_spec &);
+};
+
+inline int env_definite_font(environment *env)
+{
+ return env->get_family()->make_definite(env->get_font());
+}
+
+static void invalidate_fontno(int n);
+
+/* font_info functions */
+
+static font_info **font_table = 0;
+static int font_table_size = 0;
+
+font_info::font_info(symbol nm, int n, symbol enm, font *f)
+: internal_name(nm), external_name(enm), fm(f), number(n),
+ is_constant_spaced(CONSTANT_SPACE_NONE),
+ sf(0), is_bold(0), cond_bold_list(0),
+ last_ligature_mode(1), last_kern_mode(1),
+ last_tfont(0), last_size(0)
+{
+}
+
+inline int font_info::contains(charinfo *ci)
+{
+ return fm != 0 && fm->contains(ci->get_index());
+}
+
+inline int font_info::is_special()
+{
+ return fm != 0 && fm->is_special();
+}
+
+inline int font_info::is_style()
+{
+ return fm == 0;
+}
+
+// this is the current_font, fontno is where we found the character,
+// presumably a special font
+
+tfont *font_info::get_tfont(font_size fs, int height, int slant, int fontno)
+{
+ if (last_tfont == 0 || fs != last_size
+ || height != last_height || slant != last_slant
+ || global_ligature_mode != last_ligature_mode
+ || global_kern_mode != last_kern_mode
+ || fontno != number) {
+ font_info *f = font_table[fontno];
+ tfont_spec spec(f->external_name, f->number, f->fm, fs, height, slant);
+ for (conditional_bold *p = cond_bold_list; p; p = p->next)
+ if (p->fontno == fontno) {
+ spec.is_bold = 1;
+ spec.bold_offset = p->offset;
+ break;
+ }
+ if (!spec.is_bold && is_bold) {
+ spec.is_bold = 1;
+ spec.bold_offset = bold_offset;
+ }
+ spec.track_kern = track_kern.compute(fs.to_scaled_points());
+ spec.ligature_mode = global_ligature_mode;
+ spec.kern_mode = global_kern_mode;
+ switch (is_constant_spaced) {
+ case CONSTANT_SPACE_NONE:
+ break;
+ case CONSTANT_SPACE_ABSOLUTE:
+ spec.is_constant_spaced = 1;
+ spec.constant_space_width = constant_space;
+ break;
+ case CONSTANT_SPACE_RELATIVE:
+ spec.is_constant_spaced = 1;
+ spec.constant_space_width
+ = scale(constant_space*fs.to_scaled_points(),
+ units_per_inch,
+ 36*72*sizescale);
+ break;
+ default:
+ assert(0);
+ }
+ if (fontno != number)
+ return make_tfont(spec);
+ last_tfont = make_tfont(spec);
+ last_size = fs;
+ last_height = height;
+ last_slant = slant;
+ last_ligature_mode = global_ligature_mode;
+ last_kern_mode = global_kern_mode;
+ }
+ return last_tfont;
+}
+
+int font_info::get_bold(hunits *res)
+{
+ if (is_bold) {
+ *res = bold_offset;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void font_info::unbold()
+{
+ if (is_bold) {
+ is_bold = 0;
+ flush();
+ }
+}
+
+void font_info::set_bold(hunits offset)
+{
+ if (!is_bold || offset != bold_offset) {
+ is_bold = 1;
+ bold_offset = offset;
+ flush();
+ }
+}
+
+void font_info::set_conditional_bold(int fontno, hunits offset)
+{
+ for (conditional_bold *p = cond_bold_list; p; p = p->next)
+ if (p->fontno == fontno) {
+ if (offset != p->offset) {
+ p->offset = offset;
+ flush();
+ }
+ return;
+ }
+ cond_bold_list = new conditional_bold(fontno, offset, cond_bold_list);
+}
+
+conditional_bold::conditional_bold(int f, hunits h, conditional_bold *x)
+ : fontno(f), offset(h), next(x)
+{
+}
+
+void font_info::conditional_unbold(int fontno)
+{
+ for (conditional_bold **p = &cond_bold_list; *p; p = &(*p)->next)
+ if ((*p)->fontno == fontno) {
+ conditional_bold *tem = *p;
+ *p = (*p)->next;
+ delete tem;
+ flush();
+ return;
+ }
+}
+
+void font_info::set_constant_space(constant_space_type type, units x)
+{
+ if (type != is_constant_spaced
+ || (type != CONSTANT_SPACE_NONE && x != constant_space)) {
+ flush();
+ is_constant_spaced = type;
+ constant_space = x;
+ }
+}
+
+void font_info::set_track_kern(track_kerning_function &tk)
+{
+ if (track_kern != tk) {
+ track_kern = tk;
+ flush();
+ }
+}
+
+void font_info::flush()
+{
+ last_tfont = 0;
+}
+
+int font_info::is_named(symbol s)
+{
+ return internal_name == s;
+}
+
+symbol font_info::get_name()
+{
+ return internal_name;
+}
+
+hunits font_info::get_space_width(font_size fs, int space_size)
+{
+ if (is_constant_spaced == CONSTANT_SPACE_NONE)
+ return scale(hunits(fm->get_space_width(fs.to_scaled_points())),
+ space_size, 12);
+ else if (is_constant_spaced == CONSTANT_SPACE_ABSOLUTE)
+ return constant_space;
+ else
+ return scale(constant_space*fs.to_scaled_points(),
+ units_per_inch, 36*72*sizescale);
+}
+
+hunits font_info::get_narrow_space_width(font_size fs)
+{
+ charinfo *ci = get_charinfo(symbol("|"));
+ if (fm->contains(ci->get_index()))
+ return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
+ else
+ return hunits(fs.to_units()/6);
+}
+
+hunits font_info::get_half_narrow_space_width(font_size fs)
+{
+ charinfo *ci = get_charinfo(symbol("^"));
+ if (fm->contains(ci->get_index()))
+ return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
+ else
+ return hunits(fs.to_units()/12);
+}
+
+/* tfont */
+
+tfont_spec::tfont_spec(symbol nm, int n, font *f,
+ font_size s, int h, int sl)
+ : name(nm), input_position(n), fm(f), size(s),
+ is_bold(0), is_constant_spaced(0), ligature_mode(1), kern_mode(1),
+ height(h), slant(sl)
+{
+ if (height == size.to_scaled_points())
+ height = 0;
+}
+
+int tfont_spec::operator==(const tfont_spec &spec)
+{
+ if (fm == spec.fm
+ && size == spec.size
+ && input_position == spec.input_position
+ && name == spec.name
+ && height == spec.height
+ && slant == spec.slant
+ && (is_bold
+ ? (spec.is_bold && bold_offset == spec.bold_offset)
+ : !spec.is_bold)
+ && track_kern == spec.track_kern
+ && (is_constant_spaced
+ ? (spec.is_constant_spaced
+ && constant_space_width == spec.constant_space_width)
+ : !spec.is_constant_spaced)
+ && ligature_mode == spec.ligature_mode
+ && kern_mode == spec.kern_mode)
+ return 1;
+ else
+ return 0;
+}
+
+tfont_spec tfont_spec::plain()
+{
+ return tfont_spec(name, input_position, fm, size, height, slant);
+}
+
+hunits tfont::get_width(charinfo *c)
+{
+ if (is_constant_spaced)
+ return constant_space_width;
+ else if (is_bold)
+ return (hunits(fm->get_width(c->get_index(), size.to_scaled_points()))
+ + track_kern + bold_offset);
+ else
+ return (hunits(fm->get_width(c->get_index(), size.to_scaled_points())) + track_kern);
+}
+
+vunits tfont::get_char_height(charinfo *c)
+{
+ vunits v = fm->get_height(c->get_index(), size.to_scaled_points());
+ if (height != 0 && height != size.to_scaled_points())
+ return scale(v, height, size.to_scaled_points());
+ else
+ return v;
+}
+
+vunits tfont::get_char_depth(charinfo *c)
+{
+ vunits v = fm->get_depth(c->get_index(), size.to_scaled_points());
+ if (height != 0 && height != size.to_scaled_points())
+ return scale(v, height, size.to_scaled_points());
+ else
+ return v;
+}
+
+hunits tfont::get_char_skew(charinfo *c)
+{
+ return hunits(fm->get_skew(c->get_index(), size.to_scaled_points(), slant));
+}
+
+hunits tfont::get_italic_correction(charinfo *c)
+{
+ return hunits(fm->get_italic_correction(c->get_index(), size.to_scaled_points()));
+}
+
+hunits tfont::get_left_italic_correction(charinfo *c)
+{
+ return hunits(fm->get_left_italic_correction(c->get_index(),
+ size.to_scaled_points()));
+}
+
+hunits tfont::get_subscript_correction(charinfo *c)
+{
+ return hunits(fm->get_subscript_correction(c->get_index(),
+ size.to_scaled_points()));
+}
+
+inline int tfont::get_input_position()
+{
+ return input_position;
+}
+
+inline int tfont::contains(charinfo *ci)
+{
+ return fm->contains(ci->get_index());
+}
+
+inline int tfont::get_character_type(charinfo *ci)
+{
+ return fm->get_character_type(ci->get_index());
+}
+
+inline int tfont::get_bold(hunits *res)
+{
+ if (is_bold) {
+ *res = bold_offset;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+inline int tfont::get_constant_space(hunits *res)
+{
+ if (is_constant_spaced) {
+ *res = constant_space_width;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+inline hunits tfont::get_track_kern()
+{
+ return track_kern;
+}
+
+inline tfont *tfont::get_plain()
+{
+ return plain_version;
+}
+
+inline font_size tfont::get_size()
+{
+ return size;
+}
+
+inline symbol tfont::get_name()
+{
+ return name;
+}
+
+inline int tfont::get_height()
+{
+ return height;
+}
+
+inline int tfont::get_slant()
+{
+ return slant;
+}
+
+symbol SYMBOL_ff("ff");
+symbol SYMBOL_fi("fi");
+symbol SYMBOL_fl("fl");
+symbol SYMBOL_Fi("Fi");
+symbol SYMBOL_Fl("Fl");
+
+charinfo *tfont::get_lig(charinfo *c1, charinfo *c2)
+{
+ if (ligature_mode == 0)
+ return 0;
+ charinfo *ci = 0;
+ if (c1->get_ascii_code() == 'f') {
+ switch (c2->get_ascii_code()) {
+ case 'f':
+ if (fm->has_ligature(font::LIG_ff))
+ ci = get_charinfo(SYMBOL_ff);
+ break;
+ case 'i':
+ if (fm->has_ligature(font::LIG_fi))
+ ci = get_charinfo(SYMBOL_fi);
+ break;
+ case 'l':
+ if (fm->has_ligature(font::LIG_fl))
+ ci = get_charinfo(SYMBOL_fl);
+ break;
+ }
+ }
+ else if (ligature_mode != 2 && c1->nm == SYMBOL_ff) {
+ switch (c2->get_ascii_code()) {
+ case 'i':
+ if (fm->has_ligature(font::LIG_ffi))
+ ci = get_charinfo(SYMBOL_Fi);
+ break;
+ case 'l':
+ if (fm->has_ligature(font::LIG_ffl))
+ ci = get_charinfo(SYMBOL_Fl);
+ break;
+ }
+ }
+ if (ci != 0 && fm->contains(ci->get_index()))
+ return ci;
+ return 0;
+}
+
+inline int tfont::get_kern(charinfo *c1, charinfo *c2, hunits *res)
+{
+ if (kern_mode == 0)
+ return 0;
+ else {
+ int n = fm->get_kern(c1->get_index(),
+ c2->get_index(),
+ size.to_scaled_points());
+ if (n) {
+ *res = hunits(n);
+ return 1;
+ }
+ else
+ return 0;
+ }
+}
+
+tfont *make_tfont(tfont_spec &spec)
+{
+ for (tfont *p = tfont::tfont_list; p; p = p->next)
+ if (*p == spec)
+ return p;
+ return new tfont(spec);
+}
+
+tfont *tfont::tfont_list = 0;
+
+tfont::tfont(tfont_spec &spec) : tfont_spec(spec)
+{
+ next = tfont_list;
+ tfont_list = this;
+ tfont_spec plain_spec = plain();
+ for (tfont *p = tfont_list; p; p = p->next)
+ if (*p == plain_spec) {
+ plain_version = p;
+ break;
+ }
+ if (!p)
+ plain_version = new tfont(plain_spec);
+}
+
+/* output_file */
+
+class real_output_file : public output_file {
+ int piped;
+ int printing;
+ virtual void really_transparent_char(unsigned char) = 0;
+ virtual void really_print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after) = 0;
+ virtual void really_begin_page(int pageno, vunits page_length) = 0;
+ virtual void really_copy_file(hunits x, vunits y, const char *filename);
+protected:
+ FILE *fp;
+public:
+ real_output_file();
+ ~real_output_file();
+ void flush();
+ void transparent_char(unsigned char);
+ void print_line(hunits x, vunits y, node *n, vunits before, vunits after);
+ void begin_page(int pageno, vunits page_length);
+ int is_printing();
+ void copy_file(hunits x, vunits y, const char *filename);
+};
+
+class suppress_output_file : public real_output_file {
+public:
+ suppress_output_file();
+ void really_transparent_char(unsigned char);
+ void really_print_line(hunits x, vunits y, node *n, vunits, vunits);
+ void really_begin_page(int pageno, vunits page_length);
+};
+
+class ascii_output_file : public real_output_file {
+public:
+ ascii_output_file();
+ void really_transparent_char(unsigned char);
+ void really_print_line(hunits x, vunits y, node *n, vunits, vunits);
+ void really_begin_page(int pageno, vunits page_length);
+ void outc(unsigned char c);
+ void outs(const char *s);
+};
+
+void ascii_output_file::outc(unsigned char c)
+{
+ fputc(c, fp);
+}
+
+void ascii_output_file::outs(const char *s)
+{
+ fputc('<', fp);
+ if (s)
+ fputs(s, fp);
+ fputc('>', fp);
+}
+
+struct hvpair;
+
+class troff_output_file : public real_output_file {
+ units hpos;
+ units vpos;
+ units output_vpos;
+ units output_hpos;
+ int force_motion;
+ int current_size;
+ int current_slant;
+ int current_height;
+ tfont *current_tfont;
+ int current_font_number;
+ symbol *font_position;
+ int nfont_positions;
+ enum { TBUF_SIZE = 256 };
+ char tbuf[TBUF_SIZE];
+ int tbuf_len;
+ int tbuf_kern;
+ int begun_page;
+ void do_motion();
+ void put(char c);
+ void put(unsigned char c);
+ void put(int i);
+ void put(const char *s);
+ void set_font(tfont *tf);
+ void flush_tbuf();
+public:
+ troff_output_file();
+ ~troff_output_file();
+ void trailer(vunits page_length);
+ void put_char(charinfo *ci, tfont *tf);
+ void put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k);
+ void right(hunits);
+ void down(vunits);
+ void moveto(hunits, vunits);
+ void start_special();
+ void special_char(unsigned char c);
+ void end_special();
+ void word_marker();
+ void really_transparent_char(unsigned char c);
+ void really_print_line(hunits x, vunits y, node *n, vunits before, vunits after);
+ void really_begin_page(int pageno, vunits page_length);
+ void really_copy_file(hunits x, vunits y, const char *filename);
+ void draw(char, hvpair *, int, font_size);
+ int get_hpos() { return hpos; }
+ int get_vpos() { return vpos; }
+};
+
+static void put_string(const char *s, FILE *fp)
+{
+ for (; *s != '\0'; ++s)
+ putc(*s, fp);
+}
+
+inline void troff_output_file::put(char c)
+{
+ putc(c, fp);
+}
+
+inline void troff_output_file::put(unsigned char c)
+{
+ putc(c, fp);
+}
+
+inline void troff_output_file::put(const char *s)
+{
+ put_string(s, fp);
+}
+
+inline void troff_output_file::put(int i)
+{
+ put_string(itoa(i), fp);
+}
+
+void troff_output_file::start_special()
+{
+ flush_tbuf();
+ do_motion();
+ put("x X ");
+}
+
+void troff_output_file::special_char(unsigned char c)
+{
+ put(c);
+ if (c == '\n')
+ put('+');
+}
+
+void troff_output_file::end_special()
+{
+ put('\n');
+}
+
+inline void troff_output_file::moveto(hunits h, vunits v)
+{
+ hpos = h.to_units();
+ vpos = v.to_units();
+}
+
+void troff_output_file::really_print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after)
+{
+ moveto(x, y);
+ while (n != 0) {
+ n->tprint(this);
+ n = n->next;
+ }
+ flush_tbuf();
+ // This ensures that transparent throughput will have a more predictable
+ // position.
+ do_motion();
+ force_motion = 1;
+ hpos = 0;
+ put('n');
+ put(before.to_units());
+ put(' ');
+ put(after.to_units());
+ put('\n');
+}
+
+inline void troff_output_file::word_marker()
+{
+ flush_tbuf();
+ put('w');
+}
+
+inline void troff_output_file::right(hunits n)
+{
+ hpos += n.to_units();
+}
+
+inline void troff_output_file::down(vunits n)
+{
+ vpos += n.to_units();
+}
+
+void troff_output_file::do_motion()
+{
+ if (force_motion) {
+ put('V');
+ put(vpos);
+ put('\n');
+ put('H');
+ put(hpos);
+ put('\n');
+ }
+ else {
+ if (hpos != output_hpos) {
+ units n = hpos - output_hpos;
+ if (n > 0 && n < hpos) {
+ put('h');
+ put(n);
+ }
+ else {
+ put('H');
+ put(hpos);
+ }
+ put('\n');
+ }
+ if (vpos != output_vpos) {
+ units n = vpos - output_vpos;
+ if (n > 0 && n < vpos) {
+ put('v');
+ put(n);
+ }
+ else {
+ put('V');
+ put(vpos);
+ }
+ put('\n');
+ }
+ }
+ output_vpos = vpos;
+ output_hpos = hpos;
+ force_motion = 0;
+}
+
+void troff_output_file::flush_tbuf()
+{
+ if (tbuf_len == 0)
+ return;
+ if (tbuf_kern == 0)
+ put('t');
+ else {
+ put('u');
+ put(tbuf_kern);
+ put(' ');
+ }
+ for (int i = 0; i < tbuf_len; i++)
+ put(tbuf[i]);
+ put('\n');
+ tbuf_len = 0;
+}
+
+void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
+ hunits k)
+{
+ if (tf != current_tfont) {
+ flush_tbuf();
+ set_font(tf);
+ }
+ char c = ci->get_ascii_code();
+ int kk = k.to_units();
+ if (c == '\0') {
+ flush_tbuf();
+ do_motion();
+ if (ci->numbered()) {
+ put('N');
+ put(ci->get_number());
+ }
+ else {
+ put('C');
+ const char *s = ci->nm.contents();
+ if (s[1] == 0) {
+ put('\\');
+ put(s[0]);
+ }
+ else
+ put(s);
+ }
+ put('\n');
+ hpos += w.to_units() + kk;
+ }
+ else if (tcommand_flag) {
+ if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos
+ && kk == tbuf_kern
+ && tbuf_len < TBUF_SIZE) {
+ tbuf[tbuf_len++] = c;
+ output_hpos += w.to_units() + kk;
+ hpos = output_hpos;
+ return;
+ }
+ flush_tbuf();
+ do_motion();
+ tbuf[tbuf_len++] = c;
+ output_hpos += w.to_units() + kk;
+ tbuf_kern = kk;
+ hpos = output_hpos;
+ }
+ else {
+ // flush_tbuf();
+ int n = hpos - output_hpos;
+ if (vpos == output_vpos && n > 0 && n < 100 && !force_motion) {
+ put(char(n/10 + '0'));
+ put(char(n%10 + '0'));
+ put(c);
+ output_hpos = hpos;
+ }
+ else {
+ do_motion();
+ put('c');
+ put(c);
+ }
+ hpos += w.to_units() + kk;
+ }
+}
+
+void troff_output_file::put_char(charinfo *ci, tfont *tf)
+{
+ flush_tbuf();
+ if (tf != current_tfont)
+ set_font(tf);
+ char c = ci->get_ascii_code();
+ if (c == '\0') {
+ do_motion();
+ if (ci->numbered()) {
+ put('N');
+ put(ci->get_number());
+ }
+ else {
+ put('C');
+ const char *s = ci->nm.contents();
+ if (s[1] == 0) {
+ put('\\');
+ put(s[0]);
+ }
+ else
+ put(s);
+ }
+ put('\n');
+ }
+ else {
+ int n = hpos - output_hpos;
+ if (vpos == output_vpos && n > 0 && n < 100) {
+ put(char(n/10 + '0'));
+ put(char(n%10 + '0'));
+ put(c);
+ output_hpos = hpos;
+ }
+ else {
+ do_motion();
+ put('c');
+ put(c);
+ }
+ }
+}
+
+void troff_output_file::set_font(tfont *tf)
+{
+ if (current_tfont == tf)
+ return;
+ int n = tf->get_input_position();
+ symbol nm = tf->get_name();
+ if (n >= nfont_positions || font_position[n] != nm) {
+ put("x font ");
+ put(n);
+ put(' ');
+ put(nm.contents());
+ put('\n');
+ if (n >= nfont_positions) {
+ int old_nfont_positions = nfont_positions;
+ symbol *old_font_position = font_position;
+ nfont_positions *= 3;
+ nfont_positions /= 2;
+ if (nfont_positions <= n)
+ nfont_positions = n + 10;
+ font_position = new symbol[nfont_positions];
+ memcpy(font_position, old_font_position,
+ old_nfont_positions*sizeof(symbol));
+ a_delete old_font_position;
+ }
+ font_position[n] = nm;
+ }
+ if (current_font_number != n) {
+ put('f');
+ put(n);
+ put('\n');
+ current_font_number = n;
+ }
+ int size = tf->get_size().to_scaled_points();
+ if (current_size != size) {
+ put('s');
+ put(size);
+ put('\n');
+ current_size = size;
+ }
+ int slant = tf->get_slant();
+ if (current_slant != slant) {
+ put("x Slant ");
+ put(slant);
+ put('\n');
+ current_slant = slant;
+ }
+ int height = tf->get_height();
+ if (current_height != height) {
+ put("x Height ");
+ put(height == 0 ? current_size : height);
+ put('\n');
+ current_height = height;
+ }
+ current_tfont = tf;
+}
+
+void troff_output_file::draw(char code, hvpair *point, int npoints,
+ font_size fsize)
+{
+ flush_tbuf();
+ do_motion();
+ int size = fsize.to_scaled_points();
+ if (current_size != size) {
+ put('s');
+ put(size);
+ put('\n');
+ current_size = size;
+ current_tfont = 0;
+ }
+ put('D');
+ put(code);
+ int i;
+ if (code == 'c') {
+ put(' ');
+ put(point[0].h.to_units());
+ }
+ else
+ for (i = 0; i < npoints; i++) {
+ put(' ');
+ put(point[i].h.to_units());
+ put(' ');
+ put(point[i].v.to_units());
+ }
+ for (i = 0; i < npoints; i++)
+ output_hpos += point[i].h.to_units();
+ hpos = output_hpos;
+ if (code != 'e') {
+ for (i = 0; i < npoints; i++)
+ output_vpos += point[i].v.to_units();
+ vpos = output_vpos;
+ }
+ put('\n');
+}
+
+void troff_output_file::really_begin_page(int pageno, vunits page_length)
+{
+ flush_tbuf();
+ if (begun_page) {
+ if (page_length > V0) {
+ put('V');
+ put(page_length.to_units());
+ put('\n');
+ }
+ }
+ else
+ begun_page = 1;
+ current_tfont = 0;
+ current_font_number = -1;
+ current_size = 0;
+ // current_height = 0;
+ // current_slant = 0;
+ hpos = 0;
+ vpos = 0;
+ output_hpos = 0;
+ output_vpos = 0;
+ force_motion = 1;
+ for (int i = 0; i < nfont_positions; i++)
+ font_position[i] = NULL_SYMBOL;
+ put('p');
+ put(pageno);
+ put('\n');
+}
+
+void troff_output_file::really_copy_file(hunits x, vunits y, const char *filename)
+{
+ moveto(x, y);
+ flush_tbuf();
+ do_motion();
+ errno = 0;
+ FILE *ifp = fopen(filename, "r");
+ if (ifp == 0)
+ error("can't open `%1': %2", filename, strerror(errno));
+ else {
+ int c;
+ while ((c = getc(ifp)) != EOF)
+ put(char(c));
+ fclose(ifp);
+ }
+ force_motion = 1;
+ current_size = 0;
+ current_tfont = 0;
+ current_font_number = -1;
+ for (int i = 0; i < nfont_positions; i++)
+ font_position[i] = NULL_SYMBOL;
+}
+
+void troff_output_file::really_transparent_char(unsigned char c)
+{
+ put(c);
+}
+
+troff_output_file::~troff_output_file()
+{
+ a_delete font_position;
+}
+
+void troff_output_file::trailer(vunits page_length)
+{
+ flush_tbuf();
+ if (page_length > V0) {
+ put("x trailer\n");
+ put('V');
+ put(page_length.to_units());
+ put('\n');
+ }
+ put("x stop\n");
+}
+
+troff_output_file::troff_output_file()
+: current_height(0), current_slant(0), tbuf_len(0), nfont_positions(10),
+ begun_page(0)
+{
+ font_position = new symbol[nfont_positions];
+ put("x T ");
+ put(device);
+ put('\n');
+ put("x res ");
+ put(units_per_inch);
+ put(' ');
+ put(hresolution);
+ put(' ');
+ put(vresolution);
+ put('\n');
+ put("x init\n");
+}
+
+/* output_file */
+
+output_file *the_output = 0;
+
+output_file::output_file()
+{
+}
+
+output_file::~output_file()
+{
+}
+
+void output_file::trailer(vunits)
+{
+}
+
+real_output_file::real_output_file()
+: printing(0)
+{
+ if (pipe_command) {
+ if ((fp = popen(pipe_command, "w")) != 0) {
+ piped = 1;
+ return;
+ }
+ error("pipe open failed: %1", strerror(errno));
+ }
+ piped = 0;
+ fp = stdout;
+}
+
+real_output_file::~real_output_file()
+{
+ if (!fp)
+ return;
+ // To avoid looping, set fp to 0 before calling fatal().
+ if (ferror(fp) || fflush(fp) < 0) {
+ fp = 0;
+ fatal("error writing output file");
+ }
+ if (piped) {
+ int result = pclose(fp);
+ fp = 0;
+ if (result < 0)
+ fatal("pclose failed");
+ if ((result & 0x7f) != 0)
+ error("output process `%1' got fatal signal %2",
+ pipe_command, result & 0x7f);
+ else {
+ int exit_status = (result >> 8) & 0xff;
+ if (exit_status != 0)
+ error("output process `%1' exited with status %2",
+ pipe_command, exit_status);
+ }
+ }
+ else if (fclose(fp) < 0) {
+ fp = 0;
+ fatal("error closing output file");
+ }
+}
+
+void real_output_file::flush()
+{
+ if (fflush(fp) < 0)
+ fatal("error writing output file");
+}
+
+int real_output_file::is_printing()
+{
+ return printing;
+}
+
+void real_output_file::begin_page(int pageno, vunits page_length)
+{
+ printing = in_output_page_list(pageno);
+ if (printing)
+ really_begin_page(pageno, page_length);
+}
+
+void real_output_file::copy_file(hunits x, vunits y, const char *filename)
+{
+ if (printing)
+ really_copy_file(x, y, filename);
+}
+
+void real_output_file::transparent_char(unsigned char c)
+{
+ if (printing)
+ really_transparent_char(c);
+}
+
+void real_output_file::print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after)
+{
+ if (printing)
+ really_print_line(x, y, n, before, after);
+ delete_node_list(n);
+}
+
+void real_output_file::really_copy_file(hunits, vunits, const char *)
+{
+ // do nothing
+}
+
+
+/* ascii_output_file */
+
+void ascii_output_file::really_transparent_char(unsigned char c)
+{
+ putc(c, fp);
+}
+
+void ascii_output_file::really_print_line(hunits, vunits, node *n, vunits, vunits)
+{
+ while (n != 0) {
+ n->ascii_print(this);
+ n = n->next;
+ }
+ fputc('\n', fp);
+}
+
+void ascii_output_file::really_begin_page(int /*pageno*/, vunits /*page_length*/)
+{
+ fputs("<beginning of page>\n", fp);
+}
+
+ascii_output_file::ascii_output_file()
+{
+}
+
+/* suppress_output_file */
+
+suppress_output_file::suppress_output_file()
+{
+}
+
+void suppress_output_file::really_print_line(hunits, vunits, node *, vunits, vunits)
+{
+}
+
+void suppress_output_file::really_begin_page(int, vunits)
+{
+}
+
+void suppress_output_file::really_transparent_char(unsigned char)
+{
+}
+
+/* glyphs, ligatures, kerns, discretionary breaks */
+
+class glyph_node : public node {
+ static glyph_node *free_list;
+protected:
+ charinfo *ci;
+ tfont *tf;
+#ifdef STORE_WIDTH
+ hunits wid;
+ glyph_node(charinfo *, tfont *, hunits, node * = 0);
+#endif
+public:
+ void *operator new(size_t);
+ void operator delete(void *);
+ glyph_node(charinfo *, tfont *, node * = 0);
+ ~glyph_node() {}
+ node *copy();
+ node *merge_glyph_node(glyph_node *);
+ node *merge_self(node *);
+ hunits width();
+ node *last_char_node();
+ units size();
+ void vertical_extent(vunits *, vunits *);
+ hunits subscript_correction();
+ hunits italic_correction();
+ hunits left_italic_correction();
+ hunits skew();
+ hyphenation_type get_hyphenation_type();
+ tfont *get_tfont();
+ void tprint(troff_output_file *);
+ void zero_width_tprint(troff_output_file *);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ node *add_self(node *, hyphen_list **);
+ int ends_sentence();
+ int overlaps_vertically();
+ int overlaps_horizontally();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int character_type();
+ int same(node *);
+ const char *type();
+};
+
+glyph_node *glyph_node::free_list = 0;
+
+class ligature_node : public glyph_node {
+ node *n1;
+ node *n2;
+#ifdef STORE_WIDTH
+ ligature_node(charinfo *, tfont *, hunits, node *gn1, node *gn2, node *x = 0);
+#endif
+public:
+ void *operator new(size_t);
+ void operator delete(void *);
+ ligature_node(charinfo *, tfont *, node *gn1, node *gn2, node *x = 0);
+ ~ligature_node();
+ node *copy();
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+};
+
+class kern_pair_node : public node {
+ hunits amount;
+ node *n1;
+ node *n2;
+public:
+ kern_pair_node(hunits n, node *first, node *second, node *x = 0);
+ ~kern_pair_node();
+ node *copy();
+ node *merge_glyph_node(glyph_node *);
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ node *add_discretionary_hyphen();
+ hunits width();
+ node *last_char_node();
+ hunits italic_correction();
+ hunits subscript_correction();
+ void tprint(troff_output_file *);
+ hyphenation_type get_hyphenation_type();
+ int ends_sentence();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+};
+
+class dbreak_node : public node {
+ node *none;
+ node *pre;
+ node *post;
+public:
+ dbreak_node(node *n, node *p, node *x = 0);
+ ~dbreak_node();
+ node *copy();
+ node *merge_glyph_node(glyph_node *);
+ node *add_discretionary_hyphen();
+ hunits width();
+ node *last_char_node();
+ hunits italic_correction();
+ hunits subscript_correction();
+ void tprint(troff_output_file *);
+ breakpoint *get_breakpoints(hunits width, int ns, breakpoint *rest = 0,
+ int is_inner = 0);
+ int nbreaks();
+ int ends_sentence();
+ void split(int, node **, node **);
+ hyphenation_type get_hyphenation_type();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+};
+
+void *glyph_node::operator new(size_t n)
+{
+ assert(n == sizeof(glyph_node));
+ if (!free_list) {
+ const int BLOCK = 1024;
+ free_list = (glyph_node *)new char[sizeof(glyph_node)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ glyph_node *p = free_list;
+ free_list = (glyph_node *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+void *ligature_node::operator new(size_t n)
+{
+ return new char[n];
+}
+
+void glyph_node::operator delete(void *p)
+{
+ if (p) {
+ ((glyph_node *)p)->next = free_list;
+ free_list = (glyph_node *)p;
+ }
+}
+
+void ligature_node::operator delete(void *p)
+{
+ delete p;
+}
+
+glyph_node::glyph_node(charinfo *c, tfont *t, node *x)
+ : ci(c), tf(t), node(x)
+{
+#ifdef STORE_WIDTH
+ wid = tf->get_width(ci);
+#endif
+}
+
+#ifdef STORE_WIDTH
+glyph_node::glyph_node(charinfo *c, tfont *t, hunits w, node *x)
+ : ci(c), tf(t), wid(w), node(x)
+{
+}
+#endif
+
+node *glyph_node::copy()
+{
+#ifdef STORE_WIDTH
+ return new glyph_node(ci, tf, wid);
+#else
+ return new glyph_node(ci, tf);
+#endif
+}
+
+node *glyph_node::merge_self(node *nd)
+{
+ return nd->merge_glyph_node(this);
+}
+
+int glyph_node::character_type()
+{
+ return tf->get_character_type(ci);
+}
+
+node *glyph_node::add_self(node *n, hyphen_list **p)
+{
+ assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
+ next = 0;
+ node *nn;
+ if (n == 0 || (nn = n->merge_glyph_node(this)) == 0) {
+ next = n;
+ nn = this;
+ }
+ if ((*p)->hyphen)
+ nn = nn->add_discretionary_hyphen();
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return nn;
+}
+
+int glyph_node::overlaps_horizontally()
+{
+ return ci->overlaps_horizontally();
+}
+
+int glyph_node::overlaps_vertically()
+{
+ return ci->overlaps_vertically();
+}
+
+units glyph_node::size()
+{
+ return tf->get_size().to_units();
+}
+
+hyphen_list *glyph_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(ci->get_hyphenation_code(), tail);
+}
+
+
+tfont *node::get_tfont()
+{
+ return 0;
+}
+
+tfont *glyph_node::get_tfont()
+{
+ return tf;
+}
+
+node *node::merge_glyph_node(glyph_node * /*gn*/)
+{
+ return 0;
+}
+
+node *glyph_node::merge_glyph_node(glyph_node *gn)
+{
+ if (tf == gn->tf) {
+ charinfo *lig;
+ if ((lig = tf->get_lig(ci, gn->ci)) != 0) {
+ node *next1 = next;
+ next = 0;
+ return new ligature_node(lig, tf, this, gn, next1);
+ }
+ hunits kern;
+ if (tf->get_kern(ci, gn->ci, &kern)) {
+ node *next1 = next;
+ next = 0;
+ return new kern_pair_node(kern, this, gn, next1);
+ }
+ }
+ return 0;
+}
+
+#ifdef STORE_WIDTH
+inline
+#endif
+hunits glyph_node::width()
+{
+#ifdef STORE_WIDTH
+ return wid;
+#else
+ return tf->get_width(ci);
+#endif
+}
+
+node *glyph_node::last_char_node()
+{
+ return this;
+}
+
+void glyph_node::vertical_extent(vunits *min, vunits *max)
+{
+ *min = -tf->get_char_height(ci);
+ *max = tf->get_char_depth(ci);
+}
+
+hunits glyph_node::skew()
+{
+ return tf->get_char_skew(ci);
+}
+
+hunits glyph_node::subscript_correction()
+{
+ return tf->get_subscript_correction(ci);
+}
+
+hunits glyph_node::italic_correction()
+{
+ return tf->get_italic_correction(ci);
+}
+
+hunits glyph_node::left_italic_correction()
+{
+ return tf->get_left_italic_correction(ci);
+}
+
+hyphenation_type glyph_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+int glyph_node::ends_sentence()
+{
+ if (ci->ends_sentence())
+ return 1;
+ else if (ci->transparent())
+ return 2;
+ else
+ return 0;
+}
+
+void glyph_node::ascii_print(ascii_output_file *ascii)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0)
+ ascii->outc(c);
+ else
+ ascii->outs(ci->nm.contents());
+}
+
+ligature_node::ligature_node(charinfo *c, tfont *t,
+ node *gn1, node *gn2, node *x)
+ : glyph_node(c, t, x), n1(gn1), n2(gn2)
+{
+}
+
+#ifdef STORE_WIDTH
+ligature_node::ligature_node(charinfo *c, tfont *t, hunits w,
+ node *gn1, node *gn2, node *x)
+ : glyph_node(c, t, w, x), n1(gn1), n2(gn2)
+{
+}
+#endif
+
+ligature_node::~ligature_node()
+{
+ delete n1;
+ delete n2;
+}
+
+node *ligature_node::copy()
+{
+#ifdef STORE_WIDTH
+ return new ligature_node(ci, tf, wid, n1->copy(), n2->copy());
+#else
+ return new ligature_node(ci, tf, n1->copy(), n2->copy());
+#endif
+}
+
+void ligature_node::ascii_print(ascii_output_file *ascii)
+{
+ n1->ascii_print(ascii);
+ n2->ascii_print(ascii);
+}
+
+hyphen_list *ligature_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n1->get_hyphen_list(n2->get_hyphen_list(tail));
+}
+
+node *ligature_node::add_self(node *n, hyphen_list **p)
+{
+ n = n1->add_self(n, p);
+ n = n2->add_self(n, p);
+ n1 = n2 = 0;
+ delete this;
+ return n;
+}
+
+kern_pair_node::kern_pair_node(hunits n, node *first, node *second, node *x)
+ : node(x), n1(first), n2(second), amount(n)
+{
+}
+
+dbreak_node::dbreak_node(node *n, node *p, node *x)
+ : node(x), none(n), pre(p), post(0)
+{
+}
+
+node *dbreak_node::merge_glyph_node(glyph_node *gn)
+{
+ glyph_node *gn2 = (glyph_node *)gn->copy();
+ node *new_none = none ? none->merge_glyph_node(gn) : 0;
+ node *new_post = post ? post->merge_glyph_node(gn2) : 0;
+ if (new_none == 0 && new_post == 0) {
+ delete gn2;
+ return 0;
+ }
+ if (new_none != 0)
+ none = new_none;
+ else {
+ gn->next = none;
+ none = gn;
+ }
+ if (new_post != 0)
+ post = new_post;
+ else {
+ gn2->next = post;
+ post = gn2;
+ }
+ return this;
+}
+
+node *kern_pair_node::merge_glyph_node(glyph_node *gn)
+{
+ node *nd = n2->merge_glyph_node(gn);
+ if (nd == 0)
+ return 0;
+ n2 = nd;
+ nd = n2->merge_self(n1);
+ if (nd) {
+ nd->next = next;
+ n1 = 0;
+ n2 = 0;
+ delete this;
+ return nd;
+ }
+ return this;
+}
+
+
+hunits kern_pair_node::italic_correction()
+{
+ return n2->italic_correction();
+}
+
+hunits kern_pair_node::subscript_correction()
+{
+ return n2->subscript_correction();
+}
+
+node *kern_pair_node::add_discretionary_hyphen()
+{
+ tfont *tf = n2->get_tfont();
+ if (tf) {
+ if (tf->contains(soft_hyphen_char)) {
+ node *next1 = next;
+ next = 0;
+ node *n = copy();
+ glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
+ node *nn = n->merge_glyph_node(gn);
+ if (nn == 0) {
+ gn->next = n;
+ nn = gn;
+ }
+ return new dbreak_node(this, nn, next1);
+ }
+ }
+ return this;
+}
+
+
+kern_pair_node::~kern_pair_node()
+{
+ if (n1 != 0)
+ delete n1;
+ if (n2 != 0)
+ delete n2;
+}
+
+dbreak_node::~dbreak_node()
+{
+ delete_node_list(pre);
+ delete_node_list(post);
+ delete_node_list(none);
+}
+
+node *kern_pair_node::copy()
+{
+ return new kern_pair_node(amount, n1->copy(), n2->copy());
+}
+
+node *copy_node_list(node *n)
+{
+ node *p = 0;
+ while (n != 0) {
+ node *nn = n->copy();
+ nn->next = p;
+ p = nn;
+ n = n->next;
+ }
+ while (p != 0) {
+ node *pp = p->next;
+ p->next = n;
+ n = p;
+ p = pp;
+ }
+ return n;
+}
+
+void delete_node_list(node *n)
+{
+ while (n != 0) {
+ node *tem = n;
+ n = n->next;
+ delete tem;
+ }
+}
+
+node *dbreak_node::copy()
+{
+ dbreak_node *p = new dbreak_node(copy_node_list(none), copy_node_list(pre));
+ p->post = copy_node_list(post);
+ return p;
+}
+
+hyphen_list *node::get_hyphen_list(hyphen_list *tail)
+{
+ return tail;
+}
+
+
+hyphen_list *kern_pair_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n1->get_hyphen_list(n2->get_hyphen_list(tail));
+}
+
+class hyphen_inhibitor_node : public node {
+public:
+ hyphen_inhibitor_node(node *nd = 0);
+ node *copy();
+ int same(node *);
+ const char *type();
+ hyphenation_type get_hyphenation_type();
+};
+
+hyphen_inhibitor_node::hyphen_inhibitor_node(node *nd) : node(nd)
+{
+}
+
+node *hyphen_inhibitor_node::copy()
+{
+ return new hyphen_inhibitor_node;
+}
+
+int hyphen_inhibitor_node::same(node *)
+{
+ return 1;
+}
+
+const char *hyphen_inhibitor_node::type()
+{
+ return "hyphen_inhibitor_node";
+}
+
+hyphenation_type hyphen_inhibitor_node::get_hyphenation_type()
+{
+ return HYPHEN_INHIBIT;
+}
+
+/* add_discretionary_hyphen methods */
+
+node *dbreak_node::add_discretionary_hyphen()
+{
+ if (post)
+ post = post->add_discretionary_hyphen();
+ if (none)
+ none = none->add_discretionary_hyphen();
+ return this;
+}
+
+
+node *node::add_discretionary_hyphen()
+{
+ tfont *tf = get_tfont();
+ if (!tf)
+ return new hyphen_inhibitor_node(this);
+ if (tf->contains(soft_hyphen_char)) {
+ node *next1 = next;
+ next = 0;
+ node *n = copy();
+ glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
+ node *n1 = n->merge_glyph_node(gn);
+ if (n1 == 0) {
+ gn->next = n;
+ n1 = gn;
+ }
+ return new dbreak_node(this, n1, next1);
+ }
+ return this;
+}
+
+
+node *node::merge_self(node *)
+{
+ return 0;
+}
+
+node *node::add_self(node *n, hyphen_list ** /*p*/)
+{
+ next = n;
+ return this;
+}
+
+node *kern_pair_node::add_self(node *n, hyphen_list **p)
+{
+ n = n1->add_self(n, p);
+ n = n2->add_self(n, p);
+ n1 = n2 = 0;
+ delete this;
+ return n;
+}
+
+
+hunits node::width()
+{
+ return H0;
+}
+
+node *node::last_char_node()
+{
+ return 0;
+}
+
+hunits hmotion_node::width()
+{
+ return n;
+}
+
+units node::size()
+{
+ return points_to_units(10);
+}
+
+hunits kern_pair_node::width()
+{
+ return n1->width() + n2->width() + amount;
+}
+
+node *kern_pair_node::last_char_node()
+{
+ node *nd = n2->last_char_node();
+ if (nd)
+ return nd;
+ return n1->last_char_node();
+}
+
+hunits dbreak_node::width()
+{
+ hunits x = H0;
+ for (node *n = none; n != 0; n = n->next)
+ x += n->width();
+ return x;
+}
+
+node *dbreak_node::last_char_node()
+{
+ for (node *n = none; n; n = n->next) {
+ node *last = n->last_char_node();
+ if (last)
+ return last;
+ }
+ return 0;
+}
+
+hunits dbreak_node::italic_correction()
+{
+ return none ? none->italic_correction() : H0;
+}
+
+hunits dbreak_node::subscript_correction()
+{
+ return none ? none->subscript_correction() : H0;
+}
+
+class italic_corrected_node : public node {
+ node *n;
+ hunits x;
+public:
+ italic_corrected_node(node *, hunits, node * = 0);
+ ~italic_corrected_node();
+ node *copy();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *m);
+ hunits width();
+ node *last_char_node();
+ void vertical_extent(vunits *, vunits *);
+ int ends_sentence();
+ int overlaps_horizontally();
+ int overlaps_vertically();
+ int same(node *);
+ hyphenation_type get_hyphenation_type();
+ tfont *get_tfont();
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ int character_type();
+ void tprint(troff_output_file *);
+ hunits subscript_correction();
+ hunits skew();
+ node *add_self(node *, hyphen_list **);
+ const char *type();
+};
+
+node *node::add_italic_correction(hunits *width)
+{
+ hunits ic = italic_correction();
+ if (ic.is_zero())
+ return this;
+ else {
+ node *next1 = next;
+ next = 0;
+ *width += ic;
+ return new italic_corrected_node(this, ic, next1);
+ }
+}
+
+italic_corrected_node::italic_corrected_node(node *nn, hunits xx, node *p)
+: n(nn), x(xx), node(p)
+{
+ assert(n != 0);
+}
+
+italic_corrected_node::~italic_corrected_node()
+{
+ delete n;
+}
+
+node *italic_corrected_node::copy()
+{
+ return new italic_corrected_node(n->copy(), x);
+}
+
+hunits italic_corrected_node::width()
+{
+ return n->width() + x;
+}
+
+void italic_corrected_node::vertical_extent(vunits *min, vunits *max)
+{
+ n->vertical_extent(min, max);
+}
+
+void italic_corrected_node::tprint(troff_output_file *out)
+{
+ n->tprint(out);
+ out->right(x);
+}
+
+hunits italic_corrected_node::skew()
+{
+ return n->skew() - x/2;
+}
+
+hunits italic_corrected_node::subscript_correction()
+{
+ return n->subscript_correction() - x;
+}
+
+void italic_corrected_node::ascii_print(ascii_output_file *out)
+{
+ n->ascii_print(out);
+}
+
+int italic_corrected_node::ends_sentence()
+{
+ return n->ends_sentence();
+}
+
+int italic_corrected_node::overlaps_horizontally()
+{
+ return n->overlaps_horizontally();
+}
+
+int italic_corrected_node::overlaps_vertically()
+{
+ return n->overlaps_vertically();
+}
+
+node *italic_corrected_node::last_char_node()
+{
+ return n->last_char_node();
+}
+
+tfont *italic_corrected_node::get_tfont()
+{
+ return n->get_tfont();
+}
+
+hyphenation_type italic_corrected_node::get_hyphenation_type()
+{
+ return n->get_hyphenation_type();
+}
+
+node *italic_corrected_node::add_self(node *nd, hyphen_list **p)
+{
+ nd = n->add_self(nd, p);
+ hunits not_interested;
+ nd = nd->add_italic_correction(&not_interested);
+ n = 0;
+ delete this;
+ return nd;
+}
+
+hyphen_list *italic_corrected_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n->get_hyphen_list(tail);
+}
+
+int italic_corrected_node::character_type()
+{
+ return n->character_type();
+}
+
+class break_char_node : public node {
+ node *ch;
+ char break_code;
+public:
+ break_char_node(node *, int, node * = 0);
+ ~break_char_node();
+ node *copy();
+ hunits width();
+ vunits vertical_width();
+ node *last_char_node();
+ int character_type();
+ int ends_sentence();
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *s = 0);
+ void tprint(troff_output_file *);
+ void zero_width_tprint(troff_output_file *);
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *m);
+ hyphenation_type get_hyphenation_type();
+ int overlaps_vertically();
+ int overlaps_horizontally();
+ units size();
+ tfont *get_tfont();
+ int same(node *);
+ const char *type();
+};
+
+break_char_node::break_char_node(node *n, int c, node *x)
+: node(x), ch(n), break_code(c)
+{
+}
+
+break_char_node::~break_char_node()
+{
+ delete ch;
+}
+
+node *break_char_node::copy()
+{
+ return new break_char_node(ch->copy(), break_code);
+}
+
+hunits break_char_node::width()
+{
+ return ch->width();
+}
+
+vunits break_char_node::vertical_width()
+{
+ return ch->vertical_width();
+}
+
+node *break_char_node::last_char_node()
+{
+ return ch->last_char_node();
+}
+
+int break_char_node::character_type()
+{
+ return ch->character_type();
+}
+
+int break_char_node::ends_sentence()
+{
+ return ch->ends_sentence();
+}
+
+node *break_char_node::add_self(node *n, hyphen_list **p)
+{
+ assert((*p)->hyphenation_code == 0);
+ if ((*p)->breakable && (break_code & 1)) {
+ n = new space_node(H0, n);
+ n->freeze_space();
+ }
+ next = n;
+ n = this;
+ if ((*p)->breakable && (break_code & 2)) {
+ n = new space_node(H0, n);
+ n->freeze_space();
+ }
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return n;
+}
+
+hyphen_list *break_char_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(0, tail);
+}
+
+hyphenation_type break_char_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+void break_char_node::ascii_print(ascii_output_file *ascii)
+{
+ ch->ascii_print(ascii);
+}
+
+int break_char_node::overlaps_vertically()
+{
+ return ch->overlaps_vertically();
+}
+
+int break_char_node::overlaps_horizontally()
+{
+ return ch->overlaps_horizontally();
+}
+
+units break_char_node::size()
+{
+ return ch->size();
+}
+
+tfont *break_char_node::get_tfont()
+{
+ return ch->get_tfont();
+}
+
+node *extra_size_node::copy()
+{
+ return new extra_size_node(n);
+}
+
+node *vertical_size_node::copy()
+{
+ return new vertical_size_node(n);
+}
+
+node *hmotion_node::copy()
+{
+ return new hmotion_node(n);
+}
+
+node *space_char_hmotion_node::copy()
+{
+ return new space_char_hmotion_node(n);
+}
+
+node *vmotion_node::copy()
+{
+ return new vmotion_node(n);
+}
+
+node *dummy_node::copy()
+{
+ return new dummy_node;
+}
+
+node *transparent_dummy_node::copy()
+{
+ return new transparent_dummy_node;
+}
+
+hline_node::~hline_node()
+{
+ if (n)
+ delete n;
+}
+
+node *hline_node::copy()
+{
+ return new hline_node(x, n ? n->copy() : 0);
+}
+
+hunits hline_node::width()
+{
+ return x < H0 ? H0 : x;
+}
+
+
+vline_node::~vline_node()
+{
+ if (n)
+ delete n;
+}
+
+node *vline_node::copy()
+{
+ return new vline_node(x, n ? n->copy() : 0);
+}
+
+hunits vline_node::width()
+{
+ return n == 0 ? H0 : n->width();
+}
+
+
+zero_width_node::zero_width_node(node *nd) : n(nd)
+{
+}
+
+zero_width_node::~zero_width_node()
+{
+ delete_node_list(n);
+}
+
+node *zero_width_node::copy()
+{
+ return new zero_width_node(copy_node_list(n));
+}
+
+int node_list_character_type(node *p)
+{
+ int t = 0;
+ for (; p; p = p->next)
+ t |= p->character_type();
+ return t;
+}
+
+int zero_width_node::character_type()
+{
+ return node_list_character_type(n);
+}
+
+void node_list_vertical_extent(node *p, vunits *min, vunits *max)
+{
+ *min = V0;
+ *max = V0;
+ vunits cur_vpos = V0;
+ vunits v1, v2;
+ for (; p; p = p->next) {
+ p->vertical_extent(&v1, &v2);
+ v1 += cur_vpos;
+ if (v1 < *min)
+ *min = v1;
+ v2 += cur_vpos;
+ if (v2 > *max)
+ *max = v2;
+ cur_vpos += p->vertical_width();
+ }
+}
+
+void zero_width_node::vertical_extent(vunits *min, vunits *max)
+{
+ node_list_vertical_extent(n, min, max);
+}
+
+overstrike_node::overstrike_node() : max_width(H0), list(0)
+{
+}
+
+overstrike_node::~overstrike_node()
+{
+ delete_node_list(list);
+}
+
+node *overstrike_node::copy()
+{
+ overstrike_node *on = new overstrike_node;
+ for (node *tem = list; tem; tem = tem->next)
+ on->overstrike(tem->copy());
+ return on;
+}
+
+void overstrike_node::overstrike(node *n)
+{
+ if (n == 0)
+ return;
+ hunits w = n->width();
+ if (w > max_width)
+ max_width = w;
+ for (node **p = &list; *p; p = &(*p)->next)
+ ;
+ n->next = 0;
+ *p = n;
+}
+
+hunits overstrike_node::width()
+{
+ return max_width;
+}
+
+bracket_node::bracket_node() : max_width(H0), list(0)
+{
+}
+
+bracket_node::~bracket_node()
+{
+ delete_node_list(list);
+}
+
+node *bracket_node::copy()
+{
+ bracket_node *on = new bracket_node;
+ for (node *tem = list; tem; tem = tem->next)
+ on->bracket(tem->copy());
+ return on;
+}
+
+
+void bracket_node::bracket(node *n)
+{
+ if (n == 0)
+ return;
+ hunits w = n->width();
+ if (w > max_width)
+ max_width = w;
+ n->next = list;
+ list = n;
+}
+
+hunits bracket_node::width()
+{
+ return max_width;
+}
+
+int node::nspaces()
+{
+ return 0;
+}
+
+int node::merge_space(hunits)
+{
+ return 0;
+}
+
+#if 0
+space_node *space_node::free_list = 0;
+
+void *space_node::operator new(size_t n)
+{
+ assert(n == sizeof(space_node));
+ if (!free_list) {
+ free_list = (space_node *)new char[sizeof(space_node)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ space_node *p = free_list;
+ free_list = (space_node *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+inline void space_node::operator delete(void *p)
+{
+ if (p) {
+ ((space_node *)p)->next = free_list;
+ free_list = (space_node *)p;
+ }
+}
+#endif
+
+space_node::space_node(hunits nn, node *p) : node(p), n(nn), set(0)
+{
+}
+
+space_node::space_node(hunits nn, int s, node *p) : node(p), n(nn), set(s)
+{
+}
+
+#if 0
+space_node::~space_node()
+{
+}
+#endif
+
+node *space_node::copy()
+{
+ return new space_node(n, set);
+}
+
+int space_node::nspaces()
+{
+ return set ? 0 : 1;
+}
+
+int space_node::merge_space(hunits h)
+{
+ n += h;
+ return 1;
+}
+
+hunits space_node::width()
+{
+ return n;
+}
+
+void node::spread_space(int*, hunits*)
+{
+}
+
+void space_node::spread_space(int *nspaces, hunits *desired_space)
+{
+ if (!set) {
+ assert(*nspaces > 0);
+ if (*nspaces == 1) {
+ n += *desired_space;
+ *desired_space = H0;
+ }
+ else {
+ hunits extra = *desired_space / *nspaces;
+ *desired_space -= extra;
+ n += extra;
+ }
+ *nspaces -= 1;
+ set = 1;
+ }
+}
+
+void node::freeze_space()
+{
+}
+
+void space_node::freeze_space()
+{
+ set = 1;
+}
+
+diverted_space_node::diverted_space_node(vunits d, node *p)
+: node(p), n(d)
+{
+}
+
+node *diverted_space_node::copy()
+{
+ return new diverted_space_node(n);
+}
+
+diverted_copy_file_node::diverted_copy_file_node(symbol s, node *p)
+: node(p), filename(s)
+{
+}
+
+node *diverted_copy_file_node::copy()
+{
+ return new diverted_copy_file_node(filename);
+}
+
+int node::ends_sentence()
+{
+ return 0;
+}
+
+int kern_pair_node::ends_sentence()
+{
+ switch (n2->ends_sentence()) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ break;
+ default:
+ assert(0);
+ }
+ return n1->ends_sentence();
+}
+
+int node_list_ends_sentence(node *n)
+{
+ for (; n != 0; n = n->next)
+ switch (n->ends_sentence()) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ break;
+ default:
+ assert(0);
+ }
+ return 2;
+}
+
+
+int dbreak_node::ends_sentence()
+{
+ return node_list_ends_sentence(none);
+}
+
+
+int node::overlaps_horizontally()
+{
+ return 0;
+}
+
+int node::overlaps_vertically()
+{
+ return 0;
+}
+
+int node::discardable()
+{
+ return 0;
+}
+
+int space_node::discardable()
+{
+ return set ? 0 : 1;
+}
+
+
+vunits node::vertical_width()
+{
+ return V0;
+}
+
+vunits vline_node::vertical_width()
+{
+ return x;
+}
+
+vunits vmotion_node::vertical_width()
+{
+ return n;
+}
+
+int node::character_type()
+{
+ return 0;
+}
+
+hunits node::subscript_correction()
+{
+ return H0;
+}
+
+hunits node::italic_correction()
+{
+ return H0;
+}
+
+hunits node::left_italic_correction()
+{
+ return H0;
+}
+
+hunits node::skew()
+{
+ return H0;
+}
+
+
+/* vertical_extent methods */
+
+void node::vertical_extent(vunits *min, vunits *max)
+{
+ vunits v = vertical_width();
+ if (v < V0) {
+ *min = v;
+ *max = V0;
+ }
+ else {
+ *max = v;
+ *min = V0;
+ }
+}
+
+void vline_node::vertical_extent(vunits *min, vunits *max)
+{
+ if (n == 0)
+ node::vertical_extent(min, max);
+ else {
+ vunits cmin, cmax;
+ n->vertical_extent(&cmin, &cmax);
+ vunits h = n->size();
+ if (x < V0) {
+ if (-x < h) {
+ *min = x;
+ *max = V0;
+ }
+ else {
+ // we print the first character and then move up, so
+ *max = cmax;
+ // we print the last character and then move up h
+ *min = cmin + h;
+ if (*min > V0)
+ *min = V0;
+ *min += x;
+ }
+ }
+ else {
+ if (x < h) {
+ *max = x;
+ *min = V0;
+ }
+ else {
+ // we move down by h and then print the first character, so
+ *min = cmin + h;
+ if (*min > V0)
+ *min = V0;
+ *max = x + cmax;
+ }
+ }
+ }
+}
+
+/* ascii_print methods */
+
+
+static void ascii_print_reverse_node_list(ascii_output_file *ascii, node *n)
+{
+ if (n == 0)
+ return;
+ ascii_print_reverse_node_list(ascii, n->next);
+ n->ascii_print(ascii);
+}
+
+void dbreak_node::ascii_print(ascii_output_file *ascii)
+{
+ ascii_print_reverse_node_list(ascii, none);
+}
+
+void kern_pair_node::ascii_print(ascii_output_file *ascii)
+{
+ n1->ascii_print(ascii);
+ n2->ascii_print(ascii);
+}
+
+
+void node::ascii_print(ascii_output_file *)
+{
+}
+
+void space_node::ascii_print(ascii_output_file *ascii)
+{
+ if (!n.is_zero())
+ ascii->outc(' ');
+}
+
+void hmotion_node::ascii_print(ascii_output_file *ascii)
+{
+ // this is pretty arbitrary
+ if (n >= points_to_units(2))
+ ascii->outc(' ');
+}
+
+void space_char_hmotion_node::ascii_print(ascii_output_file *ascii)
+{
+ ascii->outc(' ');
+}
+
+/* asciify methods */
+
+void node::asciify(macro *m)
+{
+ m->append(this);
+}
+
+void glyph_node::asciify(macro *m)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0) {
+ m->append(c);
+ delete this;
+ }
+ else
+ m->append(this);
+}
+
+void kern_pair_node::asciify(macro *m)
+{
+ n1->asciify(m);
+ n2->asciify(m);
+ n1 = n2 = 0;
+ delete this;
+}
+
+static void asciify_reverse_node_list(macro *m, node *n)
+{
+ if (n == 0)
+ return;
+ asciify_reverse_node_list(m, n->next);
+ n->asciify(m);
+}
+
+void dbreak_node::asciify(macro *m)
+{
+ asciify_reverse_node_list(m, none);
+ none = 0;
+ delete this;
+}
+
+void ligature_node::asciify(macro *m)
+{
+ n1->asciify(m);
+ n2->asciify(m);
+ n1 = n2 = 0;
+ delete this;
+}
+
+void break_char_node::asciify(macro *m)
+{
+ ch->asciify(m);
+ ch = 0;
+ delete this;
+}
+
+void italic_corrected_node::asciify(macro *m)
+{
+ n->asciify(m);
+ n = 0;
+ delete this;
+}
+
+void left_italic_corrected_node::asciify(macro *m)
+{
+ if (n) {
+ n->asciify(m);
+ n = 0;
+ }
+ delete this;
+}
+
+space_char_hmotion_node::space_char_hmotion_node(hunits i, node *next)
+: hmotion_node(i, next)
+{
+}
+
+void space_char_hmotion_node::asciify(macro *m)
+{
+ m->append(' ');
+ delete this;
+}
+
+void line_start_node::asciify(macro *)
+{
+ delete this;
+}
+
+void vertical_size_node::asciify(macro *)
+{
+ delete this;
+}
+
+breakpoint *node::get_breakpoints(hunits /*width*/, int /*nspaces*/,
+ breakpoint *rest, int /*is_inner*/)
+{
+ return rest;
+}
+
+int node::nbreaks()
+{
+ return 0;
+}
+
+breakpoint *space_node::get_breakpoints(hunits width, int ns, breakpoint *rest,
+ int is_inner)
+{
+ if (next->discardable())
+ return rest;
+ breakpoint *bp = new breakpoint;
+ bp->next = rest;
+ bp->width = width;
+ bp->nspaces = ns;
+ bp->hyphenated = 0;
+ if (is_inner) {
+ assert(rest != 0);
+ bp->index = rest->index + 1;
+ bp->nd = rest->nd;
+ }
+ else {
+ bp->nd = this;
+ bp->index = 0;
+ }
+ return bp;
+}
+
+int space_node::nbreaks()
+{
+ if (next->discardable())
+ return 0;
+ else
+ return 1;
+}
+
+static breakpoint *node_list_get_breakpoints(node *p, hunits *widthp,
+ int ns, breakpoint *rest)
+{
+ if (p != 0) {
+ rest = p->get_breakpoints(*widthp,
+ ns,
+ node_list_get_breakpoints(p->next, widthp, ns,
+ rest),
+ 1);
+ *widthp += p->width();
+ }
+ return rest;
+}
+
+
+breakpoint *dbreak_node::get_breakpoints(hunits width, int ns,
+ breakpoint *rest, int is_inner)
+{
+ breakpoint *bp = new breakpoint;
+ bp->next = rest;
+ bp->width = width;
+ for (node *tem = pre; tem != 0; tem = tem->next)
+ bp->width += tem->width();
+ bp->nspaces = ns;
+ bp->hyphenated = 1;
+ if (is_inner) {
+ assert(rest != 0);
+ bp->index = rest->index + 1;
+ bp->nd = rest->nd;
+ }
+ else {
+ bp->nd = this;
+ bp->index = 0;
+ }
+ return node_list_get_breakpoints(none, &width, ns, bp);
+}
+
+int dbreak_node::nbreaks()
+{
+ int i = 1;
+ for (node *tem = none; tem != 0; tem = tem->next)
+ i += tem->nbreaks();
+ return i;
+}
+
+void node::split(int /*where*/, node ** /*prep*/, node ** /*postp*/)
+{
+ assert(0);
+}
+
+void space_node::split(int where, node **pre, node **post)
+{
+ assert(where == 0);
+ *pre = next;
+ *post = 0;
+ delete this;
+}
+
+static void node_list_split(node *p, int *wherep, node **prep, node **postp)
+{
+ if (p == 0)
+ return;
+ int nb = p->nbreaks();
+ node_list_split(p->next, wherep, prep, postp);
+ if (*wherep < 0) {
+ p->next = *postp;
+ *postp = p;
+ }
+ else if (*wherep < nb) {
+ p->next = *prep;
+ p->split(*wherep, prep, postp);
+ }
+ else {
+ p->next = *prep;
+ *prep = p;
+ }
+ *wherep -= nb;
+}
+
+void dbreak_node::split(int where, node **prep, node **postp)
+{
+ assert(where >= 0);
+ if (where == 0) {
+ *postp = post;
+ post = 0;
+ if (pre == 0)
+ *prep = next;
+ else {
+ for (node *tem = pre; tem->next != 0; tem = tem->next)
+ ;
+ tem->next = next;
+ *prep = pre;
+ }
+ pre = 0;
+ delete this;
+ }
+ else {
+ *prep = next;
+ where -= 1;
+ node_list_split(none, &where, prep, postp);
+ none = 0;
+ delete this;
+ }
+}
+
+
+hyphenation_type node::get_hyphenation_type()
+{
+ return HYPHEN_BOUNDARY;
+}
+
+
+hyphenation_type dbreak_node::get_hyphenation_type()
+{
+ return HYPHEN_INHIBIT;
+}
+
+hyphenation_type kern_pair_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+hyphenation_type dummy_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+hyphenation_type transparent_dummy_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+int node::interpret(macro *)
+{
+ return 0;
+}
+
+special_node::special_node(const macro &m)
+: mac(m)
+{
+}
+
+int special_node::same(node *n)
+{
+ return mac == ((special_node *)n)->mac;
+}
+
+const char *special_node::type()
+{
+ return "special_node";
+}
+
+node *special_node::copy()
+{
+ return new special_node(mac);
+}
+
+void special_node::tprint_start(troff_output_file *out)
+{
+ out->start_special();
+}
+
+void special_node::tprint_char(troff_output_file *out, unsigned char c)
+{
+ out->special_char(c);
+}
+
+void special_node::tprint_end(troff_output_file *out)
+{
+ out->end_special();
+}
+
+/* composite_node */
+
+class composite_node : public node {
+ charinfo *ci;
+ node *n;
+ tfont *tf;
+public:
+ composite_node(node *, charinfo *, tfont *, node * = 0);
+ ~composite_node();
+ node *copy();
+ hunits width();
+ node *last_char_node();
+ units size();
+ void tprint(troff_output_file *);
+ hyphenation_type get_hyphenation_type();
+ int overlaps_horizontally();
+ int overlaps_vertically();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ hyphen_list *get_hyphen_list(hyphen_list *tail);
+ node *add_self(node *, hyphen_list **);
+ tfont *get_tfont();
+ int same(node *);
+ const char *type();
+ void vertical_extent(vunits *, vunits *);
+ vunits vertical_width();
+};
+
+composite_node::composite_node(node *p, charinfo *c, tfont *t, node *x)
+: node(x), n(p), ci(c), tf(t)
+{
+}
+
+composite_node::~composite_node()
+{
+ delete_node_list(n);
+}
+
+node *composite_node::copy()
+{
+ return new composite_node(copy_node_list(n), ci, tf);
+}
+
+hunits composite_node::width()
+{
+ hunits x;
+ if (tf->get_constant_space(&x))
+ return x;
+ x = H0;
+ for (node *tem = n; tem; tem = tem->next)
+ x += tem->width();
+ hunits offset;
+ if (tf->get_bold(&offset))
+ x += offset;
+ x += tf->get_track_kern();
+ return x;
+}
+
+node *composite_node::last_char_node()
+{
+ return this;
+}
+
+vunits composite_node::vertical_width()
+{
+ vunits v = V0;
+ for (node *tem = n; tem; tem = tem->next)
+ v += tem->vertical_width();
+ return v;
+}
+
+units composite_node::size()
+{
+ return tf->get_size().to_units();
+}
+
+hyphenation_type composite_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+int composite_node::overlaps_horizontally()
+{
+ return ci->overlaps_horizontally();
+}
+
+int composite_node::overlaps_vertically()
+{
+ return ci->overlaps_vertically();
+}
+
+void composite_node::asciify(macro *m)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0) {
+ m->append(c);
+ delete this;
+ }
+ else
+ m->append(this);
+}
+
+void composite_node::ascii_print(ascii_output_file *ascii)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0)
+ ascii->outc(c);
+ else
+ ascii->outs(ci->nm.contents());
+
+}
+
+hyphen_list *composite_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(ci->get_hyphenation_code(), tail);
+
+}
+
+node *composite_node::add_self(node *nn, hyphen_list **p)
+{
+ assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
+ next = nn;
+ nn = this;
+ if ((*p)->hyphen)
+ nn = nn->add_discretionary_hyphen();
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return nn;
+}
+
+tfont *composite_node::get_tfont()
+{
+ return tf;
+}
+
+node *reverse_node_list(node *n)
+{
+ node *r = 0;
+ while (n) {
+ node *tem = n;
+ n = n->next;
+ tem->next = r;
+ r = tem;
+ }
+ return r;
+}
+
+void composite_node::vertical_extent(vunits *min, vunits *max)
+{
+ n = reverse_node_list(n);
+ node_list_vertical_extent(n, min, max);
+ n = reverse_node_list(n);
+}
+
+word_space_node::word_space_node(hunits d, node *x) : space_node(d, x)
+{
+}
+
+word_space_node::word_space_node(hunits d, int s, node *x)
+: space_node(d, s, x)
+{
+}
+
+node *word_space_node::copy()
+{
+ return new word_space_node(n, set);
+}
+
+void word_space_node::tprint(troff_output_file *out)
+{
+ out->word_marker();
+ space_node::tprint(out);
+}
+
+unbreakable_space_node::unbreakable_space_node(hunits d, node *x)
+: word_space_node(d, x)
+{
+}
+
+unbreakable_space_node::unbreakable_space_node(hunits d, int s, node *x)
+: word_space_node(d, s, x)
+{
+}
+
+node *unbreakable_space_node::copy()
+{
+ return new unbreakable_space_node(n, set);
+}
+
+breakpoint *unbreakable_space_node::get_breakpoints(hunits, int,
+ breakpoint *rest, int)
+{
+ return rest;
+}
+
+int unbreakable_space_node::nbreaks()
+{
+ return 0;
+}
+
+void unbreakable_space_node::split(int, node **, node **)
+{
+ assert(0);
+}
+
+int unbreakable_space_node::merge_space(hunits)
+{
+ return 0;
+}
+
+hvpair::hvpair()
+{
+}
+
+draw_node::draw_node(char c, hvpair *p, int np, font_size s)
+ : code(c), npoints(np), sz(s)
+{
+ point = new hvpair[npoints];
+ for (int i = 0; i < npoints; i++)
+ point[i] = p[i];
+}
+
+int draw_node::same(node *n)
+{
+ draw_node *nd = (draw_node *)n;
+ if (code != nd->code || npoints != nd->npoints || sz != nd->sz)
+ return 0;
+ for (int i = 0; i < npoints; i++)
+ if (point[i].h != nd->point[i].h || point[i].v != nd->point[i].v)
+ return 0;
+ return 1;
+}
+
+const char *draw_node::type()
+{
+ return "draw_node";
+}
+
+draw_node::~draw_node()
+{
+ if (point)
+ a_delete point;
+}
+
+hunits draw_node::width()
+{
+ hunits x = H0;
+ for (int i = 0; i < npoints; i++)
+ x += point[i].h;
+ return x;
+}
+
+vunits draw_node::vertical_width()
+{
+ if (code == 'e')
+ return V0;
+ vunits x = V0;
+ for (int i = 0; i < npoints; i++)
+ x += point[i].v;
+ return x;
+}
+
+node *draw_node::copy()
+{
+ return new draw_node(code, point, npoints, sz);
+}
+
+void draw_node::tprint(troff_output_file *out)
+{
+ out->draw(code, point, npoints, sz);
+}
+
+/* tprint methods */
+
+void glyph_node::tprint(troff_output_file *out)
+{
+ tfont *ptf = tf->get_plain();
+ if (ptf == tf)
+ out->put_char_width(ci, ptf, width(), H0);
+ else {
+ hunits offset;
+ int bold = tf->get_bold(&offset);
+ hunits w = ptf->get_width(ci);
+ hunits k = H0;
+ hunits x;
+ int cs = tf->get_constant_space(&x);
+ if (cs) {
+ x -= w;
+ if (bold)
+ x -= offset;
+ hunits x2 = x/2;
+ out->right(x2);
+ k = x - x2;
+ }
+ else
+ k = tf->get_track_kern();
+ if (bold) {
+ out->put_char(ci, ptf);
+ out->right(offset);
+ }
+ out->put_char_width(ci, ptf, w, k);
+ }
+}
+
+void glyph_node::zero_width_tprint(troff_output_file *out)
+{
+ tfont *ptf = tf->get_plain();
+ hunits offset;
+ int bold = tf->get_bold(&offset);
+ hunits x;
+ int cs = tf->get_constant_space(&x);
+ if (cs) {
+ x -= ptf->get_width(ci);
+ if (bold)
+ x -= offset;
+ x = x/2;
+ out->right(x);
+ }
+ out->put_char(ci, ptf);
+ if (bold) {
+ out->right(offset);
+ out->put_char(ci, ptf);
+ out->right(-offset);
+ }
+ if (cs)
+ out->right(-x);
+}
+
+void break_char_node::tprint(troff_output_file *t)
+{
+ ch->tprint(t);
+}
+
+void break_char_node::zero_width_tprint(troff_output_file *t)
+{
+ ch->zero_width_tprint(t);
+}
+
+void hline_node::tprint(troff_output_file *out)
+{
+ if (x < H0) {
+ out->right(x);
+ x = -x;
+ }
+ if (n == 0) {
+ out->right(x);
+ return;
+ }
+ hunits w = n->width();
+ if (w <= H0) {
+ error("horizontal line drawing character must have positive width");
+ out->right(x);
+ return;
+ }
+ int i = int(x/w);
+ if (i == 0) {
+ hunits xx = x - w;
+ hunits xx2 = xx/2;
+ out->right(xx2);
+ n->tprint(out);
+ out->right(xx - xx2);
+ }
+ else {
+ hunits rem = x - w*i;
+ if (rem > H0)
+ if (n->overlaps_horizontally()) {
+ n->tprint(out);
+ out->right(rem - w);
+ }
+ else
+ out->right(rem);
+ while (--i >= 0)
+ n->tprint(out);
+ }
+}
+
+void vline_node::tprint(troff_output_file *out)
+{
+ if (n == 0) {
+ out->down(x);
+ return;
+ }
+ vunits h = n->size();
+ int overlaps = n->overlaps_vertically();
+ vunits y = x;
+ if (y < V0) {
+ y = -y;
+ int i = y / h;
+ vunits rem = y - i*h;
+ if (i == 0) {
+ out->right(n->width());
+ out->down(-rem);
+ }
+ else {
+ while (--i > 0) {
+ n->zero_width_tprint(out);
+ out->down(-h);
+ }
+ if (overlaps) {
+ n->zero_width_tprint(out);
+ out->down(-rem);
+ n->tprint(out);
+ out->down(-h);
+ }
+ else {
+ n->tprint(out);
+ out->down(-h - rem);
+ }
+ }
+ }
+ else {
+ int i = y / h;
+ vunits rem = y - i*h;
+ if (i == 0) {
+ out->down(rem);
+ out->right(n->width());
+ }
+ else {
+ out->down(h);
+ if (overlaps)
+ n->zero_width_tprint(out);
+ out->down(rem);
+ while (--i > 0) {
+ n->zero_width_tprint(out);
+ out->down(h);
+ }
+ n->tprint(out);
+ }
+ }
+}
+
+void zero_width_node::tprint(troff_output_file *out)
+{
+ if (!n)
+ return;
+ if (!n->next) {
+ n->zero_width_tprint(out);
+ return;
+ }
+ int hpos = out->get_hpos();
+ int vpos = out->get_vpos();
+ node *tem = n;
+ while (tem) {
+ tem->tprint(out);
+ tem = tem->next;
+ }
+ out->moveto(hpos, vpos);
+}
+
+void overstrike_node::tprint(troff_output_file *out)
+{
+ hunits pos = H0;
+ for (node *tem = list; tem; tem = tem->next) {
+ hunits x = (max_width - tem->width())/2;
+ out->right(x - pos);
+ pos = x;
+ tem->zero_width_tprint(out);
+ }
+ out->right(max_width - pos);
+}
+
+void bracket_node::tprint(troff_output_file *out)
+{
+ if (list == 0)
+ return;
+ int npieces = 0;
+ for (node *tem = list; tem; tem = tem->next)
+ ++npieces;
+ vunits h = list->size();
+ vunits totalh = h*npieces;
+ vunits y = (totalh - h)/2;
+ out->down(y);
+ for (tem = list; tem; tem = tem->next) {
+ tem->zero_width_tprint(out);
+ out->down(-h);
+ }
+ out->right(max_width);
+ out->down(totalh - y);
+}
+
+void node::tprint(troff_output_file *)
+{
+}
+
+void node::zero_width_tprint(troff_output_file *out)
+{
+ int hpos = out->get_hpos();
+ int vpos = out->get_vpos();
+ tprint(out);
+ out->moveto(hpos, vpos);
+}
+
+void space_node::tprint(troff_output_file *out)
+{
+ out->right(n);
+}
+
+void hmotion_node::tprint(troff_output_file *out)
+{
+ out->right(n);
+}
+
+void vmotion_node::tprint(troff_output_file *out)
+{
+ out->down(n);
+}
+
+void kern_pair_node::tprint(troff_output_file *out)
+{
+ n1->tprint(out);
+ out->right(amount);
+ n2->tprint(out);
+}
+
+static void tprint_reverse_node_list(troff_output_file *out, node *n)
+{
+ if (n == 0)
+ return;
+ tprint_reverse_node_list(out, n->next);
+ n->tprint(out);
+}
+
+void dbreak_node::tprint(troff_output_file *out)
+{
+ tprint_reverse_node_list(out, none);
+}
+
+void composite_node::tprint(troff_output_file *out)
+{
+ hunits bold_offset;
+ int is_bold = tf->get_bold(&bold_offset);
+ hunits track_kern = tf->get_track_kern();
+ hunits constant_space;
+ int is_constant_spaced = tf->get_constant_space(&constant_space);
+ hunits x = H0;
+ if (is_constant_spaced) {
+ x = constant_space;
+ for (node *tem = n; tem; tem = tem->next)
+ x -= tem->width();
+ if (is_bold)
+ x -= bold_offset;
+ hunits x2 = x/2;
+ out->right(x2);
+ x -= x2;
+ }
+ if (is_bold) {
+ int hpos = out->get_hpos();
+ int vpos = out->get_vpos();
+ tprint_reverse_node_list(out, n);
+ out->moveto(hpos, vpos);
+ out->right(bold_offset);
+ }
+ tprint_reverse_node_list(out, n);
+ if (is_constant_spaced)
+ out->right(x);
+ else
+ out->right(track_kern);
+}
+
+node *make_composite_node(charinfo *s, environment *env)
+{
+ int fontno = env_definite_font(env);
+ if (fontno < 0) {
+ error("no current font");
+ return 0;
+ }
+ assert(fontno < font_table_size && font_table[fontno] != 0);
+ node *n = charinfo_to_node_list(s, env);
+ font_size fs = env->get_font_size();
+ int char_height = env->get_char_height();
+ int char_slant = env->get_char_slant();
+ tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant,
+ fontno);
+ if (env->is_composite())
+ tf = tf->get_plain();
+ return new composite_node(n, s, tf);
+}
+
+node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0)
+{
+ int fontno = env_definite_font(env);
+ if (fontno < 0) {
+ error("no current font");
+ return 0;
+ }
+ assert(fontno < font_table_size && font_table[fontno] != 0);
+ int fn = fontno;
+ int found = font_table[fontno]->contains(s);
+ if (!found) {
+ if (s->numbered()) {
+ if (!no_error_message)
+ warning(WARN_CHAR, "can't find numbered character %1",
+ s->get_number());
+ return 0;
+ }
+ special_font_list *sf = font_table[fontno]->sf;
+ while (sf != 0 && !found) {
+ fn = sf->n;
+ if (font_table[fn])
+ found = font_table[fn]->contains(s);
+ sf = sf->next;
+ }
+ if (!found) {
+ sf = global_special_fonts;
+ while (sf != 0 && !found) {
+ fn = sf->n;
+ if (font_table[fn])
+ found = font_table[fn]->contains(s);
+ sf = sf->next;
+ }
+ }
+ if (!found
+#if 0
+ && global_special_fonts == 0 && font_table[fontno]->sf == 0
+#endif
+ ) {
+ for (fn = 0; fn < font_table_size; fn++)
+ if (font_table[fn]
+ && font_table[fn]->is_special()
+ && font_table[fn]->contains(s)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ if (!no_error_message && s->first_time_not_found()) {
+ unsigned char input_code = s->get_ascii_code();
+ if (input_code != 0) {
+ if (csgraph(input_code))
+ warning(WARN_CHAR, "can't find character `%1'", input_code);
+ else
+ warning(WARN_CHAR, "can't find character with input code %1",
+ int(input_code));
+ }
+ else
+ warning(WARN_CHAR, "can't find special character `%1'",
+ s->nm.contents());
+ }
+ return 0;
+ }
+ }
+ font_size fs = env->get_font_size();
+ int char_height = env->get_char_height();
+ int char_slant = env->get_char_slant();
+ tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn);
+ if (env->is_composite())
+ tf = tf->get_plain();
+ return new glyph_node(s, tf);
+}
+
+node *make_node(charinfo *ci, environment *env)
+{
+ switch (ci->get_special_translation()) {
+ case charinfo::TRANSLATE_SPACE:
+ return new space_char_hmotion_node(env->get_space_width());
+ case charinfo::TRANSLATE_DUMMY:
+ return new dummy_node;
+ case charinfo::TRANSLATE_HYPHEN_INDICATOR:
+ error("translation to \\% ignored in this context");
+ break;
+ }
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ macro *mac = ci->get_macro();
+ if (mac)
+ return make_composite_node(ci, env);
+ else
+ return make_glyph_node(ci, env);
+}
+
+int character_exists(charinfo *ci, environment *env)
+{
+ if (ci->get_special_translation() != charinfo::TRANSLATE_NONE)
+ return 1;
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ if (ci->get_macro())
+ return 1;
+ node *nd = make_glyph_node(ci, env, 1);
+ if (nd) {
+ delete nd;
+ return 1;
+ }
+ return 0;
+}
+
+node *node::add_char(charinfo *ci, environment *env, hunits *widthp)
+{
+ node *res;
+ switch (ci->get_special_translation()) {
+ case charinfo::TRANSLATE_SPACE:
+ res = new space_char_hmotion_node(env->get_space_width(), this);
+ *widthp += res->width();
+ return res;
+ case charinfo::TRANSLATE_DUMMY:
+ return new dummy_node(this);
+ case charinfo::TRANSLATE_HYPHEN_INDICATOR:
+ return add_discretionary_hyphen();
+ }
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ macro *mac = ci->get_macro();
+ if (mac) {
+ res = make_composite_node(ci, env);
+ if (res) {
+ res->next = this;
+ *widthp += res->width();
+ }
+ else
+ return this;
+ }
+ else {
+ node *gn = make_glyph_node(ci, env);
+ if (gn == 0)
+ return this;
+ else {
+ hunits old_width = width();
+ node *p = gn->merge_self(this);
+ if (p == 0) {
+ *widthp += gn->width();
+ gn->next = this;
+ res = gn;
+ }
+ else {
+ *widthp += p->width() - old_width;
+ res = p;
+ }
+ }
+ }
+ int break_code = 0;
+ if (ci->can_break_before())
+ break_code = 1;
+ if (ci->can_break_after())
+ break_code |= 2;
+ if (break_code) {
+ node *next1 = res->next;
+ res->next = 0;
+ res = new break_char_node(res, break_code, next1);
+ }
+ return res;
+}
+
+
+#ifdef __GNUG__
+inline
+#endif
+int same_node(node *n1, node *n2)
+{
+ if (n1 != 0) {
+ if (n2 != 0)
+ return n1->type() == n2->type() && n1->same(n2);
+ else
+ return 0;
+ }
+ else
+ return n2 == 0;
+}
+
+int same_node_list(node *n1, node *n2)
+{
+ while (n1 && n2) {
+ if (n1->type() != n2->type() || !n1->same(n2))
+ return 0;
+ n1 = n1->next;
+ n2 = n2->next;
+ }
+ return !n1 && !n2;
+}
+
+int extra_size_node::same(node *nd)
+{
+ return n == ((extra_size_node *)nd)->n;
+}
+
+const char *extra_size_node::type()
+{
+ return "extra_size_node";
+}
+
+int vertical_size_node::same(node *nd)
+{
+ return n == ((vertical_size_node *)nd)->n;
+}
+
+const char *vertical_size_node::type()
+{
+ return "vertical_size_node";
+}
+
+int hmotion_node::same(node *nd)
+{
+ return n == ((hmotion_node *)nd)->n;
+}
+
+const char *hmotion_node::type()
+{
+ return "hmotion_node";
+}
+
+int space_char_hmotion_node::same(node *nd)
+{
+ return n == ((space_char_hmotion_node *)nd)->n;
+}
+
+const char *space_char_hmotion_node::type()
+{
+ return "space_char_hmotion_node";
+}
+
+int vmotion_node::same(node *nd)
+{
+ return n == ((vmotion_node *)nd)->n;
+}
+
+const char *vmotion_node::type()
+{
+ return "vmotion_node";
+}
+
+int hline_node::same(node *nd)
+{
+ return x == ((hline_node *)nd)->x && same_node(n, ((hline_node *)nd)->n);
+}
+
+const char *hline_node::type()
+{
+ return "hline_node";
+}
+
+int vline_node::same(node *nd)
+{
+ return x == ((vline_node *)nd)->x && same_node(n, ((vline_node *)nd)->n);
+}
+
+const char *vline_node::type()
+{
+ return "vline_node";
+}
+
+int dummy_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *dummy_node::type()
+{
+ return "dummy_node";
+}
+
+int transparent_dummy_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *transparent_dummy_node::type()
+{
+ return "transparent_dummy_node";
+}
+
+int transparent_dummy_node::ends_sentence()
+{
+ return 2;
+}
+
+int zero_width_node::same(node *nd)
+{
+ return same_node_list(n, ((zero_width_node *)nd)->n);
+}
+
+const char *zero_width_node::type()
+{
+ return "zero_width_node";
+}
+
+int italic_corrected_node::same(node *nd)
+{
+ return (x == ((italic_corrected_node *)nd)->x
+ && same_node(n, ((italic_corrected_node *)nd)->n));
+}
+
+const char *italic_corrected_node::type()
+{
+ return "italic_corrected_node";
+}
+
+
+left_italic_corrected_node::left_italic_corrected_node(node *x)
+: n(0), node(x)
+{
+}
+
+left_italic_corrected_node::~left_italic_corrected_node()
+{
+ delete n;
+}
+
+node *left_italic_corrected_node::merge_glyph_node(glyph_node *gn)
+{
+ if (n == 0) {
+ hunits lic = gn->left_italic_correction();
+ if (!lic.is_zero()) {
+ x = lic;
+ n = gn;
+ return this;
+ }
+ }
+ else {
+ node *nd = n->merge_glyph_node(gn);
+ if (nd) {
+ n = nd;
+ x = n->left_italic_correction();
+ return this;
+ }
+ }
+ return 0;
+}
+
+node *left_italic_corrected_node::copy()
+{
+ left_italic_corrected_node *nd = new left_italic_corrected_node;
+ if (n) {
+ nd->n = n->copy();
+ nd->x = x;
+ }
+ return nd;
+}
+
+void left_italic_corrected_node::tprint(troff_output_file *out)
+{
+ if (n) {
+ out->right(x);
+ n->tprint(out);
+ }
+}
+
+const char *left_italic_corrected_node::type()
+{
+ return "left_italic_corrected_node";
+}
+
+int left_italic_corrected_node::same(node *nd)
+{
+ return (x == ((left_italic_corrected_node *)nd)->x
+ && same_node(n, ((left_italic_corrected_node *)nd)->n));
+}
+
+void left_italic_corrected_node::ascii_print(ascii_output_file *out)
+{
+ if (n)
+ n->ascii_print(out);
+}
+
+hunits left_italic_corrected_node::width()
+{
+ return n ? n->width() + x : H0;
+}
+
+void left_italic_corrected_node::vertical_extent(vunits *min, vunits *max)
+{
+ if (n)
+ n->vertical_extent(min, max);
+ else
+ node::vertical_extent(min, max);
+}
+
+hunits left_italic_corrected_node::skew()
+{
+ return n ? n->skew() + x/2 : H0;
+}
+
+hunits left_italic_corrected_node::subscript_correction()
+{
+ return n ? n->subscript_correction() : H0;
+}
+
+hunits left_italic_corrected_node::italic_correction()
+{
+ return n ? n->italic_correction() : H0;
+}
+
+int left_italic_corrected_node::ends_sentence()
+{
+ return n ? n->ends_sentence() : 0;
+}
+
+int left_italic_corrected_node::overlaps_horizontally()
+{
+ return n ? n->overlaps_horizontally() : 0;
+}
+
+int left_italic_corrected_node::overlaps_vertically()
+{
+ return n ? n->overlaps_vertically() : 0;
+}
+
+node *left_italic_corrected_node::last_char_node()
+{
+ return n ? n->last_char_node() : 0;
+}
+
+tfont *left_italic_corrected_node::get_tfont()
+{
+ return n ? n->get_tfont() : 0;
+}
+
+hyphenation_type left_italic_corrected_node::get_hyphenation_type()
+{
+ if (n)
+ return n->get_hyphenation_type();
+ else
+ return HYPHEN_MIDDLE;
+}
+
+hyphen_list *left_italic_corrected_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n ? n->get_hyphen_list(tail) : tail;
+}
+
+node *left_italic_corrected_node::add_self(node *nd, hyphen_list **p)
+{
+ if (n) {
+ nd = new left_italic_corrected_node(nd);
+ nd = n->add_self(nd, p);
+ n = 0;
+ delete this;
+ }
+ return nd;
+}
+
+int left_italic_corrected_node::character_type()
+{
+ return n ? n->character_type() : 0;
+}
+
+int overstrike_node::same(node *nd)
+{
+ return same_node_list(list, ((overstrike_node *)nd)->list);
+}
+
+const char *overstrike_node::type()
+{
+ return "overstrike_node";
+}
+
+int bracket_node::same(node *nd)
+{
+ return same_node_list(list, ((bracket_node *)nd)->list);
+}
+
+const char *bracket_node::type()
+{
+ return "bracket_node";
+}
+
+int composite_node::same(node *nd)
+{
+ return ci == ((composite_node *)nd)->ci
+ && same_node_list(n, ((composite_node *)nd)->n);
+}
+
+const char *composite_node::type()
+{
+ return "composite_node";
+}
+
+int glyph_node::same(node *nd)
+{
+ return ci == ((glyph_node *)nd)->ci && tf == ((glyph_node *)nd)->tf;
+}
+
+const char *glyph_node::type()
+{
+ return "glyph_node";
+}
+
+int ligature_node::same(node *nd)
+{
+ return (same_node(n1, ((ligature_node *)nd)->n1)
+ && same_node(n2, ((ligature_node *)nd)->n2)
+ && glyph_node::same(nd));
+}
+
+const char *ligature_node::type()
+{
+ return "ligature_node";
+}
+
+int kern_pair_node::same(node *nd)
+{
+ return (amount == ((kern_pair_node *)nd)->amount
+ && same_node(n1, ((kern_pair_node *)nd)->n1)
+ && same_node(n2, ((kern_pair_node *)nd)->n2));
+}
+
+const char *kern_pair_node::type()
+{
+ return "kern_pair_node";
+}
+
+int dbreak_node::same(node *nd)
+{
+ return (same_node_list(none, ((dbreak_node *)nd)->none)
+ && same_node_list(pre, ((dbreak_node *)nd)->pre)
+ && same_node_list(post, ((dbreak_node *)nd)->post));
+}
+
+const char *dbreak_node::type()
+{
+ return "dbreak_node";
+}
+
+int break_char_node::same(node *nd)
+{
+ return (break_code == ((break_char_node *)nd)->break_code
+ && same_node(ch, ((break_char_node *)nd)->ch));
+}
+
+const char *break_char_node::type()
+{
+ return "break_char_node";
+}
+
+int line_start_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *line_start_node::type()
+{
+ return "line_start_node";
+}
+
+int space_node::same(node *nd)
+{
+ return n == ((space_node *)nd)->n && set == ((space_node *)nd)->set;
+}
+
+const char *space_node::type()
+{
+ return "space_node";
+}
+
+int word_space_node::same(node *nd)
+{
+ return (n == ((word_space_node *)nd)->n
+ && set == ((word_space_node *)nd)->set);
+}
+
+const char *word_space_node::type()
+{
+ return "word_space_node";
+}
+
+int unbreakable_space_node::same(node *nd)
+{
+ return (n == ((unbreakable_space_node *)nd)->n
+ && set == ((unbreakable_space_node *)nd)->set);
+}
+
+const char *unbreakable_space_node::type()
+{
+ return "unbreakable_space_node";
+}
+
+int diverted_space_node::same(node *nd)
+{
+ return n == ((diverted_space_node *)nd)->n;
+}
+
+const char *diverted_space_node::type()
+{
+ return "diverted_space_node";
+}
+
+int diverted_copy_file_node::same(node *nd)
+{
+ return filename == ((diverted_copy_file_node *)nd)->filename;
+}
+
+const char *diverted_copy_file_node::type()
+{
+ return "diverted_copy_file_node";
+}
+
+// Grow the font_table so that its size is > n.
+
+static void grow_font_table(int n)
+{
+ assert(n >= font_table_size);
+ font_info **old_font_table = font_table;
+ int old_font_table_size = font_table_size;
+ font_table_size = font_table_size ? (font_table_size*3)/2 : 10;
+ if (font_table_size <= n)
+ font_table_size = n + 10;
+ font_table = new font_info *[font_table_size];
+ if (old_font_table_size)
+ memcpy(font_table, old_font_table,
+ old_font_table_size*sizeof(font_info *));
+ a_delete old_font_table;
+ for (int i = old_font_table_size; i < font_table_size; i++)
+ font_table[i] = 0;
+}
+
+dictionary font_translation_dictionary(17);
+
+static symbol get_font_translation(symbol nm)
+{
+ void *p = font_translation_dictionary.lookup(nm);
+ return p ? symbol((char *)p) : nm;
+}
+
+dictionary font_dictionary(50);
+
+static int mount_font_no_translate(int n, symbol name, symbol external_name)
+{
+ assert(n >= 0);
+ // We store the address of this char in font_dictionary to indicate
+ // that we've previously tried to mount the font and failed.
+ static char a_char;
+ font *fm = 0;
+ void *p = font_dictionary.lookup(external_name);
+ if (p == 0) {
+ int not_found;
+ fm = font::load_font(external_name.contents(), &not_found);
+ if (!fm) {
+ if (not_found)
+ warning(WARN_FONT, "can't find font `%1'", external_name.contents());
+ font_dictionary.lookup(external_name, &a_char);
+ return 0;
+ }
+ font_dictionary.lookup(name, fm);
+ }
+ else if (p == &a_char) {
+#if 0
+ error("invalid font `%1'", external_name.contents());
+#endif
+ return 0;
+ }
+ else
+ fm = (font*)p;
+ if (n >= font_table_size) {
+ if (n - font_table_size > 1000) {
+ error("font position too much larger than first unused position");
+ return 0;
+ }
+ grow_font_table(n);
+ }
+ else if (font_table[n] != 0)
+ delete font_table[n];
+ font_table[n] = new font_info(name, n, external_name, fm);
+ invalidate_fontno(n);
+ return 1;
+}
+
+int mount_font(int n, symbol name, symbol external_name)
+{
+ assert(n >= 0);
+ name = get_font_translation(name);
+ if (external_name.is_null())
+ external_name = name;
+ else
+ external_name = get_font_translation(external_name);
+ return mount_font_no_translate(n, name, external_name);
+}
+
+void mount_style(int n, symbol name)
+{
+ assert(n >= 0);
+ if (n >= font_table_size) {
+ if (n - font_table_size > 1000) {
+ error("font position too much larger than first unused position");
+ return;
+ }
+ grow_font_table(n);
+ }
+ else if (font_table[n] != 0)
+ delete font_table[n];
+ font_table[n] = new font_info(get_font_translation(name), n, NULL_SYMBOL, 0);
+ invalidate_fontno(n);
+}
+
+/* global functions */
+
+void font_translate()
+{
+ symbol from = get_name(1);
+ if (!from.is_null()) {
+ symbol to = get_name();
+ if (to.is_null() || from == to)
+ font_translation_dictionary.remove(from);
+ else
+ font_translation_dictionary.lookup(from, (void *)to.contents());
+ }
+ skip_line();
+}
+
+void font_position()
+{
+ int n;
+ if (get_integer(&n)) {
+ if (n < 0)
+ error("negative font position");
+ else {
+ symbol internal_name = get_name(1);
+ if (!internal_name.is_null()) {
+ symbol external_name = get_long_name(0);
+ mount_font(n, internal_name, external_name); // ignore error
+ }
+ }
+ }
+ skip_line();
+}
+
+font_family::font_family(symbol s)
+: nm(s), map_size(10)
+{
+ map = new int[map_size];
+ for (int i = 0; i < map_size; i++)
+ map[i] = -1;
+}
+
+font_family::~font_family()
+{
+ a_delete map;
+}
+
+int font_family::make_definite(int i)
+{
+ if (i >= 0) {
+ if (i < map_size && map[i] >= 0)
+ return map[i];
+ else {
+ if (i < font_table_size && font_table[i] != 0) {
+ if (i >= map_size) {
+ int old_map_size = map_size;
+ int *old_map = map;
+ map_size *= 3;
+ map_size /= 2;
+ if (i >= map_size)
+ map_size = i + 10;
+ map = new int[map_size];
+ memcpy(map, old_map, old_map_size*sizeof(int));
+ a_delete old_map;
+ for (int j = old_map_size; j < map_size; j++)
+ map[j] = -1;
+ }
+ if (font_table[i]->is_style()) {
+ symbol sty = font_table[i]->get_name();
+ symbol f = concat(nm, sty);
+ int n;
+ // don't use symbol_fontno, because that might return a style
+ // and because we don't want to translate the name
+ for (n = 0; n < font_table_size; n++)
+ if (font_table[n] != 0 && font_table[n]->is_named(f)
+ && !font_table[n]->is_style())
+ break;
+ if (n >= font_table_size) {
+ n = next_available_font_position();
+ if (!mount_font_no_translate(n, f, f))
+ return -1;
+ }
+ return map[i] = n;
+ }
+ else
+ return map[i] = i;
+ }
+ else
+ return -1;
+ }
+ }
+ else
+ return -1;
+}
+
+dictionary family_dictionary(5);
+
+font_family *lookup_family(symbol nm)
+{
+ font_family *f = (font_family *)family_dictionary.lookup(nm);
+ if (!f) {
+ f = new font_family(nm);
+ (void)family_dictionary.lookup(nm, f);
+ }
+ return f;
+}
+
+static void invalidate_fontno(int n)
+{
+ assert(n >= 0 && n < font_table_size);
+ dictionary_iterator iter(family_dictionary);
+ symbol nm;
+ font_family *fam;
+ while (iter.get(&nm, (void **)&fam)) {
+ int map_size = fam->map_size;
+ if (n < map_size)
+ fam->map[n] = -1;
+ for (int i = 0; i < map_size; i++)
+ if (fam->map[i] == n)
+ fam->map[i] = -1;
+ }
+}
+
+void style()
+{
+ int n;
+ if (get_integer(&n)) {
+ if (n < 0)
+ error("negative font position");
+ else {
+ symbol internal_name = get_name(1);
+ if (!internal_name.is_null())
+ mount_style(n, internal_name);
+ }
+ }
+ skip_line();
+}
+
+static int get_fontno()
+{
+ int n;
+ tok.skip();
+ if (tok.delimiter()) {
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ n = symbol_fontno(s);
+ if (n < 0) {
+ n = next_available_font_position();
+ if (!mount_font(n, s))
+ return -1;
+ }
+ return curenv->get_family()->make_definite(n);
+ }
+ }
+ else if (get_integer(&n)) {
+ if (n < 0 || n >= font_table_size || font_table[n] == 0)
+ error("bad font number");
+ else
+ return curenv->get_family()->make_definite(n);
+ }
+ return -1;
+}
+
+static int underline_fontno = 2;
+
+void underline_font()
+{
+ int n = get_fontno();
+ if (n >= 0)
+ underline_fontno = n;
+ skip_line();
+}
+
+int get_underline_fontno()
+{
+ return underline_fontno;
+}
+
+static void read_special_fonts(special_font_list **sp)
+{
+ special_font_list *s = *sp;
+ *sp = 0;
+ while (s != 0) {
+ special_font_list *tem = s;
+ s = s->next;
+ delete tem;
+ }
+ special_font_list **p = sp;
+ while (has_arg()) {
+ int i = get_fontno();
+ if (i >= 0) {
+ special_font_list *tem = new special_font_list;
+ tem->n = i;
+ tem->next = 0;
+ *p = tem;
+ p = &(tem->next);
+ }
+ }
+}
+
+void font_special_request()
+{
+ int n = get_fontno();
+ if (n >= 0)
+ read_special_fonts(&font_table[n]->sf);
+ skip_line();
+}
+
+
+void special_request()
+{
+ read_special_fonts(&global_special_fonts);
+ skip_line();
+}
+
+int next_available_font_position()
+{
+ for (int i = 1; i < font_table_size && font_table[i] != 0; i++)
+ ;
+ return i;
+}
+
+int symbol_fontno(symbol s)
+{
+ s = get_font_translation(s);
+ for (int i = 0; i < font_table_size; i++)
+ if (font_table[i] != 0 && font_table[i]->is_named(s))
+ return i;
+ return -1;
+}
+
+int is_good_fontno(int n)
+{
+ return n >= 0 && n < font_table_size && font_table[n] != NULL;
+}
+
+int get_bold_fontno(int n)
+{
+ if (n >= 0 && n < font_table_size && font_table[n] != 0) {
+ hunits offset;
+ if (font_table[n]->get_bold(&offset))
+ return offset.to_units() + 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+hunits env_digit_width(environment *env)
+{
+ node *n = make_glyph_node(charset_table['0'], env);
+ if (n) {
+ hunits x = n->width();
+ delete n;
+ return x;
+ }
+ else
+ return H0;
+}
+
+hunits env_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return scale(fs.to_units()/3, env->get_space_size(), 12);
+ else
+ return font_table[fn]->get_space_width(fs, env->get_space_size());
+}
+
+hunits env_sentence_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return scale(fs.to_units()/3, env->get_sentence_space_size(), 12);
+ else
+ return font_table[fn]->get_space_width(fs, env->get_sentence_space_size());
+}
+
+hunits env_half_narrow_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return 0;
+ else
+ return font_table[fn]->get_half_narrow_space_width(fs);
+}
+
+hunits env_narrow_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return 0;
+ else
+ return font_table[fn]->get_narrow_space_width(fs);
+}
+
+void bold_font()
+{
+ int n = get_fontno();
+ if (n >= 0) {
+ if (has_arg()) {
+ if (tok.delimiter()) {
+ int f = get_fontno();
+ if (f >= 0) {
+ units offset;
+ if (has_arg() && get_number(&offset, 'u') && offset >= 1)
+ font_table[f]->set_conditional_bold(n, hunits(offset - 1));
+ else
+ font_table[f]->conditional_unbold(n);
+ }
+ }
+ else {
+ units offset;
+ if (get_number(&offset, 'u') && offset >= 1)
+ font_table[n]->set_bold(hunits(offset - 1));
+ else
+ font_table[n]->unbold();
+ }
+ }
+ else
+ font_table[n]->unbold();
+ }
+ skip_line();
+}
+
+track_kerning_function::track_kerning_function() : non_zero(0)
+{
+}
+
+track_kerning_function::track_kerning_function(int min_s, hunits min_a,
+ int max_s, hunits max_a)
+ : non_zero(1),
+ min_size(min_s), min_amount(min_a),
+ max_size(max_s), max_amount(max_a)
+{
+}
+
+int track_kerning_function::operator==(const track_kerning_function &tk)
+{
+ if (non_zero)
+ return (tk.non_zero
+ && min_size == tk.min_size
+ && min_amount == tk.min_amount
+ && max_size == tk.max_size
+ && max_amount == tk.max_amount);
+ else
+ return !tk.non_zero;
+}
+
+int track_kerning_function::operator!=(const track_kerning_function &tk)
+{
+ if (non_zero)
+ return (!tk.non_zero
+ || min_size != tk.min_size
+ || min_amount != tk.min_amount
+ || max_size != tk.max_size
+ || max_amount != tk.max_amount);
+ else
+ return tk.non_zero;
+}
+
+hunits track_kerning_function::compute(int size)
+{
+ if (non_zero) {
+ if (max_size <= min_size)
+ return min_amount;
+ else if (size <= min_size)
+ return min_amount;
+ else if (size >= max_size)
+ return max_amount;
+ else
+ return (scale(max_amount, size - min_size, max_size - min_size)
+ + scale(min_amount, max_size - size, max_size - min_size));
+ }
+ else
+ return H0;
+}
+
+void track_kern()
+{
+ int n = get_fontno();
+ if (n >= 0) {
+ int min_s, max_s;
+ hunits min_a, max_a;
+ if (has_arg()
+ && get_number(&min_s, 'z')
+ && get_hunits(&min_a, 'p')
+ && get_number(&max_s, 'z')
+ && get_hunits(&max_a, 'p')) {
+ track_kerning_function tk(min_s, min_a, max_s, max_a);
+ font_table[n]->set_track_kern(tk);
+ }
+ else {
+ track_kerning_function tk;
+ font_table[n]->set_track_kern(tk);
+ }
+ }
+ skip_line();
+}
+
+void constant_space()
+{
+ int n = get_fontno();
+ if (n >= 0) {
+ int x, y;
+ if (!has_arg() || !get_integer(&x))
+ font_table[n]->set_constant_space(CONSTANT_SPACE_NONE);
+ else {
+ if (!has_arg() || !get_number(&y, 'z'))
+ font_table[n]->set_constant_space(CONSTANT_SPACE_RELATIVE, x);
+ else
+ font_table[n]->set_constant_space(CONSTANT_SPACE_ABSOLUTE,
+ scale(y*x,
+ units_per_inch,
+ 36*72*sizescale));
+ }
+ }
+ skip_line();
+}
+
+void ligature()
+{
+ int lig;
+ if (has_arg() && get_integer(&lig) && lig >= 0 && lig <= 2)
+ global_ligature_mode = lig;
+ else
+ global_ligature_mode = 1;
+ skip_line();
+}
+
+void kern_request()
+{
+ int k;
+ if (has_arg() && get_integer(&k))
+ global_kern_mode = k != 0;
+ else
+ global_kern_mode = 1;
+ skip_line();
+}
+
+void set_soft_hyphen_char()
+{
+ soft_hyphen_char = get_optional_char();
+ if (!soft_hyphen_char)
+ soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
+ skip_line();
+}
+
+void init_output()
+{
+ if (suppress_output_flag)
+ the_output = new suppress_output_file;
+ else if (ascii_output_flag)
+ the_output = new ascii_output_file;
+ else
+ the_output = new troff_output_file;
+}
+
+class next_available_font_position_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *next_available_font_position_reg::get_string()
+{
+ return itoa(next_available_font_position());
+}
+
+class printing_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *printing_reg::get_string()
+{
+ if (the_output)
+ return the_output->is_printing() ? "1" : "0";
+ else
+ return "0";
+}
+
+void init_node_requests()
+{
+ init_request("fp", font_position);
+ init_request("sty", style);
+ init_request("cs", constant_space);
+ init_request("bd", bold_font);
+ init_request("uf", underline_font);
+ init_request("lg", ligature);
+ init_request("kern", kern_request);
+ init_request("tkf", track_kern);
+ init_request("special", special_request);
+ init_request("fspecial", font_special_request);
+ init_request("ftr", font_translate);
+ init_request("shc", set_soft_hyphen_char);
+ number_reg_dictionary.define(".fp", new next_available_font_position_reg);
+ number_reg_dictionary.define(".kern",
+ new constant_int_reg(&global_kern_mode));
+ number_reg_dictionary.define(".lg",
+ new constant_int_reg(&global_ligature_mode));
+ number_reg_dictionary.define(".P", new printing_reg);
+ soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
+}
diff --git a/gnu/usr.bin/groff/troff/node.h b/gnu/usr.bin/groff/troff/node.h
new file mode 100644
index 000000000000..02526e7c9534
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/node.h
@@ -0,0 +1,493 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+struct hyphen_list {
+ unsigned char hyphen;
+ unsigned char breakable;
+ unsigned char hyphenation_code;
+ hyphen_list *next;
+ hyphen_list(unsigned char code, hyphen_list *p = 0);
+};
+
+void hyphenate(hyphen_list *, unsigned);
+
+enum hyphenation_type { HYPHEN_MIDDLE, HYPHEN_BOUNDARY, HYPHEN_INHIBIT };
+
+class ascii_output_file;
+
+struct breakpoint;
+struct vertical_size;
+struct charinfo;
+
+class macro;
+
+class troff_output_file;
+class tfont;
+class environment;
+
+class glyph_node;
+class diverted_space_node;
+class token_node;
+
+struct node {
+ node *next;
+ node();
+ node(node *n);
+ node *add_char(charinfo *c, environment *, hunits *widthp);
+
+ virtual ~node();
+ virtual node *copy() = 0;
+ virtual hunits width();
+ virtual hunits subscript_correction();
+ virtual hunits italic_correction();
+ virtual hunits left_italic_correction();
+ virtual hunits skew();
+ virtual int nspaces();
+ virtual int merge_space(hunits);
+ virtual vunits vertical_width();
+ virtual node *last_char_node();
+ virtual void vertical_extent(vunits *min, vunits *max);
+ virtual int character_type();
+ virtual void set_vertical_size(vertical_size *);
+ virtual int ends_sentence();
+ virtual node *merge_self(node *);
+ virtual node *add_discretionary_hyphen();
+ virtual node *add_self(node *, hyphen_list **);
+ virtual hyphen_list *get_hyphen_list(hyphen_list *s = 0);
+ virtual void ascii_print(ascii_output_file *);
+ virtual void asciify(macro *);
+ virtual int discardable();
+ virtual void spread_space(int *, hunits *);
+ virtual void freeze_space();
+ virtual breakpoint *get_breakpoints(hunits width, int nspaces,
+ breakpoint *rest = 0,
+ int is_inner = 0);
+ virtual int nbreaks();
+ virtual void split(int, node **, node **);
+ virtual hyphenation_type get_hyphenation_type();
+ virtual int reread(int *);
+ virtual token_node *get_token_node();
+ virtual int overlaps_vertically();
+ virtual int overlaps_horizontally();
+ virtual units size();
+ virtual int interpret(macro *);
+
+ virtual node *merge_glyph_node(glyph_node *);
+ virtual tfont *get_tfont();
+ virtual void tprint(troff_output_file *);
+ virtual void zero_width_tprint(troff_output_file *);
+
+ node *add_italic_correction(hunits *);
+
+ virtual int same(node *) = 0;
+ virtual const char *type() = 0;
+};
+
+inline node::node() : next(0)
+{
+}
+
+inline node::node(node *n) : next(n)
+{
+}
+
+inline node::~node()
+{
+}
+
+// 0 means it doesn't, 1 means it does, 2 means it's transparent
+
+int node_list_ends_sentence(node *);
+
+struct breakpoint {
+ breakpoint *next;
+ hunits width;
+ int nspaces;
+ node *nd;
+ int index;
+ char hyphenated;
+};
+
+class line_start_node : public node {
+public:
+ line_start_node() {}
+ node *copy() { return new line_start_node; }
+ int same(node *);
+ const char *type();
+ void asciify(macro *);
+};
+
+class space_node : public node {
+private:
+#if 0
+ enum { BLOCK = 1024 };
+ static space_node *free_list;
+ void operator delete(void *);
+#endif
+protected:
+ hunits n;
+ char set;
+ space_node(hunits, int, node * = 0);
+public:
+ space_node(hunits d, node *p = 0);
+#if 0
+ ~space_node();
+ void *operator new(size_t);
+#endif
+ node *copy();
+ int nspaces();
+ hunits width();
+ int discardable();
+ int merge_space(hunits);
+ void freeze_space();
+ void spread_space(int*, hunits*);
+ void tprint(troff_output_file *);
+ breakpoint *get_breakpoints(hunits width, int nspaces, breakpoint *rest = 0,
+ int is_inner = 0);
+ int nbreaks();
+ void split(int, node **, node **);
+ void ascii_print(ascii_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class word_space_node : public space_node {
+protected:
+ word_space_node(hunits, int, node * = 0);
+public:
+ word_space_node(hunits, node * = 0);
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class unbreakable_space_node : public word_space_node {
+ unbreakable_space_node(hunits, int, node * = 0);
+public:
+ unbreakable_space_node(hunits, node * = 0);
+ node *copy();
+ int same(node *);
+ const char *type();
+ breakpoint *get_breakpoints(hunits width, int nspaces, breakpoint *rest = 0,
+ int is_inner = 0);
+ int nbreaks();
+ void split(int, node **, node **);
+ int merge_space(hunits);
+};
+
+class diverted_space_node : public node {
+public:
+ vunits n;
+ diverted_space_node(vunits d, node *p = 0);
+ node *copy();
+ int reread(int *);
+ int same(node *);
+ const char *type();
+};
+
+class diverted_copy_file_node : public node {
+ symbol filename;
+public:
+ vunits n;
+ diverted_copy_file_node(symbol s, node *p = 0);
+ node *copy();
+ int reread(int *);
+ int same(node *);
+ const char *type();
+};
+
+class extra_size_node : public node {
+ vunits n;
+ public:
+ extra_size_node(vunits i) : n(i) {}
+ void set_vertical_size(vertical_size *);
+ node *copy();
+ int same(node *);
+ const char *type();
+};
+
+class vertical_size_node : public node {
+ vunits n;
+ public:
+ vertical_size_node(vunits i) : n(i) {}
+ void set_vertical_size(vertical_size *);
+ void asciify(macro *);
+ node *copy();
+ int same(node *);
+ const char *type();
+};
+
+class hmotion_node : public node {
+protected:
+ hunits n;
+public:
+ hmotion_node(hunits i, node *next = 0) : node(next), n(i) {}
+ node *copy();
+ void tprint(troff_output_file *);
+ hunits width();
+ void ascii_print(ascii_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class space_char_hmotion_node : public hmotion_node {
+public:
+ space_char_hmotion_node(hunits i, node *next = 0);
+ node *copy();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+};
+
+class vmotion_node : public node {
+ vunits n;
+ public:
+ vmotion_node(vunits i) : n(i) {}
+ void tprint(troff_output_file *);
+ node *copy();
+ vunits vertical_width();
+ int same(node *);
+ const char *type();
+};
+
+
+class hline_node : public node {
+ hunits x;
+ node *n;
+ public:
+ hline_node(hunits i, node *c, node *next = 0) : node(next), x(i), n(c) {}
+ ~hline_node();
+ node *copy();
+ hunits width();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class vline_node : public node {
+ vunits x;
+ node *n;
+ public:
+ vline_node(vunits i, node *c, node *next= 0) : node(next), x(i), n(c) {}
+ ~vline_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ hunits width();
+ vunits vertical_width();
+ void vertical_extent(vunits *, vunits *);
+ int same(node *);
+ const char *type();
+};
+
+
+class dummy_node : public node {
+ public:
+ dummy_node(node *nd = 0) : node(nd) {}
+ node *copy();
+ int same(node *);
+ const char *type();
+ hyphenation_type get_hyphenation_type();
+};
+
+class transparent_dummy_node : public node {
+public:
+ transparent_dummy_node() {}
+ node *copy();
+ int same(node *);
+ const char *type();
+ int ends_sentence();
+ hyphenation_type get_hyphenation_type();
+};
+
+class zero_width_node : public node {
+ node *n;
+ public:
+ zero_width_node(node *gn);
+ ~zero_width_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+ void append(node *);
+ int character_type();
+ void vertical_extent(vunits *min, vunits *max);
+};
+
+class left_italic_corrected_node : public node {
+ node *n;
+ hunits x;
+public:
+ left_italic_corrected_node(node * = 0);
+ ~left_italic_corrected_node();
+ void tprint(troff_output_file *);
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ node *copy();
+ int same(node *);
+ const char *type();
+ hunits width();
+ node *last_char_node();
+ void vertical_extent(vunits *, vunits *);
+ int ends_sentence();
+ int overlaps_horizontally();
+ int overlaps_vertically();
+ hyphenation_type get_hyphenation_type();
+ tfont *get_tfont();
+ int character_type();
+ hunits skew();
+ hunits italic_correction();
+ hunits subscript_correction();
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ node *add_self(node *, hyphen_list **);
+ node *merge_glyph_node(glyph_node *);
+};
+
+class overstrike_node : public node {
+ node *list;
+ hunits max_width;
+public:
+ overstrike_node();
+ ~overstrike_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ void overstrike(node *); // add another node to be overstruck
+ hunits width();
+ int same(node *);
+ const char *type();
+};
+
+class bracket_node : public node {
+ node *list;
+ hunits max_width;
+public:
+ bracket_node();
+ ~bracket_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ void bracket(node *); // add another node to be overstruck
+ hunits width();
+ int same(node *);
+ const char *type();
+};
+
+class special_node : public node {
+ macro mac;
+ void tprint_start(troff_output_file *);
+ void tprint_char(troff_output_file *, unsigned char);
+ void tprint_end(troff_output_file *);
+public:
+ special_node(const macro &);
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+
+struct hvpair {
+ hunits h;
+ vunits v;
+
+ hvpair();
+};
+
+class draw_node : public node {
+ int npoints;
+ font_size sz;
+ char code;
+ hvpair *point;
+public:
+ draw_node(char, hvpair *, int, font_size);
+ ~draw_node();
+ hunits width();
+ vunits vertical_width();
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class charinfo;
+node *make_node(charinfo *ci, environment *);
+int character_exists(charinfo *, environment *);
+
+int same_node_list(node *n1, node *n2);
+node *reverse_node_list(node *n);
+void delete_node_list(node *);
+node *copy_node_list(node *);
+
+int get_bold_fontno(int f);
+
+inline hyphen_list::hyphen_list(unsigned char code, hyphen_list *p)
+: hyphenation_code(code), next(p), hyphen(0), breakable(0)
+{
+}
+
+extern void read_desc();
+extern int mount_font(int n, symbol, symbol = NULL_SYMBOL);
+extern void mount_style(int n, symbol);
+extern int is_good_fontno(int n);
+extern int symbol_fontno(symbol);
+extern int next_available_font_position();
+extern void init_size_table(int *);
+extern int get_underline_fontno();
+
+class output_file {
+ char make_g_plus_plus_shut_up;
+public:
+ output_file();
+ virtual ~output_file();
+ virtual void trailer(vunits page_length);
+ virtual void flush() = 0;
+ virtual void transparent_char(unsigned char) = 0;
+ virtual void print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after) = 0;
+ virtual void begin_page(int pageno, vunits page_length) = 0;
+ virtual void copy_file(hunits x, vunits y, const char *filename) = 0;
+ virtual int is_printing() = 0;
+#ifdef COLUMN
+ virtual void vjustify(vunits, symbol);
+#endif /* COLUMN */
+};
+
+extern char *pipe_command;
+
+extern output_file *the_output;
+extern void init_output();
+int in_output_page_list(int n);
+
+static void invalidate_fontno(int);
+
+class font_family {
+ int *map;
+ int map_size;
+public:
+ const symbol nm;
+
+ font_family(symbol);
+ ~font_family();
+ make_definite(int);
+ friend void invalidate_fontno(int);
+};
+
+font_family *lookup_family(symbol);
diff --git a/gnu/usr.bin/groff/troff/number.cc b/gnu/usr.bin/groff/troff/number.cc
new file mode 100644
index 000000000000..3e695b527acb
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/number.cc
@@ -0,0 +1,669 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "troff.h"
+#include "symbol.h"
+#include "hvunits.h"
+#include "env.h"
+#include "token.h"
+#include "div.h"
+
+vunits V0;
+hunits H0;
+
+int hresolution = 1;
+int vresolution = 1;
+int units_per_inch;
+int sizescale;
+
+static int parse_expr(units *v, int scale_indicator, int parenthesised);
+static int start_number();
+
+int get_vunits(vunits *res, unsigned char si)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, si, 0)) {
+ *res = vunits(x);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int get_hunits(hunits *res, unsigned char si)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, si, 0)) {
+ *res = hunits(x);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int get_number(units *res, unsigned char si)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, si, 0)) {
+ *res = x;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int get_integer(int *res)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, 0, 0)) {
+ *res = x;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+enum incr_number_result { BAD, ABSOLUTE, INCREMENT, DECREMENT };
+
+static incr_number_result get_incr_number(units *res, unsigned char);
+
+int get_vunits(vunits *res, unsigned char si, vunits prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, si)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + v;
+ break;
+ case DECREMENT:
+ *res = prev_value - v;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+int get_hunits(hunits *res, unsigned char si, hunits prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, si)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + v;
+ break;
+ case DECREMENT:
+ *res = prev_value - v;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+int get_number(units *res, unsigned char si, units prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, si)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + v;
+ break;
+ case DECREMENT:
+ *res = prev_value - v;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+int get_integer(int *res, int prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, 0)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + int(v);
+ break;
+ case DECREMENT:
+ *res = prev_value - int(v);
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+
+static incr_number_result get_incr_number(units *res, unsigned char si)
+{
+ if (!start_number())
+ return BAD;
+ incr_number_result result = ABSOLUTE;
+ if (tok.ch() == '+') {
+ tok.next();
+ result = INCREMENT;
+ }
+ else if (tok.ch() == '-') {
+ tok.next();
+ result = DECREMENT;
+ }
+ if (parse_expr(res, si, 0))
+ return result;
+ else
+ return BAD;
+}
+
+static int start_number()
+{
+ while (tok.space())
+ tok.next();
+ if (tok.newline()) {
+ warning(WARN_MISSING, "missing number");
+ return 0;
+ }
+ if (tok.tab()) {
+ warning(WARN_TAB, "tab character where number expected");
+ return 0;
+ }
+ if (tok.right_brace()) {
+ warning(WARN_RIGHT_BRACE, "`\\}' where number expected");
+ return 0;
+ }
+ return 1;
+}
+
+enum { OP_LEQ = 'L', OP_GEQ = 'G', OP_MAX = 'X', OP_MIN = 'N' };
+
+#define SCALE_INDICATOR_CHARS "icPmnpuvMsz"
+
+static int parse_term(units *v, int scale_indicator, int parenthesised);
+
+static int parse_expr(units *v, int scale_indicator, int parenthesised)
+{
+ int result = parse_term(v, scale_indicator, parenthesised);
+ while (result) {
+ if (parenthesised)
+ tok.skip();
+ int op = tok.ch();
+ switch (op) {
+ case '+':
+ case '-':
+ case '/':
+ case '*':
+ case '%':
+ case ':':
+ case '&':
+ tok.next();
+ break;
+ case '>':
+ tok.next();
+ if (tok.ch() == '=') {
+ tok.next();
+ op = OP_GEQ;
+ }
+ else if (tok.ch() == '?') {
+ tok.next();
+ op = OP_MAX;
+ }
+ break;
+ case '<':
+ tok.next();
+ if (tok.ch() == '=') {
+ tok.next();
+ op = OP_LEQ;
+ }
+ else if (tok.ch() == '?') {
+ tok.next();
+ op = OP_MIN;
+ }
+ break;
+ case '=':
+ tok.next();
+ if (tok.ch() == '=')
+ tok.next();
+ break;
+ default:
+ return result;
+ }
+ units v2;
+ if (!parse_term(&v2, scale_indicator, parenthesised))
+ return 0;
+ int overflow = 0;
+ switch (op) {
+ case '<':
+ *v = *v < v2;
+ break;
+ case '>':
+ *v = *v > v2;
+ break;
+ case OP_LEQ:
+ *v = *v <= v2;
+ break;
+ case OP_GEQ:
+ *v = *v >= v2;
+ break;
+ case OP_MIN:
+ if (*v > v2)
+ *v = v2;
+ break;
+ case OP_MAX:
+ if (*v < v2)
+ *v = v2;
+ break;
+ case '=':
+ *v = *v == v2;
+ break;
+ case '&':
+ *v = *v > 0 && v2 > 0;
+ break;
+ case ':':
+ *v = *v > 0 || v2 > 0;
+ case '+':
+ if (v2 < 0) {
+ if (*v < INT_MIN - v2)
+ overflow = 1;
+ }
+ else if (v2 > 0) {
+ if (*v > INT_MAX - v2)
+ overflow = 1;
+ }
+ if (overflow) {
+ error("addition overflow");
+ return 0;
+ }
+ *v += v2;
+ break;
+ case '-':
+ if (v2 < 0) {
+ if (*v > INT_MAX + v2)
+ overflow = 1;
+ }
+ else if (v2 > 0) {
+ if (*v < INT_MIN + v2)
+ overflow = 1;
+ }
+ if (overflow) {
+ error("subtraction overflow");
+ return 0;
+ }
+ *v -= v2;
+ break;
+ case '*':
+ if (v2 < 0) {
+ if (*v > 0) {
+ if (*v > -(unsigned)INT_MIN / -(unsigned)v2)
+ overflow = 1;
+ }
+ else if (-(unsigned)*v > INT_MAX / -(unsigned)v2)
+ overflow = 1;
+ }
+ else if (v2 > 0) {
+ if (*v > 0) {
+ if (*v > INT_MAX / v2)
+ overflow = 1;
+ }
+ else if (-(unsigned)*v > -(unsigned)INT_MIN / v2)
+ overflow = 1;
+ }
+ if (overflow) {
+ error("multiplication overflow");
+ return 0;
+ }
+ *v *= v2;
+ break;
+ case '/':
+ if (v2 == 0) {
+ error("division by zero");
+ return 0;
+ }
+ *v /= v2;
+ break;
+ case '%':
+ if (v2 == 0) {
+ error("modulus by zero");
+ return 0;
+ }
+ *v %= v2;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ return result;
+}
+
+static int parse_term(units *v, int scale_indicator, int parenthesised)
+{
+ int negative = 0;
+ for (;;)
+ if (parenthesised && tok.space())
+ tok.next();
+ else if (tok.ch() == '+')
+ tok.next();
+ else if (tok.ch() == '-') {
+ tok.next();
+ negative = !negative;
+ }
+ else
+ break;
+ unsigned char c = tok.ch();
+ switch (c) {
+ case '|':
+ // | is not restricted to the outermost level
+ // tbl uses this
+ tok.next();
+ if (!parse_term(v, scale_indicator, parenthesised))
+ return 0;
+ int tem;
+ tem = (scale_indicator == 'v'
+ ? curdiv->get_vertical_position().to_units()
+ : curenv->get_input_line_position().to_units());
+ if (tem >= 0) {
+ if (*v < INT_MIN + tem) {
+ error("numeric overflow");
+ return 0;
+ }
+ }
+ else {
+ if (*v > INT_MAX + tem) {
+ error("numeric overflow");
+ return 0;
+ }
+ }
+ *v -= tem;
+ if (negative) {
+ if (*v == INT_MIN) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v = -*v;
+ }
+ return 1;
+ case '(':
+ tok.next();
+ c = tok.ch();
+ if (c == ')') {
+ warning(WARN_SYNTAX, "empty parentheses");
+ tok.next();
+ *v = 0;
+ return 1;
+ }
+ else if (c != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) {
+ tok.next();
+ if (tok.ch() == ';') {
+ tok.next();
+ scale_indicator = c;
+ }
+ else {
+ error("expected `;' after scale-indicator (got %1)",
+ tok.description());
+ return 0;
+ }
+ }
+ else if (c == ';') {
+ scale_indicator = 0;
+ tok.next();
+ }
+ if (!parse_expr(v, scale_indicator, 1))
+ return 0;
+ tok.skip();
+ if (tok.ch() != ')') {
+ warning(WARN_SYNTAX, "missing `)' (got %1)", tok.description());
+ }
+ else
+ tok.next();
+ if (negative) {
+ if (*v == INT_MIN) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v = -*v;
+ }
+ return 1;
+ case '.':
+ *v = 0;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ *v = 0;
+ do {
+ if (*v > INT_MAX/10) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v *= 10;
+ if (*v > INT_MAX - (int(c) - '0')) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v += c - '0';
+ tok.next();
+ c = tok.ch();
+ } while (csdigit(c));
+ break;
+ case '/':
+ case '*':
+ case '%':
+ case ':':
+ case '&':
+ case '>':
+ case '<':
+ case '=':
+ warning(WARN_SYNTAX, "empty left operand");
+ *v = 0;
+ return 1;
+ default:
+ warning(WARN_NUMBER, "numeric expression expected (got %1)",
+ tok.description());
+ return 0;
+ }
+ int divisor = 1;
+ if (tok.ch() == '.') {
+ tok.next();
+ for (;;) {
+ c = tok.ch();
+ if (!csdigit(c))
+ break;
+ // we may multiply the divisor by 254 later on
+ if (divisor <= INT_MAX/2540 && *v <= (INT_MAX - 9)/10) {
+ *v *= 10;
+ *v += c - '0';
+ divisor *= 10;
+ }
+ tok.next();
+ }
+ }
+ int si = scale_indicator;
+ int do_next = 0;
+ if ((c = tok.ch()) != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) {
+ switch (scale_indicator) {
+ case 'z':
+ if (c != 'u' && c != 'z') {
+ warning(WARN_SCALE,
+ "only `z' and `u' scale indicators valid in this context");
+ break;
+ }
+ si = c;
+ break;
+ case 0:
+ warning(WARN_SCALE, "scale indicator invalid in this context");
+ break;
+ case 'u':
+ si = c;
+ break;
+ default:
+ if (c == 'z') {
+ warning(WARN_SCALE, "`z' scale indicator invalid in this context");
+ break;
+ }
+ si = c;
+ break;
+ }
+ // Don't do tok.next() here because the next token might be \s, which
+ // would affect the interpretation of m.
+ do_next = 1;
+ }
+ switch (si) {
+ case 'i':
+ *v = scale(*v, units_per_inch, divisor);
+ break;
+ case 'c':
+ *v = scale(*v, units_per_inch*100, divisor*254);
+ break;
+ case 0:
+ case 'u':
+ if (divisor != 1)
+ *v /= divisor;
+ break;
+ case 'p':
+ *v = scale(*v, units_per_inch, divisor*72);
+ break;
+ case 'P':
+ *v = scale(*v, units_per_inch, divisor*6);
+ break;
+ case 'm':
+ {
+ // Convert to hunits so that with -Tascii `m' behaves as in nroff.
+ hunits em = curenv->get_size();
+ *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor);
+ }
+ break;
+ case 'M':
+ {
+ hunits em = curenv->get_size();
+ *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor*100);
+ }
+ break;
+ case 'n':
+ {
+ // Convert to hunits so that with -Tascii `n' behaves as in nroff.
+ hunits en = curenv->get_size()/2;
+ *v = scale(*v, en.is_zero() ? hresolution : en.to_units(), divisor);
+ }
+ break;
+ case 'v':
+ *v = scale(*v, curenv->get_vertical_spacing().to_units(), divisor);
+ break;
+ case 's':
+ while (divisor > INT_MAX/(sizescale*72)) {
+ divisor /= 10;
+ *v /= 10;
+ }
+ *v = scale(*v, units_per_inch, divisor*sizescale*72);
+ break;
+ case 'z':
+ *v = scale(*v, sizescale, divisor);
+ break;
+ default:
+ assert(0);
+ }
+ if (do_next)
+ tok.next();
+ if (negative) {
+ if (*v == INT_MIN) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v = -*v;
+ }
+ return 1;
+}
+
+units scale(units n, units x, units y)
+{
+ assert(x >= 0 && y > 0);
+ if (x == 0)
+ return 0;
+ if (n >= 0) {
+ if (n <= INT_MAX/x)
+ return (n*x)/y;
+ }
+ else {
+ if (-(unsigned)n <= -(unsigned)INT_MIN/x)
+ return (n*x)/y;
+ }
+ double res = n*double(x)/double(y);
+ if (res > INT_MAX) {
+ error("numeric overflow");
+ return INT_MAX;
+ }
+ else if (res < INT_MIN) {
+ error("numeric overflow");
+ return INT_MIN;
+ }
+ return int(res);
+}
+
+vunits::vunits(units x)
+{
+ // don't depend on the rounding direction for division of negative integers
+ if (vresolution == 1)
+ n = x;
+ else
+ n = (x < 0
+ ? -((-x + vresolution/2 - 1)/vresolution)
+ : (x + vresolution/2 - 1)/vresolution);
+}
+
+hunits::hunits(units x)
+{
+ // don't depend on the rounding direction for division of negative integers
+ if (hresolution == 1)
+ n = x;
+ else
+ n = (x < 0
+ ? -((-x + hresolution/2 - 1)/hresolution)
+ : (x + hresolution/2 - 1)/hresolution);
+}
diff --git a/gnu/usr.bin/groff/troff/reg.cc b/gnu/usr.bin/groff/troff/reg.cc
new file mode 100644
index 000000000000..cefeb87ed5f2
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/reg.cc
@@ -0,0 +1,458 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "token.h"
+#include "request.h"
+#include "reg.h"
+
+object_dictionary number_reg_dictionary(101);
+
+int reg::get_value(units * /*d*/)
+{
+ return 0;
+}
+
+void reg::increment()
+{
+ error("can't increment read-only register");
+}
+
+void reg::decrement()
+{
+ error("can't decrement read-only register");
+}
+
+void reg::set_increment(units /*n*/)
+{
+ error("can't auto increment read-only register");
+}
+
+void reg::alter_format(char /*f*/, int /*w*/)
+{
+ error("can't alter format of read-only register");
+}
+
+const char *reg::get_format()
+{
+ return "0";
+}
+
+void reg::set_value(units /*n*/)
+{
+ error("can't write read-only register");
+}
+
+general_reg::general_reg() : format('1'), width(0), inc(0)
+{
+}
+
+static const char *number_value_to_ascii(int value, char format, int width)
+{
+ static char buf[128]; // must be at least 21
+ switch(format) {
+ case '1':
+ if (width <= 0)
+ return itoa(value);
+ else if (width > sizeof(buf) - 2)
+ sprintf(buf, "%.*d", sizeof(buf) - 2, int(value));
+ else
+ sprintf(buf, "%.*d", width, int(value));
+ break;
+ case 'i':
+ case 'I':
+ {
+ char *p = buf;
+ // troff uses z and w to represent 10000 and 5000 in Roman
+ // numerals; I can find no historical basis for this usage
+ const char *s = format == 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
+ int n = int(value);
+ if (n >= 40000 || n <= -40000) {
+ error("magnitude of `%1' too big for i or I format", n);
+ return itoa(n);
+ }
+ if (n == 0) {
+ *p++ = '0';
+ *p = 0;
+ break;
+ }
+ if (n < 0) {
+ *p++ = '-';
+ n = -n;
+ }
+ while (n >= 10000) {
+ *p++ = s[0];
+ n -= 10000;
+ }
+ for (int i = 1000; i > 0; i /= 10, s += 2) {
+ int m = n/i;
+ n -= m*i;
+ switch (m) {
+ case 3:
+ *p++ = s[2];
+ /* falls through */
+ case 2:
+ *p++ = s[2];
+ /* falls through */
+ case 1:
+ *p++ = s[2];
+ break;
+ case 4:
+ *p++ = s[2];
+ *p++ = s[1];
+ break;
+ case 8:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 7:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 6:
+ *p++ = s[1];
+ *p++ = s[2];
+ break;
+ case 5:
+ *p++ = s[1];
+ break;
+ case 9:
+ *p++ = s[2];
+ *p++ = s[0];
+ }
+ }
+ *p = 0;
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ int n = value;
+ char *p = buf;
+ if (n == 0) {
+ *p++ = '0';
+ *p = 0;
+ }
+ else {
+ if (n < 0) {
+ n = -n;
+ *p++ = '-';
+ }
+ // this is a bit tricky
+ while (n > 0) {
+ int d = n % 26;
+ if (d == 0)
+ d = 26;
+ n -= d;
+ n /= 26;
+ *p++ = format + d - 1;
+ }
+ *p-- = 0;
+ char *q = buf[0] == '-' ? buf+1 : buf;
+ while (q < p) {
+ char temp = *q;
+ *q = *p;
+ *p = temp;
+ --p;
+ ++q;
+ }
+ }
+ break;
+ }
+ default:
+ assert(0);
+ break;
+ }
+ return buf;
+}
+
+const char *general_reg::get_string()
+{
+ units n;
+ if (!get_value(&n))
+ return "";
+ return number_value_to_ascii(n, format, width);
+}
+
+
+void general_reg::increment()
+{
+ int n;
+ if (get_value(&n))
+ set_value(n + inc);
+}
+
+void general_reg::decrement()
+{
+ int n;
+ if (get_value(&n))
+ set_value(n - inc);
+}
+
+void general_reg::set_increment(units n)
+{
+ inc = n;
+}
+
+void general_reg::alter_format(char f, int w)
+{
+ format = f;
+ width = w;
+}
+
+static const char *number_format_to_ascii(char format, int width)
+{
+ static char buf[24];
+ if (format == '1') {
+ if (width > 0) {
+ int n = width;
+ if (n > int(sizeof(buf)) - 1)
+ n = int(sizeof(buf)) - 1;
+ sprintf(buf, "%.*d", n, 0);
+ return buf;
+ }
+ else
+ return "0";
+ }
+ else {
+ buf[0] = format;
+ buf[1] = '\0';
+ return buf;
+ }
+}
+
+const char *general_reg::get_format()
+{
+ return number_format_to_ascii(format, width);
+}
+
+class number_reg : public general_reg {
+ units value;
+public:
+ number_reg();
+ int get_value(units *);
+ void set_value(units);
+};
+
+number_reg::number_reg() : value(0)
+{
+}
+
+int number_reg::get_value(units *res)
+{
+ *res = value;
+ return 1;
+}
+
+void number_reg::set_value(units n)
+{
+ value = n;
+}
+
+variable_reg::variable_reg(units *p) : ptr(p)
+{
+}
+
+void variable_reg::set_value(units n)
+{
+ *ptr = n;
+}
+
+int variable_reg::get_value(units *res)
+{
+ *res = *ptr;
+ return 1;
+}
+
+void define_number_reg()
+{
+ symbol nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ units v;
+ units prev_value;
+ if (!r || !r->get_value(&prev_value))
+ prev_value = 0;
+ if (get_number(&v, 'u', prev_value)) {
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ r->set_value(v);
+ if (tok.space() && has_arg() && get_number(&v, 'u'))
+ r->set_increment(v);
+ }
+ skip_line();
+}
+
+#if 0
+void inline_define_reg()
+{
+ token start;
+ start.next();
+ if (!start.delimiter(1))
+ return;
+ tok.next();
+ symbol nm = get_name(1);
+ if (nm.is_null())
+ return;
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ units v;
+ units prev_value;
+ if (!r->get_value(&prev_value))
+ prev_value = 0;
+ if (get_number(&v, 'u', prev_value)) {
+ r->set_value(v);
+ if (start != tok) {
+ if (get_number(&v, 'u')) {
+ r->set_increment(v);
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ }
+ }
+ }
+}
+#endif
+
+void set_number_reg(symbol nm, units n)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ r->set_value(n);
+}
+
+reg *lookup_number_reg(symbol nm)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ warning(WARN_REG, "number register `%1' not defined", nm.contents());
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ return r;
+}
+
+void alter_format()
+{
+ symbol nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ tok.skip();
+ char c = tok.ch();
+ if (csdigit(c)) {
+ int n = 0;
+ do {
+ ++n;
+ tok.next();
+ } while (csdigit(tok.ch()));
+ r->alter_format('1', n);
+ }
+ else if (c == 'i' || c == 'I' || c == 'a' || c == 'A')
+ r->alter_format(c);
+ else if (tok.newline() || tok.eof())
+ warning(WARN_MISSING, "missing number register format");
+ else
+ error("bad number register format (got %1)", tok.description());
+ skip_line();
+}
+
+void remove_reg()
+{
+ for (;;) {
+ symbol s = get_name();
+ if (s.is_null())
+ break;
+ number_reg_dictionary.remove(s);
+ }
+ skip_line();
+}
+
+void alias_reg()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null()) {
+ if (!number_reg_dictionary.alias(s1, s2))
+ warning(WARN_REG, "number register `%1' not defined", s2.contents());
+ }
+ }
+ skip_line();
+}
+
+void rename_reg()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null())
+ number_reg_dictionary.rename(s1, s2);
+ }
+ skip_line();
+}
+
+void print_number_regs()
+{
+ object_dictionary_iterator iter(number_reg_dictionary);
+ reg *r;
+ symbol s;
+ while (iter.get(&s, (object **)&r)) {
+ assert(!s.is_null());
+ errprint("%1\t", s.contents());
+ const char *p = r->get_string();
+ if (p)
+ errprint(p);
+ errprint("\n");
+ }
+ fflush(stderr);
+ skip_line();
+}
+
+void init_reg_requests()
+{
+ init_request("rr", remove_reg);
+ init_request("nr", define_number_reg);
+ init_request("af", alter_format);
+ init_request("aln", alias_reg);
+ init_request("rnn", rename_reg);
+ init_request("pnr", print_number_regs);
+}
diff --git a/gnu/usr.bin/groff/troff/reg.h b/gnu/usr.bin/groff/troff/reg.h
new file mode 100644
index 000000000000..4ecbc9796014
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/reg.h
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+class reg : public object {
+public:
+ virtual const char *get_string() = 0;
+ virtual int get_value(units *);
+ virtual void increment();
+ virtual void decrement();
+ virtual void set_increment(units);
+ virtual void alter_format(char f, int w = 0);
+ virtual const char *get_format();
+ virtual void set_value(units);
+};
+
+class constant_int_reg : public reg {
+ int *p;
+public:
+ constant_int_reg(int *);
+ const char *get_string();
+};
+
+class general_reg : public reg {
+ char format;
+ int width;
+ int inc;
+public:
+ general_reg();
+ const char *get_string();
+ void increment();
+ void decrement();
+ void alter_format(char f, int w = 0);
+ void set_increment(units);
+ const char *get_format();
+ void add_value(units);
+
+ void set_value(units) = 0;
+ int get_value(units *) = 0;
+};
+
+class variable_reg : public general_reg {
+ units *ptr;
+public:
+ variable_reg(int *);
+ void set_value(units);
+ int get_value(units *);
+};
+
+extern object_dictionary number_reg_dictionary;
+extern void set_number_reg(symbol nm, units n);
+
+reg *lookup_number_reg(symbol);
+#if 0
+void inline_define_reg();
+#endif
diff --git a/gnu/usr.bin/groff/troff/request.h b/gnu/usr.bin/groff/troff/request.h
new file mode 100644
index 000000000000..2de9fb7c7739
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/request.h
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+typedef void (*REQUEST_FUNCP)();
+
+class macro;
+
+class request_or_macro : public object {
+public:
+ request_or_macro();
+ virtual void invoke(symbol s) = 0;
+ virtual macro *to_macro();
+};
+
+class request : public request_or_macro {
+ REQUEST_FUNCP p;
+public:
+ void invoke(symbol);
+ request(REQUEST_FUNCP);
+};
+
+void delete_request_or_macro(request_or_macro *);
+
+extern object_dictionary request_dictionary;
+
+struct macro_header;
+struct node;
+
+class macro : public request_or_macro {
+ macro_header *p;
+ const char *filename; // where was it defined?
+ int lineno;
+ int length;
+public:
+ macro();
+ ~macro();
+ macro(const macro &);
+ macro &operator=(const macro &);
+ void append(unsigned char);
+ void append(node *);
+ void invoke(symbol);
+ macro *to_macro();
+ void print_size();
+ int empty();
+ friend class string_iterator;
+ friend void chop_macro();
+ friend int operator==(const macro &, const macro &);
+};
+
+extern void init_input_requests();
+extern void init_div_requests();
+extern void init_node_requests();
+extern void init_reg_requests();
+extern void init_env_requests();
+extern void init_hyphen_requests();
+extern void init_request(const char *s, REQUEST_FUNCP f);
+
+extern int no_break_flag; // indicates whether request was invoked with . or '
+
+class charinfo;
+class environment;
+
+node *charinfo_to_node_list(charinfo *, const environment *);
diff --git a/gnu/usr.bin/groff/troff/symbol.cc b/gnu/usr.bin/groff/troff/symbol.cc
new file mode 100644
index 000000000000..eb816990d1ec
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/symbol.cc
@@ -0,0 +1,144 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "troff.h"
+#include "symbol.h"
+
+const char **symbol::table = 0;
+int symbol::table_used = 0;
+int symbol::table_size = 0;
+char *symbol::block = 0;
+int symbol::block_size = 0;
+
+const symbol NULL_SYMBOL;
+
+#ifdef BLOCK_SIZE
+#undef BLOCK_SIZE
+#endif
+
+const int BLOCK_SIZE = 1024;
+// the table will increase in size as necessary
+// the size will be chosen from the following array
+// add some more if you want
+// I think it unlikely that we'll need more than a million symbols
+static const unsigned int table_sizes[] = {
+101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021, 160001, 500009, 1000003, 0
+};
+const double FULL_MAX = 0.3; // don't let the table get more than this full
+
+static unsigned int hash_string(const char *p)
+{
+ // compute a hash code; this assumes 32-bit unsigned ints
+ // see p436 of Compilers by Aho, Sethi & Ullman
+ // give special treatment to two-character names
+ unsigned int hc = 0, g;
+ if (*p != 0) {
+ hc = *p++;
+ if (*p != 0) {
+ hc <<= 7;
+ hc += *p++;
+ for (; *p != 0; p++) {
+ hc <<= 4;
+ hc += *p;
+ if ((g = (hc & 0xf0000000)) == 0) {
+ hc ^= g >> 24;
+ hc ^= g;
+ }
+ }
+ }
+ }
+ return hc;
+}
+
+symbol::symbol(const char *p, int how)
+{
+ if (p == 0 || *p == 0) {
+ s = 0;
+ return;
+ }
+ if (table == 0) {
+ table_size = table_sizes[0];
+ table = (const char **)new char*[table_size];
+ for (int i = 0; i < table_size; i++)
+ table[i] = 0;
+ table_used = 0;
+ }
+ unsigned int hc = hash_string(p);
+ for (const char **pp = table + hc % table_size;
+ *pp != 0;
+ (pp == table ? pp = table + table_size - 1 : --pp))
+ if (strcmp(p, *pp) == 0) {
+ s = *pp;
+ return;
+ }
+ if (how == MUST_ALREADY_EXIST) {
+ s = 0;
+ return;
+ }
+ if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
+ const char **old_table = table;
+ unsigned int old_table_size = table_size;
+ for (int i = 1; table_sizes[i] <= old_table_size; i++)
+ if (table_sizes[i] == 0)
+ fatal("too many symbols");
+ table_size = table_sizes[i];
+ table_used = 0;
+ table = (const char **)new char*[table_size];
+ for (i = 0; i < table_size; i++)
+ table[i] = 0;
+ for (pp = old_table + old_table_size - 1;
+ pp >= old_table;
+ --pp) {
+ symbol temp(*pp, 1); /* insert it into the new table */
+ }
+ a_delete old_table;
+ for (pp = table + hc % table_size;
+ *pp != 0;
+ (pp == table ? pp = table + table_size - 1 : --pp))
+ ;
+ }
+ ++table_used;
+ if (how == DONT_STORE) {
+ s = *pp = p;
+ }
+ else {
+ int len = strlen(p)+1;
+ if (block == 0 || block_size < len) {
+ block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
+ block = new char [block_size];
+ }
+ (void)strcpy(block, p);
+ s = *pp = block;
+ block += len;
+ block_size -= len;
+ }
+}
+
+symbol concat(symbol s1, symbol s2)
+{
+ char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
+ strcpy(buf, s1.contents());
+ strcat(buf, s2.contents());
+ symbol res(buf);
+ a_delete buf;
+ return res;
+}
+
diff --git a/gnu/usr.bin/groff/troff/symbol.h b/gnu/usr.bin/groff/troff/symbol.h
new file mode 100644
index 000000000000..37916742de27
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/symbol.h
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define DONT_STORE 1
+#define MUST_ALREADY_EXIST 2
+
+class symbol {
+ static const char **table;
+ static int table_used;
+ static int table_size;
+ static char *block;
+ static int block_size;
+ const char *s;
+public:
+ symbol(const char *p, int how = 0);
+ symbol();
+ unsigned long hash() const;
+ operator ==(symbol) const;
+ operator !=(symbol) const;
+ const char *contents() const;
+ int is_null() const;
+};
+
+
+extern const symbol NULL_SYMBOL;
+
+inline symbol::symbol() : s(0)
+{
+}
+
+inline int symbol::operator==(symbol p) const
+{
+ return s == p.s;
+}
+
+inline int symbol::operator!=(symbol p) const
+{
+ return s != p.s;
+}
+
+inline unsigned long symbol::hash() const
+{
+ return (unsigned long)s;
+}
+
+inline const char *symbol::contents() const
+{
+ return s;
+}
+
+inline int symbol::is_null() const
+{
+ return s == 0;
+}
+
+symbol concat(symbol, symbol);
diff --git a/gnu/usr.bin/groff/troff/token.h b/gnu/usr.bin/groff/troff/token.h
new file mode 100644
index 000000000000..486c6eafde13
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/token.h
@@ -0,0 +1,197 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+struct charinfo;
+struct node;
+struct vunits;
+
+// See ARM p251.
+static void process_input_stack();
+
+class token {
+ symbol nm;
+ node *nd;
+ unsigned char c;
+ int val;
+ units dim;
+ enum token_type {
+ TOKEN_BACKSPACE,
+ TOKEN_BEGIN_TRAP,
+ TOKEN_CHAR, // a normal printing character
+ TOKEN_DUMMY,
+ TOKEN_EMPTY, // this is the initial value
+ TOKEN_END_TRAP,
+ TOKEN_ESCAPE, // \e
+ TOKEN_HYPHEN_INDICATOR,
+ TOKEN_INTERRUPT, // \c
+ TOKEN_ITALIC_CORRECTION, // \/
+ TOKEN_LEADER, // ^A
+ TOKEN_LEFT_BRACE,
+ TOKEN_MARK_INPUT, // \k -- `nm' is the name of the register
+ TOKEN_NEWLINE, // newline
+ TOKEN_NODE,
+ TOKEN_NUMBERED_CHAR,
+ TOKEN_PAGE_EJECTOR,
+ TOKEN_REQUEST,
+ TOKEN_RIGHT_BRACE,
+ TOKEN_SPACE, // ` ' -- ordinary space
+ TOKEN_SPECIAL, // a special character -- \' \` \- \(xx
+ TOKEN_SPREAD, // \p -- break and spread output line
+ TOKEN_TAB, // tab
+ TOKEN_TRANSPARENT, // \!
+ TOKEN_EOF // end of file
+ } type;
+public:
+ token();
+ ~token();
+ token(const token &);
+ void operator=(const token &);
+ void next();
+ void process();
+ void skip();
+ int eof();
+ int nspaces(); // 1 if space, 2 if double space, 0 otherwise
+ int space(); // is it a space or double space?
+ int white_space(); // is the current token space or tab?
+ int newline(); // is the current token a newline?
+ int tab(); // is the current token a tab?
+ int leader();
+ int backspace();
+ int delimiter(int warn = 0); // is it suitable for use as a delimiter?
+ int dummy();
+ int transparent();
+ int left_brace();
+ int right_brace();
+ int page_ejector();
+ int hyphen_indicator();
+ int operator==(const token &); // need this for delimiters, and for conditions
+ int operator!=(const token &); // ditto
+ unsigned char ch();
+ charinfo *get_char(int required = 0);
+ int add_to_node_list(node **);
+ int title();
+ void make_space();
+ void make_newline();
+ const char *description();
+
+ friend void process_input_stack();
+};
+
+extern token tok; // the current token
+
+extern symbol get_name(int required = 0);
+extern symbol get_long_name(int required = 0);
+extern charinfo *get_optional_char();
+extern void skip_line();
+extern void handle_initial_title();
+
+struct hunits;
+extern void read_title_parts(node **part, hunits *part_width);
+
+extern int get_number(units *result, unsigned char si);
+extern int get_integer(int *result);
+
+extern int get_number(units *result, unsigned char si, units prev_value);
+extern int get_integer(int *result, int prev_value);
+
+void interpolate_number_reg(symbol, int);
+
+const char *asciify(int c);
+
+inline int token::newline()
+{
+ return type == TOKEN_NEWLINE;
+}
+
+inline int token::space()
+{
+ return type == TOKEN_SPACE;
+}
+
+inline int token::nspaces()
+{
+ if (type == TOKEN_SPACE)
+ return 1;
+ else
+ return 0;
+}
+
+inline int token::white_space()
+{
+ return type == TOKEN_SPACE || type == TOKEN_TAB;
+}
+
+inline int token::transparent()
+{
+ return type == TOKEN_TRANSPARENT;
+}
+
+inline int token::page_ejector()
+{
+ return type == TOKEN_PAGE_EJECTOR;
+}
+
+inline unsigned char token::ch()
+{
+ return type == TOKEN_CHAR ? c : 0;
+}
+
+inline int token::eof()
+{
+ return type == TOKEN_EOF;
+}
+
+inline int token::dummy()
+{
+ return type == TOKEN_DUMMY;
+}
+
+inline int token::left_brace()
+{
+ return type == TOKEN_LEFT_BRACE;
+}
+
+inline int token::right_brace()
+{
+ return type == TOKEN_RIGHT_BRACE;
+}
+
+inline int token::tab()
+{
+ return type == TOKEN_TAB;
+}
+
+inline int token::leader()
+{
+ return type == TOKEN_LEADER;
+}
+
+inline int token::backspace()
+{
+ return type == TOKEN_BACKSPACE;
+}
+
+inline int token::hyphen_indicator()
+{
+ return type == TOKEN_HYPHEN_INDICATOR;
+}
+
+int has_arg();
diff --git a/gnu/usr.bin/groff/troff/troff.1 b/gnu/usr.bin/groff/troff/troff.1
new file mode 100644
index 000000000000..ebdcb2813829
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/troff.1
@@ -0,0 +1,2004 @@
+.\" -*- nroff -*-
+.\" define a string tx for the TeX logo
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH TROFF 1 "1 April 1993" "Groff Version 1.08"
+.SH NAME
+troff \- format documents
+.SH SYNOPSIS
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBtroff 'u
+.ti \niu
+.B troff
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-abivzCER
+.OP \-w name
+.OP \-W name
+.OP \-d cs
+.OP \-f fam
+.OP \-m name
+.OP \-n num
+.OP \-o list
+.OP \-r cn
+.OP \-T name
+.OP \-F dir
+.OP \-M dir
+.RI "[\ " files\|.\|.\|. "\ ]"
+.br
+.ad \na
+.SH DESCRIPTION
+This manual page describes the GNU version of
+.BR troff ,
+which is part of the groff document formatting system.
+It is highly compatible with Unix troff.
+Usually it should be invoked using the groff command, which will
+also run preprocessors and postprocessors in the appropriate
+order and with the appropriate options.
+.SH OPTIONS
+.TP \w'\-dname=s'u+2n
+.B \-a
+Generate an
+.SM ASCII
+approximation of the typeset output.
+.TP
+.B \-b
+Print a backtrace with each warning or error message. This backtrace
+should help track down the cause of the error. The line numbers given
+in the backtrace may not always correct: troff's idea of line numbers
+gets confused by
+.B as
+or
+.B am
+requests.
+.TP
+.B \-i
+Read the standard input after all the named input files have been
+processed.
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-w name
+Enable warning
+.IR name .
+Available warnings are described in
+the Warnings subsection below.
+Multiple
+.B \-w
+options are allowed.
+.TP
+.BI \-W name
+Inhibit warning
+.IR name .
+Multiple
+.B \-W
+options are allowed.
+.TP
+.B \-E
+Inhibit all error messages.
+.TP
+.B \-z
+Suppress formatted output.
+.TP
+.B \-C
+Enable compatibility mode.
+.TP
+.BI \-d cs
+.TQ
+.BI \-d name = s
+Define
+.I c
+or
+.I name
+to be a string
+.IR s ;
+.I c
+must be a one letter name.
+.TP
+.BI \-f fam
+Use
+.I fam
+as the default font family.
+.TP
+.BI \-m name
+Read in the file
+.BI tmac. name\fR.
+Normally this will be searched for in /usr/share/tmac.
+.TP
+.B \-R
+Don't load
+.BR troffrc .
+.TP
+.BI \-n num
+Number the first page
+.IR num .
+.TP
+.BI \-o list
+Output only pages in
+.IR list ,
+which is a comma-separated list of page ranges;
+.I n
+means print page
+.IR n ,
+.IB m \- n
+means print every page between
+.I m
+and
+.IR n ,
+.BI \- n
+means print every page up to
+.IR n ,
+.IB n \-
+means print every page from
+.IR n .
+.TP
+.BI \-r cn
+.TQ
+.BI \-r name = n
+Set number register
+.I c
+or
+.I name
+to
+.IR n ;
+.I c
+must be a one character name;
+.I n
+can be any troff numeric expression.
+.TP
+.BI \-T name
+Prepare output for device
+.IR name ,
+rather than the default
+.BR ps .
+.TP
+.BI \-F dir
+Search
+.I dir
+for subdirectories
+.BI dev name
+.RI ( name
+is the name of the device)
+for the
+.B DESC
+file and font files before the normal
+.BR /usr/share/groff_font .
+.TP
+.BI \-M dir
+Search directory
+.I dir
+for macro files before the normal
+.BR /usr/share/tmac .
+.SH USAGE
+Only the features not in Unix troff are described here.
+.SS Long names
+The names of number registers, fonts, strings/macros/diversions,
+special characters can be of any length. In escape sequences, where
+you can use
+.BI ( xx
+for a two character name, you can use
+.BI [ xxx ]
+for a name of arbitrary length:
+.TP
+.BI \e[ xxx ]
+Print the special character called
+.IR xxx .
+.TP
+.BI \ef[ xxx ]
+Set font
+.IR xxx .
+.TP
+.BI \e*[ xxx ]
+Interpolate string
+.IR xxx .
+.TP
+.BI \en[ xxx ]
+Interpolate number register
+.IR xxx .
+.SS Fractional pointsizes
+A
+.I
+scaled point
+is equal to 1/sizescale
+points, where
+sizescale is specified in the
+.B DESC
+file (1 by default.)
+There is a new scale indicator
+.B z
+which has the effect of multiplying by sizescale.
+Requests and escape sequences in troff
+interpret arguments that represent a pointsize as being in units
+of scaled points, but they evaluate each such argument
+using a default scale indicator of
+.BR z .
+Arguments treated in this way are
+the argument to the
+.B ps
+request,
+the third argument to the
+.B cs
+request,
+the second and fourth arguments to the
+.B tkf
+request,
+the argument to the
+.B \eH
+escape sequence,
+and those variants of the
+.B \es
+escape sequence that take a numeric expression as their argument.
+.LP
+For example, suppose sizescale is 1000;
+then a scaled point will be equivalent to a millipoint;
+the request
+.B .ps 10.25
+is equivalent to
+.B .ps 10.25z
+and so sets the pointsize to 10250 scaled points,
+which is equal to 10.25 points.
+.LP
+The number register
+.B \en(.s
+returns the pointsize in points as decimal fraction.
+There is also a new number register
+.B \en[.ps]
+that returns the pointsize in scaled points.
+.LP
+It would make no sense to use the
+.B z
+scale indicator in a numeric expression
+whose default scale indicator was neither
+.B u
+nor
+.BR z ,
+and so
+.B troff
+disallows this.
+Similarily it would make no sense to use a scaling indicator
+other than
+.B z
+or
+.B u
+in a numeric expression whose default scale indicator was
+.BR z ,
+and so
+.B troff
+disallows this as well.
+.LP
+There is also new scale indicator
+.B s
+which multiplies by the number of units in a scaled point.
+So, for example,
+.B \en[.ps]s
+is equal to
+.BR 1m .
+Be sure not to confuse the
+.B s
+and
+.B z
+scale indicators.
+.SS Numeric expressions
+.LP
+Spaces are permitted in a number expression within parentheses.
+.LP
+.B M
+indicates a scale of 100ths of an em.
+.TP
+.IB e1 >? e2
+The maximum of
+.I e1
+and
+.IR e2 .
+.TP
+.IB e1 <? e2
+The minimum of
+.I e1
+and
+.IR e2 .
+.TP
+.BI ( c ; e )
+Evaluate
+.I e
+using
+.I c
+as the default scaling indicator.
+If
+.I c
+is missing, ignore scaling indicators in the evaluation of
+.IR e .
+.SS New escape sequences
+.TP
+.BI \eA' anything '
+This expands to
+.B 1
+or
+.B 0
+according as
+.I anything
+is or is not acceptable as the name of a string, macro, diversion,
+number register, environment or font.
+It will return
+.B 0
+if
+.I anything
+is empty.
+This is useful if you want to lookup user input in some sort of
+associative table.
+.TP
+.BI \eC' xxx '
+Typeset character named
+.IR xxx .
+Normally it is more convenient to use
+.BI \e[ xxx ]\fR.
+But
+.B \eC
+has the advantage that it is compatible with recent versions of
+.SM UNIX
+and is available in compatibility mode.
+.TP
+.B \eE
+This is equivalent to an escape character,
+but it's not interpreted in copy-mode.
+For example, strings to start and end superscripting could be defined
+like this:
+.RS
+.IP
+\&.ds { \ev'\-.3m'\es'\eEn[.s]*6u/10u'
+.br
+\&.ds } \es0\ev'.3m'
+.LP
+The use of
+.B \eE
+ensures that these definitions will work even if
+.B \e*{
+gets interpreted in copy-mode
+(for example, by being used in a macro argument.)
+.RE
+.TP
+.BI \eN' n '
+Typeset the character with code
+.I n
+in the current font.
+.I n
+can be any integer.
+Most devices only have characters with codes between 0 and 255.
+If the current font does not contain a character with that code,
+special fonts will
+.I not
+be searched.
+The
+.B \eN
+escape sequence can be conveniently used on conjunction with the
+.B char
+request:
+.RS
+.IP
+.B
+\&.char \e[phone] \ef(ZD\eN'37'
+.RE
+.IP
+The code of each character is given in the fourth column in the font
+description file after the
+.B charset
+command.
+It is possible to include unnamed characters in the font description
+file by using a name of
+.BR \-\-\- ;
+the
+.B \eN
+escape sequence is the only way to use these.
+.TP
+.BI \eR' name\ \(+-n '
+This has the same effect as
+.RS
+.IP
+.BI .nr\ name\ \(+-n
+.RE
+.TP
+.BI \es( nn
+.TQ
+.BI \es\(+-( nn
+Set the point size to
+.I nn
+points;
+.I nn
+must be exactly two digits.
+.TP
+.BI \es[\(+- n ]
+.TQ
+.BI \es\(+-[ n ]
+.TQ
+.BI \es'\(+- n '
+.TQ
+.BI \es\(+-' n '
+Set the point size to
+.I n
+scaled points;
+.I n
+is a numeric expression with a default scale indicator of
+.BR z .
+.TP
+.BI \eV x
+.TQ
+.BI \eV( xx
+.TQ
+.BI \eV[ xxx ]
+Interpolate the contents of the environment variable
+.I xxx ,
+as returned by
+.BR getenv (3).
+.B \eV
+is interpreted in copy-mode.
+.TP
+.BI \eY x
+.TQ
+.BI \eY( xx
+.TQ
+.BI \eY[ xxx ]
+This is approximately equivalent to
+.BI \eX'\e*[ xxx ]'\fR.
+However the contents of the string or macro
+.I xxx
+are not interpreted;
+also it is permitted for
+.I xxx
+to have been defined as a macro and thus contain newlines
+(it is not permitted for the argument to
+.B \eX
+to contain newlines).
+The inclusion of newlines requires an extension to the Unix troff output
+format, and will confuse drivers that do not know about this
+extension.
+.TP
+.BI \eZ' anything '
+Print anything and then restore the horizontal and vertical
+position;
+.I anything
+may not contain tabs or leaders.
+.TP
+.B \e$0
+The name by which the current macro was invoked.
+The
+.B als
+request can make a macro have more than one name.
+.TP
+.B \e$*
+In a macro, the concatenation of all the arguments separated by spaces.
+.TP
+.B \e$@
+In a macro, the concatenation of all the arguments with each surrounded by
+double quotes, and separated by spaces.
+.TP
+.BI \e$( nn
+.TQ
+.BI \e$[ nnn ]
+In a macro, this gives the
+.IR nn -th
+or
+.IR nnn -th
+argument.
+Macros can have a unlimited number of arguments.
+.TP
+.BI \e? anything \e?
+When used in a diversion, this will transparently embed
+.I anything
+in the diversion.
+.I anything
+is read in copy mode.
+When the diversion is reread,
+.I anything
+will be interpreted.
+.I anything
+may not contain newlines; use
+.B \e!
+if you want to embed newlines in a diversion.
+The escape sequence
+.B \e?
+is also recognised in copy mode and turned into a single internal
+code; it is this code that terminates
+.IR anything .
+Thus
+.RS
+.RS
+.ft B
+.nf
+.ne 15
+\&.nr x 1
+\&.nf
+\&.di d
+\e?\e\e?\e\e\e\e?\e\e\e\e\e\e\e\enx\e\e\e\e?\e\e?\e?
+\&.di
+\&.nr x 2
+\&.di e
+\&.d
+\&.di
+\&.nr x 3
+\&.di f
+\&.e
+\&.di
+\&.nr x 4
+\&.f
+.fi
+.ft
+.RE
+.RE
+.IP
+will print
+.BR 4 .
+.TP
+.B \e/
+This increases the width of the preceding character so that
+the spacing between that character and the following character
+will be correct if the following character is a roman character.
+For example, if an italic f is immediately followed by a roman
+right parenthesis, then in many fonts the top right portion of the f
+will overlap the top left of the right parenthesis producing \fIf\fR)\fR,
+which is ugly.
+Inserting
+.B \e/
+produces
+.ie \n(.g \fIf\/\fR)\fR
+.el \fIf\|\fR)\fR
+and avoids this problem.
+It is a good idea to use this escape sequence whenever an
+italic character is immediately followed by a roman character without any
+intervening space.
+.TP
+.B \e,
+This modifies the spacing of the following character so that the spacing
+between that character and the preceding character will correct if
+the preceding character is a roman character.
+For example, inserting
+.B \e,
+between the parenthesis and the f changes
+\fR(\fIf\fR to
+.ie \n(.g \fR(\,\fIf\fR.
+.el \fR(\^\fIf\fR.
+It is a good idea to use this escape sequence whenever a
+roman character is immediately followed by an italic character without any
+intervening space.
+.TP
+.B \e)
+Like
+.B \e&
+except that it behaves like a character declared with the
+.B cflags
+request to be transparent for the purposes of end of sentence recognition.
+.TP
+.B \e~
+This produces an unbreakable space that stretches like a normal inter-word
+space when a line is adjusted.
+.TP
+.B \e#
+Everything up to and including the next newline is ignored.
+This is interpreted in copy mode.
+This is like
+.B \e%
+except that
+.B \e%
+does not ignore the terminating newline.
+.SS New requests
+.TP
+.BI .aln\ xx\ yy
+Create an alias
+.I xx
+for number register object named
+.IR yy .
+The new name and the old name will be exactly equivalent.
+If
+.I yy
+is undefined, a warning of type
+.B reg
+will be generated, and the request will be ignored.
+.TP
+.BI .als\ xx\ yy
+Create an alias
+.I xx
+for request, string, macro, or diversion object named
+.IR yy .
+The new name and the old name will be exactly equivalent (it is similar to a
+hard rather than a soft link).
+If
+.I yy
+is undefined, a warning of type
+.B mac
+will be generated, and the request will be ignored.
+The
+.BR de ,
+.BR am ,
+.BR di ,
+.BR da ,
+.BR ds ,
+and
+.B as
+requests only create a new object if the name of the macro, diversion
+or string diversion is currently undefined or if it is defined to be a
+request; normally they modify the value of an existing object.
+.TP
+.BI .asciify\ xx
+This request only exists in order to make it possible
+to make certain gross hacks work with GNU troff.
+It `unformats' the diversion
+.I xx
+in such a way that
+.SM ASCII
+characters that were formatted and diverted into
+.I xx
+will be treated like ordinary input characters when
+.I xx
+is reread.
+For example, this
+.RS
+.IP
+.ne 7v+\n(.Vu
+.ft B
+.nf
+.ss 24
+\&.tr @.
+\&.di x
+\&@nr\e n\e 1
+\&.br
+\&.di
+\&.tr @@
+\&.asciify x
+\&.x
+.ss 12
+.fi
+.RE
+.IP
+will set register
+.B n
+to 1.
+.TP
+.B .backtrace
+Print a backtrace of the input stack on stderr.
+.TP
+.B .break
+Break out of a while loop.
+See also the
+.B while
+and
+.B continue
+requests.
+Be sure not to confuse this with the
+.B br
+request.
+.TP
+.BI .cflags\ n\ c1\ c2\|.\|.\|.
+Characters
+.IR c1 ,
+.IR c2 ,\|.\|.\|.
+have properties determined by
+.IR n ,
+which is ORed from the following:
+.RS
+.TP
+1
+the character ends sentences
+(initially characters
+.B .?!
+have this property);
+.TP
+2
+lines can be broken before the character
+(initially no characters have this property);
+.TP
+4
+lines can be broken after the character
+(initially characters
+.B \-\e(hy\e(em
+have this property);
+.TP
+8
+the character overlaps horizontally
+(initially characters
+.B \e(ul\e(rn\e(ru
+have this property);
+.TP
+16
+the character overlaps vertically
+(initially character
+.B \e(br
+has this property);
+.TP
+32
+an end of sentence character followed by any number of characters
+with this property will be treated
+as the end of a sentence if followed by a newline or two spaces;
+in other words
+the character is transparent for the purposes of end of sentence
+recognition;
+this is the same as having a zero space factor in \*(tx
+(initially characters
+.B \(ts')]*\e(dg\e(rq
+have this property).
+.RE
+.TP
+.BI .char\ c\ string
+Define character
+.I c
+to be
+.IR string .
+Every time character
+.I c
+needs to be printed,
+.I string
+will be processed in a temporary environment and the result
+will be wrapped up into a single object.
+Compatibility mode will be turned off
+and the escape character will be set to
+.B \e
+while
+.I string
+is being processed.
+Any emboldening, constant spacing or track kerning will be applied
+to this object rather than to individual characters in
+.IR string .
+A character defined by this request can be used just like
+a normal character provided by the output device.
+In particular other characters can be translated to it
+with the
+.B tr
+request;
+it can be made the leader character by the
+.B lc
+request;
+repeated patterns can be drawn with the character using the
+.B \el
+and
+.B \eL
+escape sequences;
+words containing the character can be hyphenated
+correctly, if the
+.B hcode
+request is used to give the character a hyphenation code.
+There is a special anti-recursion feature:
+use of character within the character's definition
+will be handled like normal characters not defined with
+.BR char .
+A character definition can be removed with the
+.B rchar
+request.
+.TP
+.BI .chop\ xx
+Chop the last character off macro, string, or diversion
+.IR xx .
+This is useful for removing the newline from the end of diversions
+that are to be interpolated as strings.
+.TP
+.BI .close\ stream
+Close the stream named
+.IR stream ;
+.I stream
+will no longer be an acceptable argument to the
+.B write
+request.
+See the
+.B open
+request.
+.TP
+.B .continue
+Finish the current iteration of a while loop.
+See also the
+.B while
+and
+.B break
+requests.
+.TP
+.BI .cp\ n
+If
+.I n
+is non-zero or missing, enable compatibility mode, otherwise
+disable it.
+In compatibility mode, long names are not recognised, and the
+incompatibilities caused by long names do not arise.
+.TP
+.BI .do\ xxx
+Interpret
+.I .xxx
+with compatibility mode disabled.
+For example,
+.RS
+.IP
+.B
+\&.do fam T
+.LP
+would have the same effect as
+.IP
+.B
+\&.fam T
+.LP
+except that it would work even if compatibility mode had been enabled.
+Note that the previous compatibility mode is restored before any files
+sourced by
+.I xxx
+are interpreted.
+.RE
+.TP
+.BI .fam\ xx
+Set the current font family to
+.IR xx .
+The current font family is part of the current environment.
+See the description of the
+.B sty
+request for more information on font families.
+.TP
+.BI .fspecial\ f\ s1\ s2\|.\|.\|.
+When the current font is
+.IR f ,
+fonts
+.IR s1 ,
+.IR s2 ,\|.\|.\|.
+will be special, that is, they will searched for characters not in
+the current font.
+Any fonts specified in the
+.B special
+request will be searched before fonts specified in the
+.B fspecial
+request.
+.TP
+.BI .ftr\ f\ g
+Translate font
+.I f
+to
+.IR g .
+Whenever a font named
+.I f
+is referred to in
+.B \ef
+escape sequence,
+or in the
+.BR ft ,
+.BR ul ,
+.BR bd ,
+.BR cs ,
+.BR tkf ,
+.BR special ,
+.BR fspecial ,
+.BR fp ,
+or
+.BR sty
+requests,
+font
+.I g
+will be used.
+If
+.I g
+is missing,
+or equal to
+.I f
+then font
+.I f
+will not be translated.
+.TP
+.BI .hcode \ c1\ code1\ c2\ code2\|.\|.\|.
+Set the hyphenation code of character
+.I c1
+to
+.I code1
+and that of
+.I c2
+to
+.IR code2 .
+A hyphenation code must be a single input
+character (not a special character) other than a digit or a space.
+Initially each lower-case letter has a hyphenation code, which
+is itself, and each upper-case letter has a hyphenation code
+which is the lower case version of itself.
+See also the
+.B hpf
+request.
+.TP
+.BI .hla\ lang
+Set the current hyphenation language to
+.IR lang .
+Hyphenation exceptions specified with the
+.B hw
+request and hyphenation patterns specified with the
+.B hpf
+request are both associated with the current hyphenation language.
+The
+.B hla
+request is usually invoked by the
+.B troffrc
+file.
+.TP
+.BI .hlm\ n
+Set the maximum number of consecutive hyphenated lines to
+.IR n .
+If
+.I n
+is negative, there is no maximum.
+The default value is \-1.
+This value is associated with the current environment.
+Only lines output from an environment count towards the maximum associated
+with that environment.
+Hyphens resulting from
+.B \e%
+are counted; explicit hyphens are not.
+.TP
+.BI .hpf\ file
+Read hyphenation patterns from
+.IR file ;
+this will be searched for in the same way that
+.BI tmac. name
+is searched for when the
+.BI \-m name
+option is specified.
+It should have the same format as the argument to
+the \epatterns primitive in \*(tx;
+the letters appearing in this file are interpreted as hyphenation
+codes.
+A
+.B %
+character in the patterns file introduces a comment that continues
+to the end of the line.
+The set of hyphenation patterns is associated with the current language
+set by the
+.B hla
+request.
+The
+.B hpf
+request
+is usually invoked by the
+.B troffrc
+file.
+.TP
+.BI .hym\ n
+Set the
+.I hyphenation margin
+to
+.IR n :
+when the current adjustment mode is not
+.BR b ,
+the line will not be hyphenated if the line is no more than
+.I n
+short.
+The default hyphenation margin is 0.
+The default scaling indicator for this request is
+.IR m .
+The hyphenation margin is associated with the current environment.
+The current hyphenation margin is available in the
+.B \en[.hym]
+register.
+.TP
+.BI .hys\ n
+Set the
+.I hyphenation space
+to
+.IR n :
+when the current adjustment mode is
+.B b
+don't hyphenate the line if the line can be justified by adding no more than
+.I n
+extra space to each word space.
+The default hyphenation space is 0.
+The default scaling indicator for this request is
+.BR m .
+The hyphenation space is associated with the current environment.
+The current hyphenation space is available in the
+.B \en[.hys]
+register.
+.TP
+.BI .kern\ n
+If
+.I n
+is non-zero or missing, enable pairwise kerning, otherwise disable it.
+.TP
+.BI .mso\ file
+The same as the
+.B so
+request except that
+.I file
+is searched for in the same way that
+.BI tmac. name
+is searched for when the
+.BI \-m name
+option is specified.
+.TP
+.B .nroff
+Make the
+.B n
+built-in condition true
+and the
+.B t
+built-in condition false.
+This can be reversed using the
+.B troff
+request.
+.TP
+.BI .open\ stream\ filename
+Open
+.I filename
+for writing and associate the stream named
+.I stream
+with it.
+See also the
+.B close
+and
+.B write
+requests.
+.TP
+.BI .opena\ stream\ filename
+Like
+.BR open ,
+but if
+.I filename
+exists, append to it instead of truncating it.
+.TP
+.B .pnr
+Print the names and contents of all currently defined number registers
+on stderr.
+.TP
+.B .ptr
+Print the names and positions of all traps (not including input line
+traps and diversion traps) on stderr. Empty slots in the page trap
+list are printed as well, because they can affect the priority of
+subsequently planted traps.
+.TP
+.BI .rchar\ c1\ c2\|.\|.\|.
+Remove the definitions of characters
+.IR c1 ,
+.IR c2 ,\|.\|.\|.
+This undoes the effect of a
+.B char
+request.
+.TP
+.B .rj
+.TQ
+.BI .rj\ n
+Right justify the next
+.I n
+input lines.
+Without an argument right justify the next input line.
+The number of lines to be right justifed is available in the
+.B \en[.rj]
+register.
+This implicitly does
+.BR .ce\ 0 .
+The
+.B ce
+request implicitly does
+.BR .rj\ 0 .
+.TP
+.BI .rnn \ xx\ yy
+Rename number register
+.I xx
+to
+.IR yy .
+.TP
+.BI .shc\ c
+Set the soft hyphen character to
+.IR c .
+If
+.I c
+is omitted,
+the soft hyphen character will be set to the default
+.BR \e(hy .
+The soft hyphen character is the character which will be inserted
+when a word is hyphenated at a line break.
+If the soft hyphen character does not exist in the font of the character
+immediately preceding a potential break point,
+then the line will not be broken at that point.
+Neither definitions (specified with the
+.B char
+request)
+nor translations (specified with the
+.B tr
+request)
+are considered when finding the soft hyphen character.
+.TP
+.BI .shift\ n
+In a macro, shift the arguments by
+.I n
+positions:
+argument
+.I i
+becomes argument
+.IR i \- n ;
+arguments 1 to
+.I n
+will no longer be available.
+If
+.I n
+is missing,
+arguments will be shifted by 1.
+Shifting by negative amounts is currently undefined.
+.TP
+.BI .special\ s1\ s2\|.\|.\|.
+Fonts
+.IR s1 ,
+.IR s2 ,
+are special and will be searched for characters not in the
+current font.
+.TP
+.BI .sty\ n\ f
+Associate style
+.I f
+with font position
+.IR n .
+A font position can be associated either with a font or
+with a style.
+The current font is the index of a font position and so is also
+either a font or a style.
+When it is a style, the font that is actually used is the font the
+name of which is the concatenation of the name of the current family
+and the name of the current style.
+For example, if the current font is 1 and font position 1 is
+associated with style
+.B R
+and the current
+font family is
+.BR T ,
+then font
+.BR TR
+will be used.
+If the current font is not a style, then the current family is ignored.
+When the requests
+.BR cs ,
+.BR bd ,
+.BR tkf ,
+.BR uf ,
+or
+.B fspecial
+are applied to a style,
+then they will instead be applied to the member of the
+current family corresponding to that style.
+The default family can be set with the
+.B \-f
+option.
+The styles command in the
+.SM DESC
+file controls which font positions
+(if any) are initially associated with styles rather than fonts.
+.TP
+.BI .tkf\ f\ s1\ n1\ s2\ n2
+Enable track kerning for font
+.IR f .
+When the current font is
+.I f
+the width of every character will be increased by an amount
+between
+.I n1
+and
+.IR n2 ;
+when the current point size is less than or equal to
+.I s1
+the width will be increased by
+.IR n1 ;
+when it is greater than or equal to
+.I s2
+the width will be increased by
+.IR n2 ;
+when the point size is greater than or equal to
+.I s1
+and less than or equal to
+.I s2
+the increase in width is a linear function of the point size.
+.TP
+.BI .trf\ filename
+Transparently output the contents of file
+.IR filename .
+Each line is output as it would be were it preceded by
+.BR \e! ;
+however, the lines are not subject to copy-mode interpretation.
+If the file does not end with a newline, then a newline will
+be added.
+For example, you can define a macro
+.I x
+containing the contents of file
+.IR f ,
+using
+.RS
+.IP
+.BI .di\ x
+.br
+.BI .trf\ f
+.br
+.B .di
+.LP
+Unlike with the
+.B cf
+request,
+the file cannot contain characters such as
+.SM NUL
+that are not legal troff input characters.
+.RE
+.TP
+.B .trnt abcd
+This is the same as the
+.B tr
+request except that the translations do not apply to text that is
+transparently throughput into a diversion with
+.BR \e! .
+For example,
+.RS
+.LP
+.nf
+.ft B
+\&.tr ab
+\&.di x
+\e!.tm a
+\&.di
+\&.x
+.fi
+.ft
+.LP
+will print
+.BR b ;
+if
+.B trnt
+is used instead of
+.B tr
+it will print
+.BR a .
+.RE
+.TP
+.B .troff
+Make the
+.B n
+built-in condition false,
+and the
+.B t
+built-in condition true.
+This undoes the effect of the
+.B nroff
+request.
+.TP
+.BI .vpt\ n
+Enable vertical position traps if
+.I n
+is non-zero, disable them otherwise.
+Vertical position traps are traps set by the
+.B wh
+or
+.B dt
+requests.
+Traps set by the
+.B it
+request are not vertical position traps.
+The parameter that controls whether vertical position traps are enabled
+is global.
+Initially vertical position traps are enabled.
+.TP
+.BI .warn\ n
+Control warnings.
+.I n
+is the sum of the numbers associated with each warning that is to be enabled;
+all other warnings will be disabled.
+The number associated with each warning is listed in the `Warnings' section.
+For example,
+.B .warn 0
+will disable all warnings, and
+.B .warn 1
+will disable all warnings except that about missing characters.
+If
+.I n
+is not given,
+all warnings will be enabled.
+.TP
+.BI .while \ c\ anything
+While condition
+.I c
+is true, accept
+.I anything
+as input;
+.I c
+can be any condition acceptable to an
+.B if
+request;
+.I anything
+can comprise multiple lines if the first line starts with
+.B \e{
+and the last line ends with
+.BR \e} .
+See also the
+.B break
+and
+.B continue
+requests.
+.TP
+.BI .write\ stream\ anything
+Write
+.I anything
+to the stream named
+.IR stream .
+.I stream
+must previously have been the subject of an
+.B open
+request.
+.I anything
+is read in copy mode;
+a leading
+.B \(ts
+will be stripped.
+.SS Extended requests
+.TP
+.BI .cf\ filename
+When used in a diversion, this will embed in the diversion an object which,
+when reread, will cause the contents of
+.I filename
+to be transparently copied through to the output.
+In Unix troff, the
+contents of
+.I filename
+is immediately copied through to the output regardless of whether
+there is a current diversion; this behavior is so anomalous that it
+must be considered a bug.
+.TP
+.BI .ev\ xx
+If
+.I xx
+is not a number, this will switch to a named environment called
+.IR xx .
+The environment should be popped with a matching
+.B ev
+request without any arguments, just as for numbered environments.
+There is no limit on the number of named environments; they will be
+created the first time that they are referenced.
+.TP
+.BI .fp\ n\ f1\ f2
+The
+.B fp
+request has an optional third argument.
+This argument gives the external name of the font,
+which is used for finding the font description file.
+The second argument gives the internal name of the font
+which is used to refer to the font in troff after it has been mounted.
+If there is no third argument then the internal name will be used
+as the external name.
+This feature allows you to use fonts with long names in compatibility mode.
+.TP
+.BI .ss\ m\ n
+When two arguments are given to the
+.B ss
+request, the second argument gives the
+.IR "sentence space size" .
+If the second argument is not given, the sentence space size
+will be the same as the word space size.
+Like the word space size, the sentence space is in units of
+one twelfth of the spacewidth parameter for the current font.
+Initially both the word space size and the sentence
+space size are 12.
+The sentence space size is used in two circumstances:
+if the end of a sentence occurs at the end of a line in fill mode, then
+both an inter-word space and a sentence space will be added;
+if two spaces follow the end of a sentence in the middle of a line,
+then the second space will be a sentence space.
+Note that the behavior of Unix troff will be exactly
+that exhibited by GNU troff if a second argument is never given to the
+.B ss
+request.
+In GNU troff, as in Unix troff, you should always
+follow a sentence with either a newline or two spaces.
+.TP
+.BI .ta\ n1\ n2\|.\|.\|.nn \ T\ r1\ r2\|.\|.\|.\|rn
+Set tabs at positions
+.IR n1 ,
+.IR n2 ,\|.\|.\|.\|,
+.I nn
+and then set tabs at
+.IR nn + r1 ,
+.IR nn + r2 ,\|.\|.\|.\|.\|,
+.IR nn + rn
+and then at
+.IR nn + rn + r1 ,
+.IR nn + rn + r2 ,\|.\|.\|.\|,
+.IR nn + rn + rn ,
+and so on.
+For example,
+.RS
+.IP
+.B
+\&.ta T .5i
+.LP
+will set tabs every half an inch.
+.RE
+.SS New number registers
+The following read-only registers are available:
+.TP
+.B \en[.C]
+1 if compatibility mode is in effect, 0 otherwise.
+.TP
+.B \en[.cdp]
+The depth of the last character added to the current environment.
+It is positive if the character extends below the baseline.
+.TP
+.B \en[.ce]
+The number of lines remaining to be centered, as set by the
+.B ce
+request.
+.TP
+.B \en[.cht]
+The height of the last character added to the current environment.
+It is positive if the character extends above the baseline.
+.TP
+.B \en[.csk]
+The skew of the last character added to the current environment.
+The
+.I skew
+of a character is how far to the right of the center of a character
+the center of an accent over that character should be placed.
+.TP
+.B \en[.ev]
+The name or number of the current environment.
+This is a string-valued register.
+.TP
+.B \en[.fam]
+The current font family.
+This is a string-valued register.
+.TP
+.B \en[.fp]
+The number of the next free font position.
+.TP
+.B \en[.g]
+Always 1.
+Macros should use this to determine whether they are running
+under GNU troff.
+.TP
+.B \en[.hla]
+The current hyphenation language as set by the
+.B hla
+request.
+.TP
+.B \en[.hlc]
+The number of immediately preceding consecutive hyphenated lines.
+.TP
+.B \en[.hlm]
+The maximum allowed number of consecutive hyphenated lines, as set by the
+.B hlm
+request.
+.TP
+.B \en[.hy]
+The current hyphenation flags (as set by the
+.B hy
+request.)
+.TP
+.B \en[.hym]
+The current hyphenation margin (as set by the
+.B hym
+request.)
+.TP
+.B \en[.hys]
+The current hyphenation space (as set by the
+.B hys
+request.)
+.TP
+.B \en[.in]
+The indent that applies to the current output line.
+.TP
+.B \en[.kern]
+.B 1
+if pairwise kerning is enabled,
+.B 0
+otherwise.
+.TP
+.B \en[.lg]
+The current ligature mode (as set by the
+.B lg
+request.)
+.TP
+.B \en[.ll]
+The line length that applies to the current output line.
+.TP
+.B \en[.lt]
+The title length as set by the
+.B lt
+request.
+.TP
+.B \en[.ne]
+The amount of space that was needed in the last
+.B ne
+request that caused a trap to be sprung.
+Useful in conjunction with the
+.B \en[.trunc]
+register.
+.TP
+.B \en[.pn]
+The number of the next page:
+either the value set by a
+.B pn
+request, or the number of the current page plus 1.
+.TP
+.B \en[.ps]
+The current pointsize in scaled points.
+.TP
+.B \en[.psr]
+The last-requested pointsize in scaled points.
+.TP
+.B \en[.rj]
+The number of lines to be right-justified as set by the
+.B rj
+request.
+.TP
+.B \en[.sr]
+The last requested pointsize in points as a decimal fraction.
+This is a string-valued register.
+.TP
+.B \en[.tabs]
+A string representation of the current tab settings suitable for use as
+an argument to the
+.B ta
+request.
+.TP
+.B \en[.trunc]
+The amount of vertical space truncated by the most recently sprung
+vertical position trap, or,
+if the trap was sprung by a
+.B ne
+request,
+minus the amount of vertical motion produced by the
+.B ne
+request.
+In other words, at the point a trap is sprung, it represents the difference
+of what the vertical position would have been but for the trap,
+and what the vertical position actually is.
+Useful in conjunction with the
+.B \en[.ne]
+register.
+.TP
+.B \en[.ss]
+.TQ
+.B \en[.sss]
+These give the values of the parameters set by the
+first and second arguments of the
+.B ss
+request.
+.TP
+.B \en[.vpt]
+1 if vertical position traps are enabled, 0 otherwise.
+.TP
+.B \en[.warn]
+The sum of the numbers associated with each of the currently enabled
+warnings.
+The number associated with each warning is listed in the `Warnings'
+subsection.
+.TP
+.B \en(.x
+The major version number.
+For example, if the version number is
+.B 1.03
+then
+.B \en(.x
+will contain
+.BR 1 .
+.TP
+.B \en(.y
+The minor version number.
+For example, if the version number is
+.B 1.03
+then
+.B \en(.y
+will contain
+.BR 03 .
+.LP
+The following registers are set by the
+.B \ew
+escape sequence:
+.TP
+.B \en[rst]
+.TQ
+.B \en[rsb]
+Like the
+.B st
+and
+.B sb
+registers, but takes account of the heights and depths of characters.
+.TP
+.B \en[ssc]
+The amount of horizontal space (possibly negative) that should
+be added to the last character before a subscript.
+.TP
+.B \en[skw]
+How far to right of the center of the last character
+in the
+.B \ew
+argument,
+the center of an accent from a roman font should be placed over that character.
+.LP
+The following read/write number registers are available:
+.TP
+.B \en[systat]
+The return value of the system() function executed by the last
+.B sy
+request.
+.TP
+.B \en[slimit]
+If greater than 0, the maximum number of objects on the input stack.
+If less than or equal to 0, there is no limit on the number of objects
+on the input stack. With no limit, recursion can continue until
+virtual memory is exhausted.
+.SS Miscellaneous
+.LP
+Fonts not listed in the
+.SM DESC
+file are automatically mounted on the next available font position
+when they are referenced.
+If a font is to be mounted explicitly with the
+.B fp
+request on an unused font position,
+it should be mounted on the first unused font position,
+which can be found in the
+.B \en[.fp]
+register;
+although
+.B troff
+does not enforce this strictly,
+it will not allow a font to be mounted at a position whose number is much
+greater than that of any currently used position.
+.LP
+Interpolating a string does not hide existing macro arguments.
+Thus in a macro, a more efficient way of doing
+.IP
+.BI . xx\ \e\e$@
+.LP
+is
+.IP
+.BI \e\e*[ xx ]\e\e
+.LP
+If the font description file contains pairwise kerning information,
+characters from that font will be kerned.
+Kerning between two characters can be inhibited by placing a
+.B \e&
+between them.
+.LP
+In a string comparison in a condition,
+characters that appear at different input levels
+to the first delimiter character will not be recognised
+as the second or third delimiters.
+This applies also to the
+.B tl
+request.
+In a
+.B \ew
+escape sequence,
+a character that appears at a different input level to
+the starting delimiter character will not be recognised
+as the closing delimiter character.
+When decoding a macro argument that is delimited
+by double quotes, a character that appears at a different
+input level to the starting delimiter character will not
+be recognised as the closing delimiter character.
+The implementation of
+.B \e$@
+ensures that the double quotes surrounding an argument
+will appear the same input level, which will be different
+to the input level of the argument itself.
+In a long escape name
+.B ]
+will not be recognized as a closing delimiter except
+when it occurs at the same input level as the opening
+.BR ] .
+In compatibility mode, no attention is paid to the input-level.
+.LP
+There are some new types of condition:
+.TP
+.BI .if\ r xxx
+True if there is a number register named
+.IR xxx .
+.TP
+.BI .if\ d xxx
+True if there is a string, macro, diversion, or request named
+.IR xxx .
+.TP
+.BI .if\ c ch
+True if there is a character
+.IR ch
+available;
+.I ch
+is either an
+.SM ASCII
+character
+or a special character
+.BI \e( xx
+or
+.BI \e[ xxx ]\fR;
+the condition will also be true if
+.I ch
+has been defined by the
+.B char
+request.
+.SS Warnings
+The warnings that can be given by
+.B troff
+are divided into the following categories.
+The name associated with each warning is used by the
+.B \-w
+and
+.B \-W
+options;
+the number is used by the
+.B warn
+request, and by the
+.B .warn
+register.
+.nr x \w'\fBright-brace'+1n+\w'0000'u
+.ta \nxuR
+.TP \nxu+3n
+.BR char \t1
+Non-existent characters.
+This is enabled by default.
+.TP
+.BR number \t2
+Invalid numeric expressions.
+This is enabled by default.
+.TP
+.BR break \t4
+In fill mode, lines which could not be broken so that their length was
+less than the line length.
+This is enabled by default.
+.TP
+.BR delim \t8
+Missing or mismatched closing delimiters.
+.TP
+.BR el \t16
+Use of the
+.B el
+request with no matching
+.B ie
+request.
+.TP
+.BR scale \t32
+Meaningless scaling indicators.
+.TP
+.BR range \t64
+Out of range arguments.
+.TP
+.BR syntax \t128
+Dubious syntax in numeric expressions.
+.TP
+.BR di \t256
+Use of
+.B di
+or
+.B da
+without an argument when there is no current diversion.
+.TP
+.BR mac \t512
+Use of undefined strings, macros and diversions.
+When an undefined string, macro or diversion is used,
+that string is automatically defined as empty.
+So, in most cases, at most one warning will be given for
+each name.
+.TP
+.BR reg \t1024
+Use of undefined number registers.
+When an undefined number register is used,
+that register is automatically defined to have a value of 0.
+a definition is automatically made with a value of 0.
+So, in most cases, at most one warning will be given for
+use of a particular name.
+.TP
+.BR tab \t2048
+Use of a tab character where a number was expected.
+.TP
+.BR right-brace \t4096
+Use of
+.B \e}
+where a number was expected.
+.TP
+.BR missing \t8192
+Requests that are missing non-optional arguments.
+.TP
+.BR input \t16384
+Illegal input characters.
+.TP
+.BR escape \t32768
+Unrecognized escape sequences.
+When an unrecognized escape sequence is encountered,
+the escape character is ignored.
+.TP
+.BR space \t65536
+Missing space between a request or macro and its argument.
+This warning will be given
+when an undefined name longer than two characters is encountered,
+and the first two characters of the name make a defined name.
+The request or macro will not be invoked.
+When this warning is given, no macro is automatically defined.
+This is enabled by default.
+This warning will never occur in compatibility mode.
+.TP
+.BR font \t131072
+Non-existent fonts.
+This is enabled by default.
+.LP
+There are also names that can be used to refer to groups of warnings:
+.TP
+.B all
+All warnings except
+.BR di ,
+.B mac
+and
+.BR reg .
+It is intended that this covers all warnings
+that are useful with traditional macro packages.
+.TP
+.B w
+All warnings.
+.SS Incompatibilities
+.LP
+Long names cause some incompatibilities.
+Unix troff will interpret
+.IP
+.B
+\&.dsabcd
+.LP
+as defining a string
+.B ab
+with contents
+.BR cd .
+Normally, GNU troff will interpret this as a call of a macro named
+.BR dsabcd .
+Also Unix troff will interpret
+.B \e*[
+or
+.B \en[
+as references to a string or number register called
+.BR [ .
+In GNU troff, however, this will normally be interpreted as the start
+of a long name.
+In
+.I compatibility mode
+GNU troff will interpret these things in the traditional way.
+In compatibility mode, however, long names are not recognised.
+Compatibility mode can be turned on with the
+.B \-C
+command line option, and turned on or off with the
+.B cp
+request.
+The number register
+.B \en(.C
+is 1 if compatibility mode is on, 0 otherwise.
+.LP
+GNU troff
+does not allow the use of the escape sequences
+.BR \\e\e|\e^\e&\e}\e{\e (space) \e'\e`\e-\e_\e!\e%\ec
+in names of strings, macros, diversions, number registers,
+fonts or environments; Unix troff does.
+The
+.B \eA
+escape sequence may be helpful in avoiding use of these
+escape sequences in names.
+.LP
+Fractional pointsizes cause one noteworthy incompatibility.
+In Unix troff the
+.B ps
+request ignores scale indicators and so
+.IP
+.B .ps\ 10u
+.LP
+will set the pointsize to 10 points, whereas in
+GNU troff it will set the pointsize to 10 scaled points.
+.LP
+In GNU troff there is a fundamental difference between unformatted,
+input characters, and formatted, output characters.
+Everything that affects how an output character
+will be output is stored with the character; once an output
+character has been constructed it is unaffected by any subsequent
+requests that are executed, including
+.BR bd ,
+.BR cs ,
+.BR tkf ,
+.BR tr ,
+or
+.B fp
+requests.
+Normally output characters are constructed from input
+characters at the moment immediately before the character
+is added to the current output line.
+Macros, diversions and strings are all, in fact, the same type
+of object; they contain lists of input characters and output
+characters in any combination.
+An output character does not behave like an input character
+for the purposes of macro processing; it does not inherit any
+of the special properties that the input character from which it
+was constructed might have had.
+For example,
+.IP
+.nf
+.ft B
+\&.di x
+\e\e\e\e
+\&.br
+\&.di
+\&.x
+.ft
+.fi
+.LP
+will print
+.B \e\e
+in GNU troff;
+each pair of input
+.BR \e s
+is turned into one output
+.B \e
+and the resulting output
+.BR \e s
+are not interpreted as escape characters when they are reread.
+Unix troff would interpret them as escape characters
+when they were reread and would end up printing one
+.BR \e .
+The correct way to obtain a printable
+.B \e
+is to use the
+.B \ee
+escape sequence: this will always print a single instance of the
+current escape character, regardless of whether or not it is used in a
+diversion; it will also work in both GNU troff and Unix troff.
+If you wish for some reason to store in a diversion an escape
+sequence that will be interpreted when the diversion is reread,
+you can either use the traditional
+.B \e!
+transparent output facility, or, if this is unsuitable, the new
+.B \e?
+escape sequence.
+.SH ENVIRONMENT
+.TP
+.SM
+.B GROFF_TMAC_PATH
+A colon separated list of directories in which to search for
+macro files.
+.TP
+.SM
+.B GROFF_TYPESETTER
+Default device.
+.TP
+.SM
+.B GROFF_FONT_PATH
+A colon separated list of directories in which to search for the
+.BI dev name
+directory.
+.B troff
+will search in directories given in the
+.B \-F
+option before these, and in standard directories
+.RB ( /usr/share/groff_font )
+after these.
+.SH FILES
+.Tp \w'/usr/share/groff_font/devname/DESC'u+3n
+.B /usr/share/tmac/troffrc
+Initialization file
+.TP
+.BI /usr/share/tmac/tmac. name
+Macro files
+.TP
+.BI /usr/share/groff_font/dev name /DESC
+Device description file for device
+.IR name .
+.TP
+.BI /usr/share/groff_font/dev name / F
+Font file for font
+.I F
+of device
+.IR name .
+.SH "SEE ALSO"
+.BR groff (1)
+.BR tbl (1),
+.BR pic (1),
+.BR eqn (1),
+.BR grops (1),
+.BR grodvi (1),
+.BR grotty (1),
+.BR groff_font (5),
+.BR groff_out (5),
+.BR groff_char (7)
diff --git a/gnu/usr.bin/groff/troff/troff.h b/gnu/usr.bin/groff/troff/troff.h
new file mode 100644
index 000000000000..854386041fe9
--- /dev/null
+++ b/gnu/usr.bin/groff/troff/troff.h
@@ -0,0 +1,86 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute 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.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "lib.h"
+#include "assert.h"
+#include "device.h"
+
+#ifdef __GNUG__
+#define NO_RETURN volatile
+#else
+#define NO_RETURN
+#endif
+
+typedef int units;
+
+extern units scale(units n, units x, units y); // scale n by x/y
+
+extern units units_per_inch;
+
+extern int ascii_output_flag;
+extern int suppress_output_flag;
+
+extern int tcommand_flag;
+extern int vresolution;
+extern int hresolution;
+extern int sizescale;
+
+#include "cset.h"
+#include "cmap.h"
+#include "errarg.h"
+#include "error.h"
+
+enum warning_type {
+ WARN_CHAR = 01,
+ WARN_NUMBER = 02,
+ WARN_BREAK = 04,
+ WARN_DELIM = 010,
+ WARN_EL = 020,
+ WARN_SCALE = 040,
+ WARN_RANGE = 0100,
+ WARN_SYNTAX = 0200,
+ WARN_DI = 0400,
+ WARN_MAC = 01000,
+ WARN_REG = 02000,
+ WARN_TAB = 04000,
+ WARN_RIGHT_BRACE = 010000,
+ WARN_MISSING = 020000,
+ WARN_INPUT = 040000,
+ WARN_ESCAPE = 0100000,
+ WARN_SPACE = 0200000,
+ WARN_FONT = 0400000
+ // change WARN_TOTAL if you add more warning types
+};
+
+const int WARN_TOTAL = 0777777;
+
+int warning(warning_type, const char *,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg);
diff --git a/gnu/usr.bin/groff/xditview/ChangeLog b/gnu/usr.bin/groff/xditview/ChangeLog
new file mode 100644
index 000000000000..880201cc4e34
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/ChangeLog
@@ -0,0 +1,259 @@
+Tue Mar 30 15:12:09 1993 James Clark (jjc at jclark)
+
+ * draw.c (charExists): Check that fi->per_char is not NULL.
+
+Sat Dec 12 17:42:40 1992 James Clark (jjc at jclark)
+
+ * Dvi.c (SetGeometry): Cast XtMakeGeometryRequest arguments.
+
+ * draw.c (DrawPolygon, DrawFilledPolygon): Cast Xtfree argument.
+
+ * font.c (DisposeFontSizes): Add declaration.
+
+ * draw.c (FakeCharacter): Add declaration.
+
+Wed Oct 28 13:24:00 1992 James Clark (jjc at jclark)
+
+ * Imakefile (install.dev): Deleted.
+ (fonts): New target.
+
+Mon Oct 12 10:50:44 1992 James Clark (jjc at jclark)
+
+ * Imakefile (install.dev): Say when we're installing devX*-12.
+
+ * Imakefile (install.dev): Depends on DESC and FontMap.
+
+Thu Oct 1 20:03:45 1992 James Clark (jjc at jclark)
+
+ * xditview.c (Syntax): Mention -filename option.
+
+Sat Aug 15 12:56:39 1992 James Clark (jjc at jclark)
+
+ * GXditview.ad: Bind space and return to NextPage. Bind backspace
+ and delete to previous page.
+
+ * DviChar.c (Adobe_Symbol_map): Add `an'.
+
+ * DviChar.c (Adobe_Symbol_map): Add arrowvertex, arrowverttp, and
+ arrowvertbt.
+
+Mon Aug 10 11:54:27 1992 James Clark (jjc at jclark)
+
+ * FontMap: Add m/p fields to the fonts names.
+
+Sat Aug 8 12:00:28 1992 James Clark (jjc at jclark)
+
+ * DESC: Leave font positions 5-9 blank.
+
+Tue Jul 28 11:37:05 1992 James Clark (jjc at jclark)
+
+ * Imakefile: Don't use gendef. Pass definition of FONTPATH using
+ DEFINES.
+ (path.h): Deleted.
+ (device.c): Don't include path.h. Provide default definition of
+ FONTPATH.
+
+Mon Jul 6 14:06:53 1992 James Clark (jjc at jclark)
+
+ * Imakefile: Don't install tmac.X and tmac.Xps.
+ * tmac.X, tmac.Xps: Moved to ../macros.
+
+ * Imakefile: Don't install eqnchar.
+ * eqnchar: Deleted.
+
+Sun Jun 14 12:55:02 1992 James Clark (jjc@jclark)
+
+ * tmac.Xps: Handle OE, oe, lq, rq.
+ * draw.c (FakeCharacter): Don't handle these.
+
+ * draw.c (FakeCharacter): Don't handle f/.
+
+Mon Jun 8 11:46:37 1992 James Clark (jjc@jclark)
+
+ * tmac.X: Translate char160 to space.
+
+Sun Jun 7 14:39:53 1992 James Clark (jjc@jclark)
+
+ * tmac.X: Do `mso tmac.psic' before restoring compatibility mode.
+
+ * tmac.X: Add \(OE, \(oe, \(ah, \(ao, \(ho.
+
+ * tmac.Xps: Make it work in compatibility mode.
+ Redo existing character definitions with .Xps-char.
+ Add more character definitions.
+ (Xps-char): New macro.
+
+Sat Jun 6 21:46:03 1992 James Clark (jjc@jclark)
+
+ * DviChar.c (Adobe_Symbol_map): Add +h, +f, +p, Fn, lz.
+ * tmac.X: Add \(bq, \(Bq, \(aq.
+ * tmac.Xps: Handle \(aq, \(bq, \(Bq, \(Fn.
+
+Wed Jun 3 11:11:15 1992 James Clark (jjc@jclark)
+
+ * DviChar.c (Adobe_Symbol_map): Add wp.
+
+Tue Apr 21 09:21:59 1992 James Clark (jjc at jclark)
+
+ * GXditview.ad: Bind n, p, q keys to NextPage, PreviousPage and
+ Quit actions.
+
+ * xditview.c (RerasterizeAction): New function.
+ (xditview_actions): Add RerasterizeAction.
+ * GXditview.ad: Bind r key to Rerasterize action.
+
+Fri Apr 17 08:25:36 1992 James Clark (jjc at jclark)
+
+ * xditview.c: Add -filename option.
+ (main): Copy any -filename argument into current_file_name.
+
+Mon Mar 16 10:21:58 1992 James Clark (jjc at jclark)
+
+ * tmac.X: Load tmac.pspic.
+
+Sun Mar 8 11:27:19 1992 James Clark (jjc at jclark)
+
+ * Lex.c (GetLine, GetWord, GetNumber): Rewrite.
+
+Sat Oct 12 22:58:52 1991 James Clark (jjc at jclark)
+
+ * Dvi.c (SetDevice): If the size change request is refused but a
+ larger geometry is offered, request that.
+
+Wed Oct 9 12:27:48 1991 James Clark (jjc at jclark)
+
+ * font.c (InstallFontSizes): Ignore FontNameAverageWidth component.
+
+ * Dvi.c (default_font_map): Add `adobe' to font names to avoid
+ ambiguity.
+
+ * FontMap: New file.
+ * FontMap.X100, FontMap.X75: Deleted.
+ * xtotroff.c (main, usage): Add -s and -r options.
+ (MapFont): Change the font pattern to have the selected resolution and
+ size.
+ * Imakefile (install.dev): Use FontMap and supply appropriate -s
+ and -r options.
+
+ * xtotroff.c (MapFont): Check for ambiguity by comparing canonicalized
+ font names.
+
+ * DviP.h (DviFontList): Add initialized and scalable members.
+ (font.c): Add support for scalable fonts based on R5 xditview.
+
+ * DviChar.c: Use xmalloc rather than malloc.
+ * xditview.c (xmalloc): New function.
+ * xtotroff.c (xmalloc): New function.
+ * other files: Use XtMalloc and XtFree instead of malloc and free.
+
+Thu Aug 29 20:15:31 1991 James Clark (jjc at jclark)
+
+ * draw.c (setGC): Do multiplication in floating point to avoid
+ overflow.
+
+Tue Aug 13 12:04:41 1991 James Clark (jjc at jclark)
+
+ * draw.c (FakeCharacter): Remove casts in defintion of pack2.
+
+Tue Jul 30 11:42:39 1991 James Clark (jjc at jclark)
+
+ * tmac.Xps: New file.
+ * Imakefile (install): Install tmac.Xps.
+
+Tue Jul 2 09:31:37 1991 James Clark (jjc at jclark)
+
+ * xtotroff.c (main): Pass argv[0] to usage().
+
+Sun Jun 30 12:34:06 1991 James Clark (jjc at jclark)
+
+ * xtotroff.c (MapFont): Handle the case where XLoadQueryFont
+ returns NULL.
+
+Sat Jun 29 12:32:52 1991 James Clark (jjc at jclark)
+
+ * Imakefile: Use ../gendef to generate path.h.
+
+Sun Jun 16 13:26:34 1991 James Clark (jjc at jclark)
+
+ * Imakefile (depend.o): Change to device.o.
+
+Sun Jun 2 12:17:56 1991 James Clark (jjc at jclark)
+
+ * Imakefile: Remove spaces from the beginning of variable
+ assignment lines.
+
+Sun May 26 14:14:01 1991 James Clark (jjc at jclark)
+
+ * xditview.c (Syntax): Update.
+
+ * Dvi.c (DviSaveToFile, SaveToFile): New functions.
+ (FindPage): Check that we're not readingTmp before checking for
+ end of file of normal input file.
+ (ClassPartInitialize): New function.
+ * Dvi.h: Add declaration of DviSaveToFile.
+ * DviP.h: Add save method to DviClassPart. Declare
+ InheritSaveToFile.
+ * xditview.c (DoPrint, Print, PrintAction): New functions.
+ * xditview.c: Add print menu entry.
+ * xditview.c: Provide printCommand application resource.
+ * lex.c: Don't output EOF to temporary file.
+
+ * Dvi.c (QueryGeometry): Check request->request_mode.
+
+ * Dvi.c (SetDevice): New function.
+ (SetDeviceResolution): Deleted.
+
+ * Dvi.c: Add resolution resource.
+ * DviP.h: Add definitions of XtNResolution and XtCResolution.
+ * xditview.c: Add -resolution argument.
+ * GXditview.ad: Add default for GXditview.height.
+ * Dvi.c (Initialize, SetDevice): Use default_resolution.
+
+ * Dvi.c: Make MY_HEIGHT and MY_WIDTH use the paperlength and
+ paperwidth commands in the DESC file.
+
+ * Dvi.c: Add SS font to default font map.
+
+ * draw.c: Rewritten so as not to assume device and display
+ resolution is the same.
+ * DviP.h: Include device.h. Add device_font member to DviFontList.
+ Add adjustable arrary to DviCharCache. Add text_x_width,
+ text_device_width, word_flag, device_font, device_font_number,
+ device, native, device_resolution, display_resolution,
+ paperlength, paperwidth, scale_factor, sizescale members.
+ * Dvi.c (Initialize): Initialize new variable used by draw.c
+ (Destroy): Call device_destroy.
+ * font.c (MaxFontPosition): New function.
+ (LookupFontSizeBySize): Handle sizescale.
+ (InstallFont): Load the device font.
+ (ForgetFonts): New function.
+ (QueryDeviceFont): New function.
+ * parse.c (ParseInput): Handle t and u commands. Split off
+ character output into draw.c.
+ (ParseDeviceControl): Ignore res command. Use the device argument
+ to the T command.
+
+ * font.c (MapXNameToDviName): Ifdefed out.
+
+ * path.h: New file.
+ * device.c, device.h: New files.
+
+ * DviChar.c: Add entries for lB, rB, oq, lC, rC, md.
+
+ * INSTALL: New file.
+
+ * libxdvi: Merged into main directory.
+ * xtotroff.c, xditview.c: Change includes accordingly.
+
+ * devX75, devX100: Merged into main directory.
+ * xditview.man: Renamed to gxditview.man.
+
+ * Xditview.ad: Renamed to GXditview.ad.
+ * xditview.c (main): Use class of GXditview rather than xditview.
+
+ * Imakefile: New file.
+ * Makefile: Deleted.
+
+ * xtotroff.c (MapFont): Unlink output file before opening it.
+
+ * Started separate ChangeLog.
diff --git a/gnu/usr.bin/groff/xditview/DESC b/gnu/usr.bin/groff/xditview/DESC
new file mode 100644
index 000000000000..172170c9c0b5
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 75
+X11
+hor 1
+vert 1
+unitwidth 10
+postpro gxditview
diff --git a/gnu/usr.bin/groff/xditview/Dvi.c b/gnu/usr.bin/groff/xditview/Dvi.c
new file mode 100644
index 000000000000..8402119a36cc
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/Dvi.c
@@ -0,0 +1,544 @@
+#ifndef SABER
+#ifndef lint
+static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $";
+#endif /* lint */
+#endif /* SABER */
+
+/*
+ * Dvi.c - Dvi display widget
+ *
+ */
+
+#define XtStrlen(s) ((s) ? strlen(s) : 0)
+
+ /* The following are defined for the reader's convenience. Any
+ Xt..Field macro in this code just refers to some field in
+ one of the substructures of the WidgetRec. */
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Converters.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+/* Private Data */
+
+static char default_font_map[] = "\
+TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+";
+
+#define offset(field) XtOffset(DviWidget, field)
+
+#define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5))
+#define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5))
+
+static XtResource resources[] = {
+ {XtNfontMap, XtCFontMap, XtRString, sizeof (char *),
+ offset(dvi.font_map_string), XtRString, default_font_map},
+ {XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long),
+ offset(dvi.foreground), XtRString, "black"},
+ {XtNbackground, XtCBackground, XtRPixel, sizeof (unsigned long),
+ offset(dvi.background), XtRString, "white"},
+ {XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int),
+ offset(dvi.requested_page), XtRString, "1"},
+ {XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int),
+ offset (dvi.last_page), XtRString, "0"},
+ {XtNfile, XtCFile, XtRFile, sizeof (FILE *),
+ offset (dvi.file), XtRFile, (char *) 0},
+ {XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean),
+ offset(dvi.seek), XtRString, "false"},
+ {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
+ offset(dvi.default_font), XtRString, "xtdefaultfont"},
+ {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
+ offset(dvi.backing_store), XtRString, "default"},
+ {XtNnoPolyText, XtCNoPolyText, XtRBoolean, sizeof (Boolean),
+ offset(dvi.noPolyText), XtRString, "false"},
+ {XtNresolution, XtCResolution, XtRInt, sizeof(int),
+ offset(dvi.default_resolution), XtRString, "75"},
+};
+
+#undef offset
+
+static void ClassInitialize ();
+static void ClassPartInitialize();
+static void Initialize(), Realize (), Destroy (), Redisplay ();
+static Boolean SetValues (), SetValuesHook ();
+static XtGeometryResult QueryGeometry ();
+static void ShowDvi ();
+static void CloseFile (), OpenFile ();
+static void FindPage ();
+
+static void SaveToFile ();
+
+DviClassRec dviClassRec = {
+{
+ &widgetClassRec, /* superclass */
+ "Dvi", /* class_name */
+ sizeof(DviRec), /* size */
+ ClassInitialize, /* class_initialize */
+ ClassPartInitialize, /* class_part_initialize */
+ FALSE, /* class_inited */
+ Initialize, /* initialize */
+ NULL, /* initialize_hook */
+ Realize, /* realize */
+ NULL, /* actions */
+ 0, /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* resource_count */
+ NULLQUARK, /* xrm_class */
+ FALSE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress_enterleave */
+ FALSE, /* visible_interest */
+ Destroy, /* destroy */
+ NULL, /* resize */
+ Redisplay, /* expose */
+ SetValues, /* set_values */
+ SetValuesHook, /* set_values_hook */
+ NULL, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback_private */
+ 0, /* tm_table */
+ QueryGeometry, /* query_geometry */
+ NULL, /* display_accelerator */
+ NULL /* extension */
+},{
+ SaveToFile, /* save */
+},
+};
+
+WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
+
+static void ClassInitialize ()
+{
+ XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+ NULL, 0 );
+}
+
+/****************************************************************
+ *
+ * Private Procedures
+ *
+ ****************************************************************/
+
+/* ARGSUSED */
+static void Initialize(request, new)
+ Widget request, new;
+{
+ DviWidget dw = (DviWidget) new;
+
+ dw->dvi.current_page = 0;
+ dw->dvi.font_map = 0;
+ dw->dvi.cache.index = 0;
+ dw->dvi.text_x_width = 0;
+ dw->dvi.text_device_width = 0;
+ dw->dvi.word_flag = 0;
+ dw->dvi.file = 0;
+ dw->dvi.tmpFile = 0;
+ dw->dvi.state = 0;
+ dw->dvi.readingTmp = 0;
+ dw->dvi.cache.char_index = 0;
+ dw->dvi.cache.font_size = -1;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.cache.adjustable[0] = 0;
+ dw->dvi.file_map = 0;
+ dw->dvi.fonts = 0;
+ dw->dvi.seek = False;
+ dw->dvi.device_resolution = dw->dvi.default_resolution;
+ dw->dvi.display_resolution = dw->dvi.default_resolution;
+ dw->dvi.paperlength = dw->dvi.default_resolution*11;
+ dw->dvi.paperwidth = (dw->dvi.default_resolution*8
+ + dw->dvi.default_resolution/2);
+ dw->dvi.scale_factor = 1.0;
+ dw->dvi.sizescale = 1;
+ dw->dvi.line_thickness = -1;
+ dw->dvi.line_width = 1;
+ dw->dvi.fill = DVI_FILL_MAX;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ dw->dvi.device = 0;
+ dw->dvi.native = 0;
+}
+
+#include <X11/bitmaps/gray>
+
+static void
+Realize (w, valueMask, attrs)
+ Widget w;
+ XtValueMask *valueMask;
+ XSetWindowAttributes *attrs;
+{
+ DviWidget dw = (DviWidget) w;
+ XGCValues values;
+
+ if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
+ attrs->backing_store = dw->dvi.backing_store;
+ *valueMask |= CWBackingStore;
+ }
+ XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
+ *valueMask, attrs);
+ values.foreground = dw->dvi.foreground;
+ values.cap_style = CapRound;
+ values.join_style = JoinRound;
+ values.line_width = dw->dvi.line_width;
+ dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
+ GCForeground|GCCapStyle|GCJoinStyle
+ |GCLineWidth,
+ &values);
+ dw->dvi.gray = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray_bits,
+ gray_width, gray_height);
+ values.background = dw->dvi.background;
+ values.stipple = dw->dvi.gray;
+ dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
+ GCForeground|GCBackground|GCStipple,
+ &values);
+
+ dw->dvi.fill_type = DVI_FILL_BLACK;
+
+ if (dw->dvi.file)
+ OpenFile (dw);
+ ParseFontMap (dw);
+}
+
+static void
+Destroy(w)
+ Widget w;
+{
+ DviWidget dw = (DviWidget) w;
+
+ XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
+ XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray);
+ DestroyFontMap (dw->dvi.font_map);
+ DestroyFileMap (dw->dvi.file_map);
+ device_destroy (dw->dvi.device);
+}
+
+/*
+ * Repaint the widget window
+ */
+
+/* ARGSUSED */
+static void
+Redisplay(w, event, region)
+ Widget w;
+ XEvent *event;
+ Region region;
+{
+ DviWidget dw = (DviWidget) w;
+ XRectangle extents;
+
+ XClipBox (region, &extents);
+ dw->dvi.extents.x1 = extents.x;
+ dw->dvi.extents.y1 = extents.y;
+ dw->dvi.extents.x2 = extents.x + extents.width;
+ dw->dvi.extents.y2 = extents.y + extents.height;
+ ShowDvi (dw);
+}
+
+/*
+ * Set specified arguments into widget
+ */
+/* ARGSUSED */
+static Boolean
+SetValues (current, request, new)
+ DviWidget current, request, new;
+{
+ Boolean redisplay = FALSE;
+ char *new_map;
+ int cur, req;
+
+ if (current->dvi.font_map_string != request->dvi.font_map_string) {
+ new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
+ if (new_map) {
+ redisplay = TRUE;
+ strcpy (new_map, request->dvi.font_map_string);
+ new->dvi.font_map_string = new_map;
+ if (current->dvi.font_map_string)
+ XtFree (current->dvi.font_map_string);
+ current->dvi.font_map_string = 0;
+ ParseFontMap (new);
+ }
+ }
+
+ req = request->dvi.requested_page;
+ cur = current->dvi.requested_page;
+ if (cur != req) {
+ if (!request->dvi.file)
+ req = 0;
+ else {
+ if (req < 1)
+ req = 1;
+ if (current->dvi.last_page != 0 &&
+ req > current->dvi.last_page)
+ req = current->dvi.last_page;
+ }
+ if (cur != req)
+ redisplay = TRUE;
+ new->dvi.requested_page = req;
+ if (current->dvi.last_page == 0 && req > cur)
+ FindPage (new);
+ }
+
+ return redisplay;
+}
+
+/*
+ * use the set_values_hook entry to check when
+ * the file is set
+ */
+
+static Boolean
+SetValuesHook (dw, args, num_argsp)
+ DviWidget dw;
+ ArgList args;
+ Cardinal *num_argsp;
+{
+ Cardinal i;
+
+ for (i = 0; i < *num_argsp; i++) {
+ if (!strcmp (args[i].name, XtNfile)) {
+ CloseFile (dw);
+ OpenFile (dw);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void CloseFile (dw)
+ DviWidget dw;
+{
+ if (dw->dvi.tmpFile)
+ fclose (dw->dvi.tmpFile);
+ ForgetPagePositions (dw);
+}
+
+static void OpenFile (dw)
+ DviWidget dw;
+{
+ char tmpName[sizeof ("/tmp/dviXXXXXX")];
+
+ dw->dvi.tmpFile = 0;
+ if (!dw->dvi.seek) {
+ strcpy (tmpName, "/tmp/dviXXXXXX");
+ mktemp (tmpName);
+ dw->dvi.tmpFile = fopen (tmpName, "w+");
+ unlink (tmpName);
+ }
+ dw->dvi.requested_page = 1;
+ dw->dvi.last_page = 0;
+}
+
+static XtGeometryResult
+QueryGeometry (w, request, geometry_return)
+ Widget w;
+ XtWidgetGeometry *request, *geometry_return;
+{
+ XtGeometryResult ret;
+ DviWidget dw = (DviWidget) w;
+
+ ret = XtGeometryYes;
+ if (((request->request_mode & CWWidth)
+ && request->width < MY_WIDTH(dw))
+ || ((request->request_mode & CWHeight)
+ && request->height < MY_HEIGHT(dw)))
+ ret = XtGeometryAlmost;
+ geometry_return->width = MY_WIDTH(dw);
+ geometry_return->height = MY_HEIGHT(dw);
+ geometry_return->request_mode = CWWidth|CWHeight;
+ return ret;
+}
+
+SetDevice (dw, name)
+ DviWidget dw;
+ char *name;
+{
+ XtWidgetGeometry request, reply;
+ XtGeometryResult ret;
+
+ ForgetFonts (dw);
+ dw->dvi.device = device_load (name);
+ if (!dw->dvi.device)
+ return;
+ dw->dvi.sizescale = dw->dvi.device->sizescale;
+ dw->dvi.device_resolution = dw->dvi.device->res;
+ dw->dvi.native = dw->dvi.device->X11;
+ dw->dvi.paperlength = dw->dvi.device->paperlength;
+ dw->dvi.paperwidth = dw->dvi.device->paperwidth;
+ if (dw->dvi.native) {
+ dw->dvi.display_resolution = dw->dvi.device_resolution;
+ dw->dvi.scale_factor = 1.0;
+ }
+ else {
+ dw->dvi.display_resolution = dw->dvi.default_resolution;
+ dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
+ / dw->dvi.device_resolution);
+ }
+ request.request_mode = CWWidth|CWHeight;
+ request.width = MY_WIDTH(dw);
+ request.height = MY_HEIGHT(dw);
+ ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
+ if (ret == XtGeometryAlmost
+ && reply.height >= request.height
+ && reply.width >= request.width) {
+ request.width = reply.width;
+ request.height = reply.height;
+ XtMakeGeometryRequest ((Widget)dw, &request, &reply);
+ }
+}
+
+static void
+ShowDvi (dw)
+ DviWidget dw;
+{
+ if (!dw->dvi.file) {
+ static char Error[] = "No file selected";
+
+ XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
+ dw->dvi.default_font->fid);
+ XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ 20, 20, Error, strlen (Error));
+ return;
+ }
+
+ FindPage (dw);
+
+ dw->dvi.display_enable = 1;
+ ParseInput (dw);
+ if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
+ dw->dvi.requested_page = dw->dvi.last_page;
+}
+
+static void
+FindPage (dw)
+ DviWidget dw;
+{
+ int i;
+ long file_position;
+
+ if (dw->dvi.requested_page < 1)
+ dw->dvi.requested_page = 1;
+
+ if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
+ dw->dvi.requested_page = dw->dvi.last_page;
+
+ file_position = SearchPagePosition (dw, dw->dvi.requested_page);
+ if (file_position != -1) {
+ FileSeek(dw, file_position);
+ dw->dvi.current_page = dw->dvi.requested_page;
+ } else {
+ for (i=dw->dvi.requested_page; i > 0; i--) {
+ file_position = SearchPagePosition (dw, i);
+ if (file_position != -1)
+ break;
+ }
+ if (file_position == -1)
+ file_position = 0;
+ FileSeek (dw, file_position);
+
+ dw->dvi.current_page = i;
+
+ dw->dvi.display_enable = 0;
+ while (dw->dvi.current_page != dw->dvi.requested_page) {
+ dw->dvi.current_page = ParseInput (dw);
+ /*
+ * at EOF, seek back to the begining of this page.
+ */
+ if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
+ file_position = SearchPagePosition (dw,
+ dw->dvi.current_page);
+ if (file_position != -1)
+ FileSeek (dw, file_position);
+ dw->dvi.requested_page = dw->dvi.current_page;
+ break;
+ }
+ }
+ }
+}
+
+void DviSaveToFile(w, fp)
+ Widget w;
+ FILE *fp;
+{
+ XtCheckSubclass(w, dviWidgetClass, NULL);
+ (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
+}
+
+static
+void SaveToFile(w, fp)
+ Widget w;
+ FILE *fp;
+{
+ DviWidget dw = (DviWidget)w;
+ long pos;
+ int c;
+
+ if (dw->dvi.tmpFile) {
+ pos = ftell(dw->dvi.tmpFile);
+ if (dw->dvi.ungot) {
+ pos--;
+ dw->dvi.ungot = 0;
+ /* The ungot character is in the tmpFile, so we don't
+ want to read it from file. */
+ (void)getc(dw->dvi.file);
+ }
+ }
+ else
+ pos = ftell(dw->dvi.file);
+ FileSeek(dw, 0L);
+ while (DviGetC(dw, &c) != EOF)
+ if (putc(c, fp) == EOF) {
+ /* XXX print error message */
+ break;
+ }
+ FileSeek(dw, pos);
+}
+
+static
+void ClassPartInitialize(widget_class)
+ WidgetClass widget_class;
+{
+ DviWidgetClass wc = (DviWidgetClass)widget_class;
+ DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
+ if (wc->command_class.save == InheritSaveToFile)
+ wc->command_class.save = super->command_class.save;
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/groff/xditview/Dvi.h b/gnu/usr.bin/groff/xditview/Dvi.h
new file mode 100644
index 000000000000..5aab7d8c7558
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/Dvi.h
@@ -0,0 +1,46 @@
+/*
+* $XConsortium: Dvi.h,v 1.4 89/07/21 14:22:06 jim Exp $
+*/
+
+#ifndef _XtDvi_h
+#define _XtDvi_h
+
+/***********************************************************************
+ *
+ * Dvi Widget
+ *
+ ***********************************************************************/
+
+/* Parameters:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ background Background pixel White
+ foreground Foreground Pixel Black
+ fontMap FontMap char * ...
+ pageNumber PageNumber int 1
+*/
+
+#define XtNfontMap "fontMap"
+#define XtNpageNumber "pageNumber"
+#define XtNlastPageNumber "lastPageNumber"
+#define XtNnoPolyText "noPolyText"
+#define XtNseek "seek"
+#define XtNresolution "resolution"
+
+#define XtCFontMap "FontMap"
+#define XtCPageNumber "PageNumber"
+#define XtCLastPageNumber "LastPageNumber"
+#define XtCNoPolyText "NoPolyText"
+#define XtCSeek "Seek"
+#define XtCResolution "Resolution"
+
+typedef struct _DviRec *DviWidget; /* completely defined in DviPrivate.h */
+typedef struct _DviClassRec *DviWidgetClass; /* completely defined in DviPrivate.h */
+
+extern WidgetClass dviWidgetClass;
+
+extern void DviSaveToFile();
+
+#endif /* _XtDvi_h */
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/gnu/usr.bin/groff/xditview/DviChar.c b/gnu/usr.bin/groff/xditview/DviChar.c
new file mode 100644
index 000000000000..dc511bf497d5
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/DviChar.c
@@ -0,0 +1,664 @@
+/*
+ * DviChar.c
+ *
+ * Map DVI (ditroff output) character names to
+ * font indexes and back
+ */
+
+#include "DviChar.h"
+
+extern char *xmalloc();
+
+#define allocHash() ((DviCharNameHash *) xmalloc (sizeof (DviCharNameHash)))
+
+struct map_list {
+ struct map_list *next;
+ DviCharNameMap *map;
+};
+
+static struct map_list *world;
+
+static int standard_maps_loaded = 0;
+static void load_standard_maps ();
+static int hash_name ();
+static dispose_hash(), compute_hash();
+
+DviCharNameMap *
+DviFindMap (encoding)
+ char *encoding;
+{
+ struct map_list *m;
+
+ if (!standard_maps_loaded)
+ load_standard_maps ();
+ for (m = world; m; m=m->next)
+ if (!strcmp (m->map->encoding, encoding))
+ return m->map;
+ return 0;
+}
+
+void
+DviRegisterMap (map)
+ DviCharNameMap *map;
+{
+ struct map_list *m;
+
+ if (!standard_maps_loaded)
+ load_standard_maps ();
+ for (m = world; m; m = m->next)
+ if (!strcmp (m->map->encoding, map->encoding))
+ break;
+ if (!m) {
+ m = (struct map_list *) xmalloc (sizeof *m);
+ m->next = world;
+ world = m;
+ }
+ dispose_hash (map);
+ m->map = map;
+ compute_hash (map);
+}
+
+static
+dispose_hash (map)
+ DviCharNameMap *map;
+{
+ DviCharNameHash **buckets;
+ DviCharNameHash *h, *next;
+ int i;
+
+ buckets = map->buckets;
+ for (i = 0; i < DVI_HASH_SIZE; i++) {
+ for (h = buckets[i]; h; h=next) {
+ next = h->next;
+ free (h);
+ }
+ }
+}
+
+static int
+hash_name (name)
+ char *name;
+{
+ int i = 0;
+
+ while (*name)
+ i = (i << 1) ^ *name++;
+ if (i < 0)
+ i = -i;
+ return i;
+}
+
+static
+compute_hash (map)
+ DviCharNameMap *map;
+{
+ DviCharNameHash **buckets;
+ int c, s, i;
+ DviCharNameHash *h;
+
+ buckets = map->buckets;
+ for (i = 0; i < DVI_HASH_SIZE; i++)
+ buckets[i] = 0;
+ for (c = 0; c < DVI_MAP_SIZE; c++)
+ for (s = 0; s < DVI_MAX_SYNONYMS; s++) {
+ if (!map->dvi_names[c][s])
+ break;
+ i = hash_name (map->dvi_names[c][s]) % DVI_HASH_SIZE;
+ h = allocHash ();
+ h->next = buckets[i];
+ buckets[i] = h;
+ h->name = map->dvi_names[c][s];
+ h->position = c;
+ }
+
+}
+
+int
+DviCharIndex (map, name)
+ DviCharNameMap *map;
+ char *name;
+{
+ int i;
+ DviCharNameHash *h;
+
+ i = hash_name (name) % DVI_HASH_SIZE;
+ for (h = map->buckets[i]; h; h=h->next)
+ if (!strcmp (h->name, name))
+ return h->position;
+ return -1;
+}
+
+static DviCharNameMap ISO8859_1_map = {
+ "iso8859-1",
+ 0,
+{
+{ 0, /* 0 */},
+{ 0, /* 1 */},
+{ 0, /* 2 */},
+{ 0, /* 3 */},
+{ 0, /* 4 */},
+{ 0, /* 5 */},
+{ 0, /* 6 */},
+{ 0, /* 7 */},
+{ 0, /* 8 */},
+{ 0, /* 9 */},
+{ 0, /* 10 */},
+{ 0, /* 11 */},
+{ 0, /* 12 */},
+{ 0, /* 13 */},
+{ 0, /* 14 */},
+{ 0, /* 15 */},
+{ 0, /* 16 */},
+{ 0, /* 17 */},
+{ 0, /* 18 */},
+{ 0, /* 19 */},
+{ 0, /* 20 */},
+{ 0, /* 21 */},
+{ 0, /* 22 */},
+{ 0, /* 23 */},
+{ 0, /* 24 */},
+{ 0, /* 25 */},
+{ 0, /* 26 */},
+{ 0, /* 27 */},
+{ 0, /* 28 */},
+{ 0, /* 29 */},
+{ 0, /* 30 */},
+{ 0, /* 31 */},
+{ 0, /* 32 */},
+{ "!", /* 33 */},
+{ "\"", /* 34 */},
+{ "#","sh", /* 35 */},
+{ "$","Do", /* 36 */},
+{ "%", /* 37 */},
+{ "&", /* 38 */},
+{ "'", /* 39 */},
+{ "(", /* 40 */},
+{ ")", /* 41 */},
+{ "*", /* 42 */},
+{ "+", /* 43 */},
+{ ",", /* 44 */},
+{ "\\-", /* 45 */},
+{ ".", /* 46 */},
+{ "/","sl", /* 47 */},
+{ "0", /* 48 */},
+{ "1", /* 49 */},
+{ "2", /* 50 */},
+{ "3", /* 51 */},
+{ "4", /* 52 */},
+{ "5", /* 53 */},
+{ "6", /* 54 */},
+{ "7", /* 55 */},
+{ "8", /* 56 */},
+{ "9", /* 57 */},
+{ ":", /* 58 */},
+{ ";", /* 59 */},
+{ "<", /* 60 */},
+{ "=","eq", /* 61 */},
+{ ">", /* 62 */},
+{ "?", /* 63 */},
+{ "@","at", /* 64 */},
+{ "A", /* 65 */},
+{ "B", /* 66 */},
+{ "C", /* 67 */},
+{ "D", /* 68 */},
+{ "E", /* 69 */},
+{ "F", /* 70 */},
+{ "G", /* 71 */},
+{ "H", /* 72 */},
+{ "I", /* 73 */},
+{ "J", /* 74 */},
+{ "K", /* 75 */},
+{ "L", /* 76 */},
+{ "M", /* 77 */},
+{ "N", /* 78 */},
+{ "O", /* 79 */},
+{ "P", /* 80 */},
+{ "Q", /* 81 */},
+{ "R", /* 82 */},
+{ "S", /* 83 */},
+{ "T", /* 84 */},
+{ "U", /* 85 */},
+{ "V", /* 86 */},
+{ "W", /* 87 */},
+{ "X", /* 88 */},
+{ "Y", /* 89 */},
+{ "Z", /* 90 */},
+{ "[","lB", /* 91 */},
+{ "\\","rs", /* 92 */},
+{ "]","rB", /* 93 */},
+{ "^","a^","ha" /* 94 */},
+{ "_", /* 95 */},
+{ "`","oq", /* 96 */},
+{ "a", /* 97 */},
+{ "b", /* 98 */},
+{ "c", /* 99 */},
+{ "d", /* 100 */},
+{ "e", /* 101 */},
+{ "f", /* 102 */},
+{ "g", /* 103 */},
+{ "h", /* 104 */},
+{ "i", /* 105 */},
+{ "j", /* 106 */},
+{ "k", /* 107 */},
+{ "l", /* 108 */},
+{ "m", /* 109 */},
+{ "n", /* 110 */},
+{ "o", /* 111 */},
+{ "p", /* 112 */},
+{ "q", /* 113 */},
+{ "r", /* 114 */},
+{ "s", /* 115 */},
+{ "t", /* 116 */},
+{ "u", /* 117 */},
+{ "v", /* 118 */},
+{ "w", /* 119 */},
+{ "x", /* 120 */},
+{ "y", /* 121 */},
+{ "z", /* 122 */},
+{ "{","lC", /* 123 */},
+{ "|","or","ba" /* 124 */},
+{ "}","rC", /* 125 */},
+{ "~","a~","ap","ti" /* 126 */},
+{ 0, /* 127 */},
+{ 0, /* 128 */},
+{ 0, /* 129 */},
+{ 0, /* 130 */},
+{ 0, /* 131 */},
+{ 0, /* 132 */},
+{ 0, /* 133 */},
+{ 0, /* 134 */},
+{ 0, /* 135 */},
+{ 0, /* 136 */},
+{ 0, /* 137 */},
+{ 0, /* 138 */},
+{ 0, /* 139 */},
+{ 0, /* 140 */},
+{ 0, /* 141 */},
+{ 0, /* 142 */},
+{ 0, /* 143 */},
+{ 0, /* 144 */},
+{ 0, /* 145 */},
+{ 0, /* 146 */},
+{ 0, /* 147 */},
+{ 0, /* 148 */},
+{ 0, /* 149 */},
+{ 0, /* 150 */},
+{ 0, /* 151 */},
+{ 0, /* 152 */},
+{ 0, /* 153 */},
+{ 0, /* 154 */},
+{ 0, /* 155 */},
+{ 0, /* 156 */},
+{ 0, /* 157 */},
+{ 0, /* 158 */},
+{ 0, /* 159 */},
+{ 0, /* 160 */},
+{ "r!", "\241", /* 161 */},
+{ "ct", "\242", /* 162 */},
+{ "Po", "\243", /* 163 */},
+{ "Cs", "\244", /* 164 */},
+{ "Ye", "\245", /* 165 */},
+{ "bb", "\246", /* 166 */},
+{ "sc", "\247", /* 167 */},
+{ "ad", "\250", /* 168 */},
+{ "co", "\251", /* 169 */},
+{ "Of", "\252", /* 170 */},
+{ "Fo", "\253", /* 171 */},
+{ "no", "\254", /* 172 */},
+{ "-", "hy", "\255" /* 173 */},
+{ "rg", "\256", /* 174 */},
+{ "a-", "\257", /* 175 */},
+{ "de", "\260", /* 176 */},
+{ "+-", "\261", /* 177 */},
+{ "S2", "\262", /* 178 */},
+{ "S3", "\263", /* 179 */},
+{ "aa", "\264", /* 180 */},
+/* Omit *m here; we want *m to match the other greek letters in the
+ symbol font. */
+{ "\265", /* 181 */},
+{ "ps", "\266", /* 182 */},
+{ "md", "\267", /* 183 */},
+{ "ac", "\270", /* 184 */},
+{ "S1", "\271", /* 185 */},
+{ "Om", "\272", /* 186 */},
+{ "Fc", "\273", /* 187 */},
+{ "14", "\274", /* 188 */},
+{ "12", "\275", /* 189 */},
+{ "34", "\276", /* 190 */},
+{ "r?", "\277", /* 191 */},
+{ "`A", "\300", /* 192 */},
+{ "'A", "\301", /* 193 */},
+{ "^A", "\302", /* 194 */},
+{ "~A", "\303", /* 195 */},
+{ ":A", "\304", /* 196 */},
+{ "oA", "\305", /* 197 */},
+{ "AE", "\306", /* 198 */},
+{ ",C", "\307", /* 199 */},
+{ "`E", "\310", /* 200 */},
+{ "'E", "\311", /* 201 */},
+{ "^E", "\312", /* 202 */},
+{ ":E", "\313", /* 203 */},
+{ "`I", "\314", /* 204 */},
+{ "'I", "\315", /* 205 */},
+{ "^I", "\316", /* 206 */},
+{ ":I", "\317", /* 207 */},
+{ "-D", "\320", /* 208 */},
+{ "~N", "\321", /* 209 */},
+{ "`O", "\322", /* 210 */},
+{ "'O", "\323", /* 211 */},
+{ "^O", "\324", /* 212 */},
+{ "~O", "\325", /* 213 */},
+{ ":O", "\326", /* 214 */},
+{ "mu", "\327", /* 215 */},
+{ "/O", "\330", /* 216 */},
+{ "`U", "\331", /* 217 */},
+{ "'U", "\332", /* 218 */},
+{ "^U", "\333", /* 219 */},
+{ ":U", "\334", /* 220 */},
+{ "'Y", "\335", /* 221 */},
+{ "TP", "\336", /* 222 */},
+{ "ss", "\337", /* 223 */},
+{ "`a", "\340", /* 224 */},
+{ "'a", "\341", /* 225 */},
+{ "^a", "\342", /* 226 */},
+{ "~a", "\343", /* 227 */},
+{ ":a", "\344", /* 228 */},
+{ "oa", "\345", /* 229 */},
+{ "ae", "\346", /* 230 */},
+{ ",c", "\347", /* 231 */},
+{ "`e", "\350", /* 232 */},
+{ "'e", "\351", /* 233 */},
+{ "^e", "\352", /* 234 */},
+{ ":e", "\353", /* 235 */},
+{ "`i", "\354", /* 236 */},
+{ "'i", "\355", /* 237 */},
+{ "^i", "\356", /* 238 */},
+{ ":i", "\357", /* 239 */},
+{ "Sd", "\360", /* 240 */},
+{ "~n", "\361", /* 241 */},
+{ "`o", "\362", /* 242 */},
+{ "'o", "\363", /* 243 */},
+{ "^o", "\364", /* 244 */},
+{ "~o", "\365", /* 245 */},
+{ ":o", "\366", /* 246 */},
+{ "di", "\367", /* 247 */},
+{ "/o", "\370", /* 248 */},
+{ "`u", "\371", /* 249 */},
+{ "'u", "\372", /* 250 */},
+{ "^u", "\373", /* 251 */},
+{ ":u", "\374", /* 252 */},
+{ "'y", "\375", /* 253 */},
+{ "Tp", "\376", /* 254 */},
+{ ":y", "\377", /* 255 */},
+}};
+
+static DviCharNameMap Adobe_Symbol_map = {
+ "adobe-fontspecific",
+ 1,
+{
+{ 0, /* 0 */},
+{ 0, /* 1 */},
+{ 0, /* 2 */},
+{ 0, /* 3 */},
+{ 0, /* 4 */},
+{ 0, /* 5 */},
+{ 0, /* 6 */},
+{ 0, /* 7 */},
+{ 0, /* 8 */},
+{ 0, /* 9 */},
+{ 0, /* 10 */},
+{ 0, /* 11 */},
+{ 0, /* 12 */},
+{ 0, /* 13 */},
+{ 0, /* 14 */},
+{ 0, /* 15 */},
+{ 0, /* 16 */},
+{ 0, /* 17 */},
+{ 0, /* 18 */},
+{ 0, /* 19 */},
+{ 0, /* 20 */},
+{ 0, /* 21 */},
+{ 0, /* 22 */},
+{ 0, /* 23 */},
+{ 0, /* 24 */},
+{ 0, /* 25 */},
+{ 0, /* 26 */},
+{ 0, /* 27 */},
+{ 0, /* 28 */},
+{ 0, /* 29 */},
+{ 0, /* 30 */},
+{ 0, /* 31 */},
+{ 0, /* 32 */},
+{ "!", /* 33 */},
+{ "fa", /* 34 */},
+{ "#", "sh", /* 35 */},
+{ "te", /* 36 */},
+{ "%", /* 37 */},
+{ "&", /* 38 */},
+{ "st", /* 39 */},
+{ "(", /* 40 */},
+{ ")", /* 41 */},
+{ "**", /* 42 */},
+{ "+", "pl", /* 43 */},
+{ ",", /* 44 */},
+{ "\\-", "mi", /* 45 */},
+{ ".", /* 46 */},
+{ "/", "sl", /* 47 */},
+{ "0", /* 48 */},
+{ "1", /* 49 */},
+{ "2", /* 50 */},
+{ "3", /* 51 */},
+{ "4", /* 52 */},
+{ "5", /* 53 */},
+{ "6", /* 54 */},
+{ "7", /* 55 */},
+{ "8", /* 56 */},
+{ "9", /* 57 */},
+{ ":", /* 58 */},
+{ ";", /* 59 */},
+{ "<", /* 60 */},
+{ "=", "eq", /* 61 */},
+{ ">", /* 62 */},
+{ "?", /* 63 */},
+{ "=~", /* 64 */},
+{ "*A", /* 65 */},
+{ "*B", /* 66 */},
+{ "*X", /* 67 */},
+{ "*D", /* 68 */},
+{ "*E", /* 69 */},
+{ "*F", /* 70 */},
+{ "*G", /* 71 */},
+{ "*Y", /* 72 */},
+{ "*I", /* 73 */},
+{ "+h", /* 74 */},
+{ "*K", /* 75 */},
+{ "*L", /* 76 */},
+{ "*M", /* 77 */},
+{ "*N", /* 78 */},
+{ "*O", /* 79 */},
+{ "*P", /* 80 */},
+{ "*H", /* 81 */},
+{ "*R", /* 82 */},
+{ "*S", /* 83 */},
+{ "*T", /* 84 */},
+{ 0, /* 85 */},
+{ "ts", /* 86 */},
+{ "*W", /* 87 */},
+{ "*C", /* 88 */},
+{ "*Q", /* 89 */},
+{ "*Z", /* 90 */},
+{ "[", "lB", /* 91 */},
+{ "tf", "3d", /* 92 */},
+{ "]", "rB", /* 93 */},
+{ "pp", /* 94 */},
+{ "_", /* 95 */},
+{ "rn", /* 96 */},
+{ "*a", /* 97 */},
+{ "*b", /* 98 */},
+{ "*x", /* 99 */},
+{ "*d", /* 100 */},
+{ "*e", /* 101 */},
+{ "*f", /* 102 */},
+{ "*g", /* 103 */},
+{ "*y", /* 104 */},
+{ "*i", /* 105 */},
+{ "+f", /* 106 */},
+{ "*k", /* 107 */},
+{ "*l", /* 108 */},
+{ "*m", "\265", /* 109 */},
+{ "*n", /* 110 */},
+{ "*o", /* 111 */},
+{ "*p", /* 112 */},
+{ "*h", /* 113 */},
+{ "*r", /* 114 */},
+{ "*s", /* 115 */},
+{ "*t", /* 116 */},
+{ "*u", /* 117 */},
+{ "+p", /* 118 */},
+{ "*w", /* 119 */},
+{ "*c", /* 120 */},
+{ "*q", /* 121 */},
+{ "*z", /* 122 */},
+{ "lC", "{", /* 123 */},
+{ "ba", "or", "|", /* 124 */},
+{ "rC", "}", /* 125 */},
+{ "ap", /* 126 */},
+{ 0, /* 127 */},
+{ 0, /* 128 */},
+{ 0, /* 129 */},
+{ 0, /* 130 */},
+{ 0, /* 131 */},
+{ 0, /* 132 */},
+{ 0, /* 133 */},
+{ 0, /* 134 */},
+{ 0, /* 135 */},
+{ 0, /* 136 */},
+{ 0, /* 137 */},
+{ 0, /* 138 */},
+{ 0, /* 139 */},
+{ 0, /* 140 */},
+{ 0, /* 141 */},
+{ 0, /* 142 */},
+{ 0, /* 143 */},
+{ 0, /* 144 */},
+{ 0, /* 145 */},
+{ 0, /* 146 */},
+{ 0, /* 147 */},
+{ 0, /* 148 */},
+{ 0, /* 149 */},
+{ 0, /* 150 */},
+{ 0, /* 151 */},
+{ 0, /* 152 */},
+{ 0, /* 153 */},
+{ 0, /* 154 */},
+{ 0, /* 155 */},
+{ 0, /* 156 */},
+{ 0, /* 157 */},
+{ 0, /* 158 */},
+{ 0, /* 159 */},
+{ 0, /* 160 */},
+{ "*U", /* 161 */},
+{ "fm", /* 162 */},
+{ "<=", /* 163 */},
+{ "f/", /* 164 */},
+{ "if", /* 165 */},
+{ "Fn", /* 166 */},
+{ "CL", /* 167 */},
+{ "DI", /* 168 */},
+{ "HE", /* 169 */},
+{ "SP", /* 170 */},
+{ "<>", /* 171 */},
+{ "<-", /* 172 */},
+{ "ua", "arrowverttp" /* 173 */},
+{ "->", /* 174 */},
+{ "da", "arrowvertbt" /* 175 */},
+{ "de", "\260", /* 176 */},
+{ "+-", "\261", /* 177 */},
+{ "sd", /* 178 */},
+{ ">=", /* 179 */},
+{ "mu", "\327", /* 180 */},
+{ "pt", /* 181 */},
+{ "pd", /* 182 */},
+{ "bu", /* 183 */},
+{ "di", "\367", /* 184 */},
+{ "!=", /* 185 */},
+{ "==", /* 186 */},
+{ "~=", "~~", /* 187 */},
+{ 0, /* 188 */},
+{ "arrowvertex", /* 189 */},
+{ "an", /* 190 */},
+{ "CR", /* 191 */},
+{ "Ah", /* 192 */},
+{ "Im", /* 193 */},
+{ "Re", /* 194 */},
+{ "wp", /* 195 */},
+{ "c*", /* 196 */},
+{ "c+", /* 197 */},
+{ "es", /* 198 */},
+{ "ca", /* 199 */},
+{ "cu", /* 200 */},
+{ "sp", /* 201 */},
+{ "ip", /* 202 */},
+{ 0, /* 203 */},
+{ "sb", /* 204 */},
+{ "ib", /* 205 */},
+{ "mo", /* 206 */},
+{ "nm", /* 207 */},
+{ "/_", /* 208 */},
+{ "gr", /* 209 */},
+{ "rg", /* 210 */},
+{ "co", /* 211 */},
+{ "tm", /* 212 */},
+{ 0, /* 213 */},
+{ "sr", /* 214 */},
+{ "md", /* 215 */},
+{ "no", "\254", /* 216 */},
+{ "AN", /* 217 */},
+{ "OR", /* 218 */},
+{ "hA", /* 219 */},
+{ "lA", /* 220 */},
+{ "uA", /* 221 */},
+{ "rA", /* 222 */},
+{ "dA", /* 223 */},
+{ "lz", /* 224 */},
+{ "la", /* 225 */},
+{ 0, /* 226 */},
+{ 0, /* 227 */},
+{ 0, /* 228 */},
+{ 0, /* 229 */},
+{ "parenlefttp", /* 230 */},
+{ "parenleftex", /* 231 */},
+{ "parenleftbt", /* 232 */},
+{ "bracketlefttp", "lc", /* 233 */},
+{ "bracketleftex", /* 234 */},
+{ "bracketleftbt", "lf", /* 235 */},
+{ "bracelefttp", "lt", /* 236 */},
+{ "braceleftmid", "lk", /* 237 */},
+{ "braceleftbt", "lb", /* 238 */},
+{ "bracerightex", "braceleftex", "bv", /* 239 */},
+{ 0, /* 240 */},
+{ "ra", /* 241 */},
+{ "is", /* 242 */},
+{ 0, /* 243 */},
+{ 0, /* 244 */},
+{ 0, /* 245 */},
+{ "parenrighttp", /* 246 */},
+{ "parenrightex", /* 247 */},
+{ "parenrightbt", /* 248 */},
+{ "bracketrighttp", "rc", /* 249 */},
+{ "bracketrightex", /* 250 */},
+{ "bracketrightbt", "rf", /* 251 */},
+{ "bracerighttp", "rt" /* 252 */},
+{ "bracerightmid", "rk" /* 253 */},
+{ "bracerightbt", "rb" /* 254 */},
+{ 0, /* 255 */},
+}};
+
+
+static void
+load_standard_maps ()
+{
+ standard_maps_loaded = 1;
+ DviRegisterMap (&ISO8859_1_map);
+ DviRegisterMap (&Adobe_Symbol_map);
+}
diff --git a/gnu/usr.bin/groff/xditview/DviChar.h b/gnu/usr.bin/groff/xditview/DviChar.h
new file mode 100644
index 000000000000..4a8f6bbe6f73
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/DviChar.h
@@ -0,0 +1,37 @@
+/*
+ * DviChar.h
+ *
+ * descriptions for mapping dvi names to
+ * font indexes and back. Dvi fonts are all
+ * 256 elements (actually only 256-32 are usable).
+ *
+ * The encoding names are taken from X -
+ * case insensitive, a dash seperating the
+ * CharSetRegistry from the CharSetEncoding
+ */
+
+# define DVI_MAX_SYNONYMS 10
+# define DVI_MAP_SIZE 256
+# define DVI_HASH_SIZE 256
+
+typedef struct _dviCharNameHash {
+ struct _dviCharNameHash *next;
+ char *name;
+ int position;
+} DviCharNameHash;
+
+typedef struct _dviCharNameMap {
+ char *encoding;
+ int special;
+ char *dvi_names[DVI_MAP_SIZE][DVI_MAX_SYNONYMS];
+ DviCharNameHash *buckets[DVI_HASH_SIZE];
+} DviCharNameMap;
+
+extern DviCharNameMap *DviFindMap ( /* char *encoding */ );
+extern void DviRegisterMap ( /* DviCharNameMap *map */ );
+#ifdef NOTDEF
+extern char *DviCharName ( /* DviCharNameMap *map, int index, int synonym */ );
+#else
+#define DviCharName(map,index,synonym) ((map)->dvi_names[index][synonym])
+#endif
+extern int DviCharIndex ( /* DviCharNameMap *map, char *name */ );
diff --git a/gnu/usr.bin/groff/xditview/DviP.h b/gnu/usr.bin/groff/xditview/DviP.h
new file mode 100644
index 000000000000..c3b7d2c71347
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/DviP.h
@@ -0,0 +1,233 @@
+/*
+ * $XConsortium: DviP.h,v 1.5 89/07/22 19:44:08 keith Exp $
+ */
+
+/*
+ * DviP.h - Private definitions for Dvi widget
+ */
+
+#ifndef _XtDviP_h
+#define _XtDviP_h
+
+#include "Dvi.h"
+#include "DviChar.h"
+#include "device.h"
+
+/***********************************************************************
+ *
+ * Dvi Widget Private Data
+ *
+ ***********************************************************************/
+
+/************************************
+ *
+ * Class structure
+ *
+ ***********************************/
+
+/* Type for save method. */
+
+typedef void (*DviSaveProc)();
+
+/*
+ * New fields for the Dvi widget class record
+ */
+
+
+typedef struct _DviClass {
+ DviSaveProc save;
+} DviClassPart;
+
+/*
+ * Full class record declaration
+ */
+
+typedef struct _DviClassRec {
+ CoreClassPart core_class;
+ DviClassPart command_class;
+} DviClassRec;
+
+extern DviClassRec dviClassRec;
+
+/***************************************
+ *
+ * Instance (widget) structure
+ *
+ **************************************/
+
+/*
+ * a list of fonts we've used for this widget
+ */
+
+typedef struct _dviFontSizeList {
+ struct _dviFontSizeList *next;
+ int size;
+ char *x_name;
+ XFontStruct *font;
+ int doesnt_exist;
+} DviFontSizeList;
+
+typedef struct _dviFontList {
+ struct _dviFontList *next;
+ char *dvi_name;
+ char *x_name;
+ int dvi_number;
+ Boolean initialized;
+ Boolean scalable;
+ DviFontSizeList *sizes;
+ DviCharNameMap *char_map;
+ DeviceFont *device_font;
+} DviFontList;
+
+typedef struct _dviFontMap {
+ struct _dviFontMap *next;
+ char *dvi_name;
+ char *x_name;
+} DviFontMap;
+
+#define DVI_TEXT_CACHE_SIZE 256
+#define DVI_CHAR_CACHE_SIZE 1024
+
+typedef struct _dviCharCache {
+ XTextItem cache[DVI_TEXT_CACHE_SIZE];
+ char adjustable[DVI_TEXT_CACHE_SIZE];
+ char char_cache[DVI_CHAR_CACHE_SIZE];
+ int index;
+ int max;
+ int char_index;
+ int font_size;
+ int font_number;
+ XFontStruct *font;
+ int start_x, start_y;
+ int x, y;
+} DviCharCache;
+
+typedef struct _dviState {
+ struct _dviState *next;
+ int font_size;
+ int font_number;
+ int x;
+ int y;
+} DviState;
+
+typedef struct _dviFileMap {
+ struct _dviFileMap *next;
+ long position;
+ int page_number;
+} DviFileMap;
+
+/*
+ * New fields for the Dvi widget record
+ */
+
+typedef struct {
+ /*
+ * resource specifiable items
+ */
+ char *font_map_string;
+ unsigned long foreground;
+ unsigned long background;
+ int requested_page;
+ int last_page;
+ XFontStruct *default_font;
+ FILE *file;
+ Boolean noPolyText;
+ Boolean seek; /* file is "seekable" */
+ int default_resolution;
+ /*
+ * private state
+ */
+ FILE *tmpFile; /* used when reading stdin */
+ char readingTmp; /* reading now from tmp */
+ char ungot; /* have ungetc'd a char */
+ GC normal_GC;
+ GC fill_GC;
+ DviFileMap *file_map;
+ DviFontList *fonts;
+ DviFontMap *font_map;
+ int current_page;
+ int font_size;
+ int font_number;
+ DeviceFont *device_font;
+ int device_font_number;
+ Device *device;
+ int native;
+ int device_resolution;
+ int display_resolution;
+ int paperlength;
+ int paperwidth;
+ double scale_factor; /* display res / device res */
+ int sizescale;
+ int line_thickness;
+ int line_width;
+
+#define DVI_FILL_MAX 1000
+
+ int fill;
+#define DVI_FILL_WHITE 0
+#define DVI_FILL_GRAY 1
+#define DVI_FILL_BLACK 2
+ int fill_type;
+ Pixmap gray;
+ int backing_store;
+ XFontStruct *font;
+ int display_enable;
+ struct ExposedExtents {
+ int x1, y1, x2, y2;
+ } extents;
+ DviState *state;
+ DviCharCache cache;
+ int text_x_width;
+ int text_device_width;
+ int word_flag;
+} DviPart;
+
+#define DviGetIn(dw,cp)\
+ (dw->dvi.tmpFile ? (\
+ DviGetAndPut (dw, cp) \
+ ) :\
+ (*cp = getc (dw->dvi.file))\
+)
+
+#define DviGetC(dw, cp)\
+ (dw->dvi.readingTmp ? (\
+ ((*cp = getc (dw->dvi.tmpFile)) == EOF) ? (\
+ fseek (dw->dvi.tmpFile, 0l, 2),\
+ (dw->dvi.readingTmp = 0),\
+ DviGetIn (dw,cp)\
+ ) : (\
+ *cp\
+ )\
+ ) : (\
+ DviGetIn(dw,cp)\
+ )\
+)
+
+#define DviUngetC(dw, c)\
+ (dw->dvi.readingTmp ? (\
+ ungetc (c, dw->dvi.tmpFile)\
+ ) : ( \
+ (dw->dvi.ungot = 1),\
+ ungetc (c, dw->dvi.file)))
+
+/*
+ * Full widget declaration
+ */
+
+typedef struct _DviRec {
+ CorePart core;
+ DviPart dvi;
+} DviRec;
+
+#define InheritSaveToFile ((DviSaveProc)_XtInherit)
+
+extern XFontStruct *QueryFont ();
+
+extern DviCharNameMap *QueryFontMap ();
+
+extern DeviceFont *QueryDeviceFont ();
+
+extern char *GetWord(), *GetLine();
+#endif /* _XtDviP_h */
+
+
diff --git a/gnu/usr.bin/groff/xditview/FontMap b/gnu/usr.bin/groff/xditview/FontMap
new file mode 100644
index 000000000000..90911f048ded
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/FontMap
@@ -0,0 +1,17 @@
+TR -adobe-times-medium-r-normal--*-*-*-*-p-*-iso8859-1
+TI -adobe-times-medium-i-normal--*-*-*-*-p-*-iso8859-1
+TB -adobe-times-bold-r-normal--*-*-*-*-p-*-iso8859-1
+TBI -adobe-times-bold-i-normal--*-*-*-*-p-*-iso8859-1
+CR -adobe-courier-medium-r-normal--*-*-*-*-m-*-iso8859-1
+CI -adobe-courier-medium-o-normal--*-*-*-*-m-*-iso8859-1
+CB -adobe-courier-bold-r-normal--*-*-*-*-m-*-iso8859-1
+CBI -adobe-courier-bold-o-normal--*-*-*-*-m-*-iso8859-1
+HR -adobe-helvetica-medium-r-normal--*-*-*-*-p-*-iso8859-1
+HI -adobe-helvetica-medium-o-normal--*-*-*-*-p-*-iso8859-1
+HB -adobe-helvetica-bold-r-normal--*-*-*-*-p-*-iso8859-1
+HBI -adobe-helvetica-bold-o-normal--*-*-*-*-p-*-iso8859-1
+NR -adobe-new century schoolbook-medium-r-normal--*-*-*-*-p-*-iso8859-1
+NI -adobe-new century schoolbook-medium-i-normal--*-*-*-*-p-*-iso8859-1
+NB -adobe-new century schoolbook-bold-r-normal--*-*-*-*-p-*-iso8859-1
+NBI -adobe-new century schoolbook-bold-i-normal--*-*-*-*-p-*-iso8859-1
+S -adobe-symbol-medium-r-normal--*-*-*-*-p-*-adobe-fontspecific
diff --git a/gnu/usr.bin/groff/xditview/GXditview.ad b/gnu/usr.bin/groff/xditview/GXditview.ad
new file mode 100644
index 000000000000..e99ff5e16f38
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/GXditview.ad
@@ -0,0 +1,57 @@
+GXditview.height: 840
+
+GXditview.paned.allowResize: true
+GXditview.paned.viewport.allowVert: true
+GXditview.paned.viewport.allowHoriz: true
+GXditview.paned.viewport.skipAdjust: false
+GXditview.paned.viewport.width: 600
+GXditview.paned.viewport.height: 800
+GXditview.paned.viewport.showGrip: false
+GXditview.paned.label.skipAdjust: true
+
+GXditview.paned.viewport.dvi.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\
+ <Key>Next: NextPage()\n\
+ <Key>n: NextPage()\n\
+ <Key>space: NextPage()\n\
+ <Key>Return: NextPage()\n\
+ <Key>Prior: PreviousPage()\n\
+ <Key>p: PreviousPage()\n\
+ <Key>BackSpace: PreviousPage()\n\
+ <Key>Delete: PreviousPage()\n\
+ <Key>Select: SelectPage()\n\
+ <Key>Find: OpenFile()\n\
+ <Key>r: Rerasterize()\n\
+ <Key>q: Quit()
+GXditview.paned.label.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\
+ <Key>Next: NextPage()\n\
+ <Key>n: NextPage()\n\
+ <Key>space: NextPage()\n\
+ <Key>Return: NextPage()\n\
+ <Key>Prior: PreviousPage()\n\
+ <Key>p: PreviousPage()\n\
+ <Key>BackSpace: PreviousPage()\n\
+ <Key>Delete: PreviousPage()\n\
+ <Key>Select: SelectPage()\n\
+ <Key>Find: OpenFile()\n\
+ <Key>r: Rerasterize()\n\
+ <Key>q: Quit()
+GXditview.menu.nextPage.label: Next Page
+GXditview.menu.previousPage.label: Previous Page
+GXditview.menu.selectPage.label: Select Page
+GXditview.menu.print.label: Print
+GXditview.menu.openFile.label: Open
+GXditview.menu.quit.label: Quit
+
+GXditview.promptShell.allowShellResize: true
+GXditview.promptShell.promptDialog.value.translations: #override \
+ <Key>Return: Accept()
+
+GXditview.promptShell.promptDialog.accept.label: Accept
+GXditview.promptShell.promptDialog.accept.translations: #override \
+ <BtnUp>: Accept() unset()
+
+GXditview.promptShell.promptDialog.cancel.label: Cancel
+GXditview.promptShell.promptDialog.cancel.translations: #override \
+ <BtnUp>: Cancel() unset()
diff --git a/gnu/usr.bin/groff/xditview/INSTALL b/gnu/usr.bin/groff/xditview/INSTALL
new file mode 100644
index 000000000000..144118fd7d42
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/INSTALL
@@ -0,0 +1,20 @@
+This version of gxditview uses imake.
+
+Here are the steps needed to install gxditview:
+
+- edit the Imakefile if necessary
+
+- xmkmf
+
+- make depend
+
+- make
+
+- make install
+
+- make install.man (installs the man page)
+
+The gxditview binary will be installed in the usual place for X
+binaries (eg /usr/bin/X11). Previous versions of gxditview were
+installed along with the other groff binaries (eg in /usr/local/bin);
+you will need to remove these by hand.
diff --git a/gnu/usr.bin/groff/xditview/Imakefile b/gnu/usr.bin/groff/xditview/Imakefile
new file mode 100644
index 000000000000..62ac707f24a2
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/Imakefile
@@ -0,0 +1,52 @@
+GROFF_LIBDIR = /usr/local/lib/groff
+GROFF_FONTDIR = $(GROFF_LIBDIR)/font
+GROFF_FONTPATH = .:$(GROFF_FONTDIR):/usr/local/lib/font:/usr/lib/font
+DPIS = 75 100
+
+PROGRAMS = gxditview xtotroff
+DEPLIBS = XawClientDepLibs
+LOCAL_LIBRARIES = XawClientLibs
+SRCS1 = xditview.c Dvi.c draw.c font.c lex.c page.c \
+ parse.c XFontName.c DviChar.c device.c
+OBJS1 = xditview.o Dvi.o draw.o font.o lex.o page.o \
+ parse.o XFontName.o DviChar.o device.o
+SRCS2 = xtotroff.c XFontName.c DviChar.c
+OBJS2 = xtotroff.o XFontName.o DviChar.o
+INCLUDES = -I$(TOOLKITSRC) -I$(TOP)
+MATHLIB = -lm
+DEFINES = $(SIGNAL_DEFINES) -DFONTPATH=\"$(GROFF_FONTPATH)\" # -DX_NOT_STDC_ENV
+
+ComplexProgramTarget_1(gxditview,$(LOCAL_LIBRARIES),$(MATHLIB))
+NormalProgramTarget(xtotroff,$(OBJS2),$(DEPXLIB),$(XLIB), /**/)
+
+InstallAppDefaults(GXditview)
+
+fonts: xtotroff DESC FontMap
+ @dir=`pwd`; \
+ fonts=`sed -e 's/[ ].*//' FontMap`; \
+ for dpi in $(DPIS); do \
+ echo Making devX$$dpi; \
+ test -d ../devX$$dpi || mkdir ../devX$$dpi; \
+ rm -f ../devX$$dpi/DESC; \
+ sed -e "s/res 75/res $$dpi/" DESC >../devX$$dpi/DESC; \
+ (cd ../devX$$dpi; \
+ rm -f Makefile.sub; \
+ echo DEV=X$$dpi >Makefile.sub; \
+ echo DEVFILES=DESC $$fonts >>Makefile.sub; \
+ $$dir/xtotroff -g -r $$dpi -s 10 $$dir/FontMap); \
+ echo Making devX$$dpi-12; \
+ test -d ../devX$$dpi-12 || mkdir ../devX$$dpi-12; \
+ rm -f ../devX$$dpi-12/DESC; \
+ sed -e "s/res 75/res $$dpi/" -e 's/unitwidth 10/unitwidth 12/' DESC \
+ >../devX$$dpi-12/DESC; \
+ (cd ../devX$$dpi-12; \
+ rm -f Makefile.sub; \
+ echo DEV=X$$dpi-12 >Makefile.sub; \
+ echo DEVFILES=DESC $$fonts >>Makefile.sub; \
+ $$dir/xtotroff -g -r $$dpi -s 12 $$dir/FontMap); \
+ done
+
+extraclean: clean
+ -rm -f junk tmp grot old
+
+FORCE:
diff --git a/gnu/usr.bin/groff/xditview/Makefile b/gnu/usr.bin/groff/xditview/Makefile
new file mode 100644
index 000000000000..bce085ec7a8e
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/Makefile
@@ -0,0 +1,30 @@
+.if exists(${X11BASE}/include)
+.if exists(${X11BASE}/lib)
+.if exists(${DESTDIR}${X11BASE}/bin)
+.if exists(${DESTDIR}${X11BASE}/man/man1)
+.if exists(${DESTDIR}${X11BASE}/lib/X11/app-defaults)
+
+BINDIR= ${X11BASE}/bin
+MANDIR= ${X11BASE}/man/man
+
+PROG= gxditview
+CFLAGS+= -I${X11BASE}/include -DFONTPATH=\"/usr/share/groff_font\"
+SRCS+= xditview.c Dvi.c draw.c font.c lex.c page.c parse.c \
+ XFontName.c DviChar.c device.c
+LDDESTDIR+= -L${X11BASE}/lib
+LDADD+= -lXaw -lXmu -lXt -lXext -lX11 -lm
+DPADD+= ${X11BASE}/lib/libXaw.a ${X11BASE}/lib/libXmu.a \
+ ${X11BASE}/lib/libXt.a ${X11BASE}/lib/libXext.a \
+ ${X11BASE}/lib/libX11.a
+
+afterinstall:
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${.CURDIR}/GXditview.ad \
+ ${DESTDIR}${X11BASE}/lib/X11/app-defaults/GXditview
+.endif
+.endif
+.endif
+.endif
+.endif
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/xditview/Menu.h b/gnu/usr.bin/groff/xditview/Menu.h
new file mode 100644
index 000000000000..c306b2740a61
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/Menu.h
@@ -0,0 +1,46 @@
+/*
+ * $XConsortium: Menu.h,v 1.2 89/07/21 14:22:10 jim Exp $
+ */
+
+#ifndef _XtMenu_h
+#define _XtMenu_h
+
+/***********************************************************************
+ *
+ * Menu Widget
+ *
+ ***********************************************************************/
+
+/* Parameters:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ background Background pixel White
+ border BorderColor pixel Black
+ borderWidth BorderWidth int 1
+ height Height int 120
+ mappedWhenManaged MappedWhenManaged Boolean True
+ reverseVideo ReverseVideo Boolean False
+ width Width int 120
+ x Position int 0
+ y Position int 0
+
+*/
+
+#define XtNmenuEntries "menuEntries"
+#define XtNhorizontalPadding "horizontalPadding"
+#define XtNverticalPadding "verticalPadding"
+#define XtNselection "Selection"
+
+#define XtCMenuEntries "MenuEntries"
+#define XtCPadding "Padding"
+#define XtCSelection "Selection"
+
+typedef struct _MenuRec *MenuWidget; /* completely defined in MenuPrivate.h */
+typedef struct _MenuClassRec *MenuWidgetClass; /* completely defined in MenuPrivate.h */
+
+extern WidgetClass menuWidgetClass;
+
+extern Widget XawMenuCreate ();
+#endif /* _XtMenu_h */
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/gnu/usr.bin/groff/xditview/README b/gnu/usr.bin/groff/xditview/README
new file mode 100644
index 000000000000..b99a9918575b
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/README
@@ -0,0 +1,14 @@
+This is gxditview, a X11 previewer for groff based on MIT's xditview.
+This version can be used with the output of gtroff -Tps as well as
+with -TX75 and -TX100. You will need X11R5 to install it (it might
+work on X11R4, but I haven't tested it.)
+
+See the file INSTALL in this directory for installation instructions.
+
+xditview is copyrighted by MIT under the usual X terms (see
+gxditview.man); my changes to it are in the public domain.
+
+Please report bugs to bug-groff@prep.ai.mit.edu.
+
+James Clark
+jjc@jclark.com
diff --git a/gnu/usr.bin/groff/xditview/TODO b/gnu/usr.bin/groff/xditview/TODO
new file mode 100644
index 000000000000..88a0dae2eae6
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/TODO
@@ -0,0 +1,15 @@
+Better error handling.
+
+Resource and command-line option to specify font path.
+
+Resource to specify name of environment variable from which to get the
+font path.
+
+Have character substitutions (currently done in draw.c:FakeCharacter)
+specified in a resource (similar format to FontMap).
+
+The initial width of the dialog box should expand to accomodate the
+default value.
+
+Option in Print dialog to specify that only the current page should be
+printed.
diff --git a/gnu/usr.bin/groff/xditview/XFontName.c b/gnu/usr.bin/groff/xditview/XFontName.c
new file mode 100644
index 000000000000..5ca9bb81e996
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/XFontName.c
@@ -0,0 +1,256 @@
+/*
+ * XFontName.c
+ *
+ * build/parse X Font name strings
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "XFontName.h"
+#include <ctype.h>
+
+static char *
+extractStringField (name, buffer, size, attrp, bit)
+ char *name;
+ char *buffer;
+ int size;
+ unsigned int *attrp;
+ unsigned int bit;
+{
+ char *buf = buffer;
+
+ if (!*name)
+ return 0;
+ while (*name && *name != '-' && size > 0) {
+ *buf++ = *name++;
+ --size;
+ }
+ if (size <= 0)
+ return 0;
+ *buf = '\0';
+ if (buffer[0] != '*' || buffer[1] != '\0')
+ *attrp |= bit;
+ if (*name == '-')
+ return name+1;
+ return name;
+}
+
+static char *
+extractUnsignedField (name, result, attrp, bit)
+ char *name;
+ unsigned int *result;
+ unsigned int *attrp;
+ unsigned int bit;
+{
+ char buf[256];
+ char *c;
+ unsigned int i;
+
+ name = extractStringField (name, buf, sizeof (buf), attrp, bit);
+ if (!name)
+ return 0;
+ if (!(*attrp & bit))
+ return name;
+ i = 0;
+ for (c = buf; *c; c++) {
+ if (!isdigit (*c))
+ return 0;
+ i = i * 10 + (*c - '0');
+ }
+ *result = i;
+ return name;
+}
+
+Bool
+XParseFontName (fontNameString, fontName, fontNameAttributes)
+ XFontNameString fontNameString;
+ XFontName *fontName;
+ unsigned int *fontNameAttributes;
+{
+ char *name = fontNameString;
+ XFontName temp;
+ unsigned int attributes = 0;
+
+#define GetString(field,bit)\
+ if (!(name = extractStringField \
+ (name, temp.field, sizeof (temp.field),\
+ &attributes, bit))) \
+ return False;
+
+#define GetUnsigned(field,bit)\
+ if (!(name = extractUnsignedField \
+ (name, &temp.field, \
+ &attributes, bit))) \
+ return False;
+
+ GetString (Registry, FontNameRegistry)
+ GetString (Foundry, FontNameFoundry)
+ GetString (FamilyName, FontNameFamilyName)
+ GetString (WeightName, FontNameWeightName)
+ GetString (Slant, FontNameSlant)
+ GetString (SetwidthName, FontNameSetwidthName)
+ GetString (AddStyleName, FontNameAddStyleName)
+ GetUnsigned (PixelSize, FontNamePixelSize)
+ GetUnsigned (PointSize, FontNamePointSize)
+ GetUnsigned (ResolutionX, FontNameResolutionX)
+ GetUnsigned (ResolutionY, FontNameResolutionY)
+ GetString (Spacing, FontNameSpacing)
+ GetUnsigned (AverageWidth, FontNameAverageWidth)
+ GetString (CharSetRegistry, FontNameCharSetRegistry)
+ if (!*name) {
+ temp.CharSetEncoding[0] = '\0';
+ attributes |= FontNameCharSetEncoding;
+ } else {
+ GetString (CharSetEncoding, FontNameCharSetEncoding)
+ }
+ *fontName = temp;
+ *fontNameAttributes = attributes;
+ return True;
+}
+
+static char *
+utoa (u, s, size)
+ unsigned int u;
+ char *s;
+ int size;
+{
+ char *t;
+
+ t = s + size;
+ *--t = '\0';
+ do
+ *--t = (u % 10) + '0';
+ while (u /= 10);
+ return t;
+}
+
+Bool
+XFormatFontName (fontName, fontNameAttributes, fontNameString)
+ XFontName *fontName;
+ unsigned int fontNameAttributes;
+ XFontNameString fontNameString;
+{
+ XFontNameString tmp;
+ char *name = tmp, *f;
+ int left = sizeof (tmp) - 1;
+ char number[32];
+
+#define PutString(field, bit)\
+ f = (fontNameAttributes & bit) ? \
+ fontName->field \
+ : "*"; \
+ if ((left -= strlen (f)) < 0) \
+ return False; \
+ while (*f) \
+ if ((*name++ = *f++) == '-') \
+ return False;
+#define PutHyphen()\
+ if (--left < 0) \
+ return False; \
+ *name++ = '-';
+
+#define PutUnsigned(field, bit) \
+ f = (fontNameAttributes & bit) ? \
+ utoa (fontName->field, number, sizeof (number)) \
+ : "*"; \
+ if ((left -= strlen (f)) < 0) \
+ return False; \
+ while (*f) \
+ *name++ = *f++;
+
+ PutString (Registry, FontNameRegistry)
+ PutHyphen ();
+ PutString (Foundry, FontNameFoundry)
+ PutHyphen ();
+ PutString (FamilyName, FontNameFamilyName)
+ PutHyphen ();
+ PutString (WeightName, FontNameWeightName)
+ PutHyphen ();
+ PutString (Slant, FontNameSlant)
+ PutHyphen ();
+ PutString (SetwidthName, FontNameSetwidthName)
+ PutHyphen ();
+ PutString (AddStyleName, FontNameAddStyleName)
+ PutHyphen ();
+ PutUnsigned (PixelSize, FontNamePixelSize)
+ PutHyphen ();
+ PutUnsigned (PointSize, FontNamePointSize)
+ PutHyphen ();
+ PutUnsigned (ResolutionX, FontNameResolutionX)
+ PutHyphen ();
+ PutUnsigned (ResolutionY, FontNameResolutionY)
+ PutHyphen ();
+ PutString (Spacing, FontNameSpacing)
+ PutHyphen ();
+ PutUnsigned (AverageWidth, FontNameAverageWidth)
+ PutHyphen ();
+ PutString (CharSetRegistry, FontNameCharSetRegistry)
+ PutHyphen ();
+ PutString (CharSetEncoding, FontNameCharSetEncoding)
+ *name = '\0';
+ strcpy (fontNameString, tmp);
+ return True;
+}
+
+Bool
+XCompareFontName (name1, name2, fontNameAttributes)
+ XFontName *name1, *name2;
+ unsigned int fontNameAttributes;
+{
+#define CompareString(field,bit) \
+ if (fontNameAttributes & bit) \
+ if (strcmp (name1->field, name2->field)) \
+ return False;
+
+#define CompareUnsigned(field,bit) \
+ if (fontNameAttributes & bit) \
+ if (name1->field != name2->field) \
+ return False;
+
+ CompareString (Registry, FontNameRegistry)
+ CompareString (Foundry, FontNameFoundry)
+ CompareString (FamilyName, FontNameFamilyName)
+ CompareString (WeightName, FontNameWeightName)
+ CompareString (Slant, FontNameSlant)
+ CompareString (SetwidthName, FontNameSetwidthName)
+ CompareString (AddStyleName, FontNameAddStyleName)
+ CompareUnsigned (PixelSize, FontNamePixelSize)
+ CompareUnsigned (PointSize, FontNamePointSize)
+ CompareUnsigned (ResolutionX, FontNameResolutionX)
+ CompareUnsigned (ResolutionY, FontNameResolutionY)
+ CompareString (Spacing, FontNameSpacing)
+ CompareUnsigned (AverageWidth, FontNameAverageWidth)
+ CompareString (CharSetRegistry, FontNameCharSetRegistry)
+ CompareString (CharSetEncoding, FontNameCharSetEncoding)
+ return True;
+}
+
+XCopyFontName (name1, name2, fontNameAttributes)
+ XFontName *name1, *name2;
+ unsigned int fontNameAttributes;
+{
+#define CopyString(field,bit) \
+ if (fontNameAttributes & bit) \
+ strcpy (name2->field, name1->field);
+
+#define CopyUnsigned(field,bit) \
+ if (fontNameAttributes & bit) \
+ name2->field = name1->field;
+
+ CopyString (Registry, FontNameRegistry)
+ CopyString (Foundry, FontNameFoundry)
+ CopyString (FamilyName, FontNameFamilyName)
+ CopyString (WeightName, FontNameWeightName)
+ CopyString (Slant, FontNameSlant)
+ CopyString (SetwidthName, FontNameSetwidthName)
+ CopyString (AddStyleName, FontNameAddStyleName)
+ CopyUnsigned (PixelSize, FontNamePixelSize)
+ CopyUnsigned (PointSize, FontNamePointSize)
+ CopyUnsigned (ResolutionX, FontNameResolutionX)
+ CopyUnsigned (ResolutionY, FontNameResolutionY)
+ CopyString (Spacing, FontNameSpacing)
+ CopyUnsigned (AverageWidth, FontNameAverageWidth)
+ CopyString (CharSetRegistry, FontNameCharSetRegistry)
+ CopyString (CharSetEncoding, FontNameCharSetEncoding)
+ return True;
+}
diff --git a/gnu/usr.bin/groff/xditview/XFontName.h b/gnu/usr.bin/groff/xditview/XFontName.h
new file mode 100644
index 000000000000..efe9eb16d1d4
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/XFontName.h
@@ -0,0 +1,45 @@
+typedef struct _xFontName {
+ char Registry[256];
+ char Foundry[256];
+ char FamilyName[256];
+ char WeightName[256];
+ char Slant[3];
+ char SetwidthName[256];
+ char AddStyleName[256];
+ unsigned int PixelSize;
+ unsigned int PointSize;
+ unsigned int ResolutionX;
+ unsigned int ResolutionY;
+ char Spacing[2];
+ unsigned int AverageWidth;
+ char CharSetRegistry[256];
+ char CharSetEncoding[256];
+} XFontName;
+
+#define FontNameRegistry (1<<0)
+#define FontNameFoundry (1<<1)
+#define FontNameFamilyName (1<<2)
+#define FontNameWeightName (1<<3)
+#define FontNameSlant (1<<4)
+#define FontNameSetwidthName (1<<5)
+#define FontNameAddStyleName (1<<6)
+#define FontNamePixelSize (1<<7)
+#define FontNamePointSize (1<<8)
+#define FontNameResolutionX (1<<9)
+#define FontNameResolutionY (1<<10)
+#define FontNameSpacing (1<<11)
+#define FontNameAverageWidth (1<<12)
+#define FontNameCharSetRegistry (1<<13)
+#define FontNameCharSetEncoding (1<<14)
+
+#define SlantRoman "R"
+#define SlantItalic "I"
+#define SlantOblique "O"
+#define SlantReverseItalic "RI"
+#define SlantReverseOblique "RO"
+
+#define SpacingMonoSpaced "M"
+#define SpacingProportional "P"
+#define SpacingCharacterCell "C"
+
+typedef char XFontNameString[256];
diff --git a/gnu/usr.bin/groff/xditview/device.c b/gnu/usr.bin/groff/xditview/device.c
new file mode 100644
index 000000000000..740f93f72b29
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/device.c
@@ -0,0 +1,587 @@
+/* device.c */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+
+#include "device.h"
+
+#ifndef FONTPATH
+#define FONTPATH "/usr/local/lib/groff/font:/usr/local/lib/font:/usr/lib/font"
+#endif
+
+extern void exit();
+extern char *strtok(), *strchr();
+extern char *getenv();
+
+/* Name of environment variable containing path to be used for
+searching for device and font description files. */
+#define FONTPATH_ENV_VAR "GROFF_FONT_PATH"
+
+#define WS " \t\r\n"
+
+/* Minimum and maximum values a `signed int' can hold. */
+
+#ifndef INT_MIN
+#define INT_MIN (-INT_MAX-1)
+#endif
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+
+#define CHAR_TABLE_SIZE 307
+
+struct _DeviceFont {
+ char *name;
+ int special;
+ DeviceFont *next;
+ Device *dev;
+ struct charinfo *char_table[CHAR_TABLE_SIZE];
+ struct charinfo *code_table[256];
+};
+
+struct charinfo {
+ int width;
+ int code;
+ struct charinfo *next;
+ struct charinfo *code_next;
+ char name[1];
+};
+
+static char *current_filename = 0;
+static int current_lineno = -1;
+
+static void error();
+static FILE *open_device_file();
+static DeviceFont *load_font();
+static Device *new_device();
+static DeviceFont *new_font();
+static void delete_font();
+static unsigned hash_name();
+static struct charinfo *add_char();
+static int read_charset_section();
+static char *canonicalize_name();
+
+static
+Device *new_device(name)
+ char *name;
+{
+ Device *dev;
+
+ dev = XtNew(Device);
+ dev->sizescale = 1;
+ dev->res = 0;
+ dev->unitwidth = 0;
+ dev->fonts = 0;
+ dev->X11 = 0;
+ dev->paperlength = 0;
+ dev->paperwidth = 0;
+ dev->name = XtNewString(name);
+ return dev;
+}
+
+void device_destroy(dev)
+ Device *dev;
+{
+ DeviceFont *f;
+
+ if (!dev)
+ return;
+ f = dev->fonts;
+ while (f) {
+ DeviceFont *tem = f;
+ f = f->next;
+ delete_font(tem);
+ }
+
+ XtFree(dev->name);
+ XtFree((char *)dev);
+}
+
+Device *device_load(name)
+ char *name;
+{
+ Device *dev;
+ FILE *fp;
+ int err = 0;
+ char buf[256];
+
+ fp = open_device_file(name, "DESC", &current_filename);
+ if (!fp)
+ return 0;
+ dev = new_device(name);
+ current_lineno = 0;
+ while (fgets(buf, sizeof(buf), fp)) {
+ char *p;
+ current_lineno++;
+ p = strtok(buf, WS);
+ if (p) {
+ int *np = 0;
+ char *q;
+
+ if (strcmp(p, "charset") == 0)
+ break;
+ if (strcmp(p, "X11") == 0)
+ dev->X11 = 1;
+ else if (strcmp(p, "sizescale") == 0)
+ np = &dev->sizescale;
+ else if (strcmp(p, "res") == 0)
+ np = &dev->res;
+ else if (strcmp(p, "unitwidth") == 0)
+ np = &dev->unitwidth;
+ else if (strcmp(p, "paperwidth") == 0)
+ np = &dev->paperwidth;
+ else if (strcmp(p, "paperlength") == 0)
+ np = &dev->paperlength;
+
+ if (np) {
+ q = strtok((char *)0, WS);
+ if (!q || sscanf(q, "%d", np) != 1 || *np <= 0) {
+ error("bad argument");
+ err = 1;
+ break;
+ }
+ }
+ }
+ }
+ fclose(fp);
+ current_lineno = -1;
+ if (!err) {
+ if (dev->res == 0) {
+ error("missing res line");
+ err = 1;
+ }
+ else if (dev->unitwidth == 0) {
+ error("missing unitwidth line");
+ err = 1;
+ }
+ }
+ if (dev->paperlength == 0)
+ dev->paperlength = dev->res*11;
+ if (dev->paperwidth == 0)
+ dev->paperwidth = dev->res*8 + dev->res/2;
+ if (err) {
+ device_destroy(dev);
+ dev = 0;
+ }
+ XtFree(current_filename);
+ current_filename = 0;
+ return dev;
+}
+
+
+DeviceFont *device_find_font(dev, name)
+ Device *dev;
+ char *name;
+{
+ DeviceFont *f;
+
+ if (!dev)
+ return 0;
+ for (f = dev->fonts; f; f = f->next)
+ if (strcmp(f->name, name) == 0)
+ return f;
+ return load_font(dev, name);
+}
+
+static
+DeviceFont *load_font(dev, name)
+ Device *dev;
+ char *name;
+{
+ FILE *fp;
+ char buf[256];
+ DeviceFont *f;
+ int special = 0;
+
+ fp = open_device_file(dev->name, name, &current_filename);
+ if (!fp)
+ return 0;
+ current_lineno = 0;
+ for (;;) {
+ char *p;
+
+ if (!fgets(buf, sizeof(buf), fp)) {
+ error("no charset line");
+ return 0;
+ }
+ current_lineno++;
+ p = strtok(buf, WS);
+ /* charset must be on a line by itself */
+ if (p && strcmp(p, "charset") == 0 && strtok((char *)0, WS) == 0)
+ break;
+ if (p && strcmp(p, "special") == 0)
+ special = 1;
+ }
+ f = new_font(name, dev);
+ f->special = special;
+ if (!read_charset_section(f, fp)) {
+ delete_font(f);
+ f = 0;
+ }
+ else {
+ f->next = dev->fonts;
+ dev->fonts = f;
+ }
+ fclose(fp);
+ XtFree(current_filename);
+ current_filename = 0;
+ return f;
+}
+
+static
+DeviceFont *new_font(name, dev)
+ char *name;
+ Device *dev;
+{
+ int i;
+ DeviceFont *f;
+
+ f = XtNew(DeviceFont);
+ f->name = XtNewString(name);
+ f->dev = dev;
+ f->special = 0;
+ f->next = 0;
+ for (i = 0; i < CHAR_TABLE_SIZE; i++)
+ f->char_table[i] = 0;
+ for (i = 0; i < 256; i++)
+ f->code_table[i] = 0;
+ return f;
+}
+
+static
+void delete_font(f)
+ DeviceFont *f;
+{
+ int i;
+
+ if (!f)
+ return;
+ XtFree(f->name);
+ for (i = 0; i < CHAR_TABLE_SIZE; i++) {
+ struct charinfo *ptr = f->char_table[i];
+ while (ptr) {
+ struct charinfo *tem = ptr;
+ ptr = ptr->next;
+ XtFree((char *)tem);
+ }
+ }
+ XtFree((char *)f);
+}
+
+
+static
+unsigned hash_name(name)
+ char *name;
+{
+ unsigned n = 0;
+ /* XXX do better than this */
+ while (*name)
+ n = (n << 1) ^ *name++;
+
+ return n;
+}
+
+static
+int scale_round(n, x, y)
+ int n, x, y;
+{
+ int y2;
+
+ if (x == 0)
+ return 0;
+ y2 = y/2;
+ if (n >= 0) {
+ if (n <= (INT_MAX - y2)/x)
+ return (n*x + y2)/y;
+ }
+ else if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)
+ return (n*x - y2)/y;
+ return (int)(n*(double)x/(double)y + .5);
+}
+
+static
+char *canonicalize_name(s)
+ char *s;
+{
+ static char ch[2];
+ if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
+ char *p;
+ int n;
+
+ for (p = s + 4; *p; p++)
+ if (!isascii(*p) || !isdigit(*p))
+ return s;
+ n = atoi(s + 4);
+ if (n >= 0 && n <= 0xff) {
+ ch[0] = (char)n;
+ return ch;
+ }
+ }
+ return s;
+}
+
+/* Return 1 if the character is present in the font; widthp gets the
+width if non-null. */
+
+int device_char_width(f, ps, name, widthp)
+ DeviceFont *f;
+ int ps;
+ char *name;
+ int *widthp;
+{
+ struct charinfo *p;
+
+ name = canonicalize_name(name);
+ for (p = f->char_table[hash_name(name) % CHAR_TABLE_SIZE];; p = p->next) {
+ if (!p)
+ return 0;
+ if (strcmp(p->name, name) == 0)
+ break;
+ }
+ *widthp = scale_round(p->width, ps, f->dev->unitwidth);
+ return 1;
+}
+
+int device_code_width(f, ps, code, widthp)
+ DeviceFont *f;
+ int ps;
+ int code;
+ int *widthp;
+{
+ struct charinfo *p;
+
+ for (p = f->code_table[code & 0xff];; p = p->code_next) {
+ if (!p)
+ return 0;
+ if (p->code == code)
+ break;
+ }
+ *widthp = scale_round(p->width, ps, f->dev->unitwidth);
+ return 1;
+}
+
+char *device_name_for_code(f, code)
+ DeviceFont *f;
+ int code;
+{
+ static struct charinfo *state = 0;
+ if (f)
+ state = f->code_table[code & 0xff];
+ for (; state; state = state->code_next)
+ if (state->code == code && state->name[0] != '\0') {
+ char *name = state->name;
+ state = state->code_next;
+ return name;
+ }
+ return 0;
+}
+
+int device_font_special(f)
+ DeviceFont *f;
+{
+ return f->special;
+}
+
+static
+struct charinfo *add_char(f, name, width, code)
+ DeviceFont *f;
+ char *name;
+ int width, code;
+{
+ struct charinfo **pp;
+ struct charinfo *ci;
+
+ name = canonicalize_name(name);
+ if (strcmp(name, "---") == 0)
+ name = "";
+
+ ci = (struct charinfo *)XtMalloc(XtOffsetOf(struct charinfo, name[0])
+ + strlen(name) + 1);
+
+ strcpy(ci->name, name);
+ ci->width = width;
+ ci->code = code;
+
+ if (*name != '\0') {
+ pp = &f->char_table[hash_name(name) % CHAR_TABLE_SIZE];
+ ci->next = *pp;
+ *pp = ci;
+ }
+ pp = &f->code_table[code & 0xff];
+ ci->code_next = *pp;
+ *pp = ci;
+ return ci;
+}
+
+/* Return non-zero for success. */
+
+static
+int read_charset_section(f, fp)
+ DeviceFont *f;
+ FILE *fp;
+{
+ struct charinfo *last_charinfo = 0;
+ char buf[256];
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ char *name;
+ int width;
+ int code;
+ char *p;
+
+ current_lineno++;
+ name = strtok(buf, WS);
+ if (!name)
+ continue; /* ignore blank lines */
+ p = strtok((char *)0, WS);
+ if (!p) /* end of charset section */
+ break;
+ if (strcmp(p, "\"") == 0) {
+ if (!last_charinfo) {
+ error("first line of charset section cannot use `\"'");
+ return 0;
+ }
+ else
+ (void)add_char(f, name,
+ last_charinfo->width, last_charinfo->code);
+ }
+ else {
+ char *q;
+ if (sscanf(p, "%d", &width) != 1) {
+ error("bad width field");
+ return 0;
+ }
+ p = strtok((char *)0, WS);
+ if (!p) {
+ error("missing type field");
+ return 0;
+ }
+ p = strtok((char *)0, WS);
+ if (!p) {
+ error("missing code field");
+ return 0;
+ }
+ code = (int)strtol(p, &q, 0);
+ if (q == p) {
+ error("bad code field");
+ return 0;
+ }
+ last_charinfo = add_char(f, name, width, code);
+ }
+ }
+ return 1;
+}
+
+static
+FILE *find_file(file, path, result)
+ char *file, *path, **result;
+{
+ char *buf = NULL;
+ int bufsiz = 0;
+ int flen;
+ FILE *fp;
+
+ *result = NULL;
+
+ if (file == NULL)
+ return NULL;
+ if (*file == '\0')
+ return NULL;
+
+ if (*file == '/') {
+ fp = fopen(file, "r");
+ if (fp)
+ *result = XtNewString(file);
+ return fp;
+ }
+
+ flen = strlen(file);
+
+ if (!path)
+ return NULL;
+
+ while (*path) {
+ int len;
+ char *start, *end;
+
+ start = path;
+ end = strchr(path, ':');
+ if (end)
+ path = end + 1;
+ else
+ path = end = strchr(path, '\0');
+ if (start >= end)
+ continue;
+ if (end[-1] == '/')
+ --end;
+ len = (end - start) + 1 + flen + 1;
+ if (len > bufsiz) {
+ if (buf)
+ buf = XtRealloc(buf, len);
+ else
+ buf = XtMalloc(len);
+ bufsiz = len;
+ }
+ memcpy(buf, start, end - start);
+ buf[end - start] = '/';
+ strcpy(buf + (end - start) + 1, file);
+ fp = fopen(buf, "r");
+ if (fp) {
+ *result = buf;
+ return fp;
+ }
+ }
+ XtFree(buf);
+ return NULL;
+}
+
+static
+FILE *open_device_file(device_name, file_name, result)
+ char *device_name, *file_name, **result;
+{
+ char *buf, *path;
+ FILE *fp;
+
+ buf = XtMalloc(3 + strlen(device_name) + 1 + strlen(file_name) + 1);
+ sprintf(buf, "dev%s/%s", device_name, file_name);
+ path = getenv(FONTPATH_ENV_VAR);
+ if (!path)
+ path = FONTPATH;
+ fp = find_file(buf, path, result);
+ if (!fp) {
+ fprintf(stderr, "can't find device file `%s'\n", file_name);
+ fflush(stderr);
+ }
+ XtFree(buf);
+ return fp;
+}
+
+static
+void error(s)
+ char *s;
+{
+ if (current_filename) {
+ fprintf(stderr, "%s:", current_filename);
+ if (current_lineno > 0)
+ fprintf(stderr, "%d:", current_lineno);
+ putc(' ', stderr);
+ }
+ fputs(s, stderr);
+ putc('\n', stderr);
+ fflush(stderr);
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 4
+c-label-offset: -4
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/groff/xditview/device.h b/gnu/usr.bin/groff/xditview/device.h
new file mode 100644
index 000000000000..2b9a64bac90b
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/device.h
@@ -0,0 +1,21 @@
+
+typedef struct _DeviceFont DeviceFont;
+
+typedef struct _Device {
+ char *name;
+ int sizescale;
+ int res;
+ int unitwidth;
+ int paperlength;
+ int paperwidth;
+ int X11;
+ DeviceFont *fonts;
+} Device;
+
+extern void device_destroy();
+extern Device *device_load();
+extern DeviceFont *device_find_font();
+extern int device_char_width();
+extern char *device_name_for_code();
+extern int device_code_width();
+extern int device_font_special();
diff --git a/gnu/usr.bin/groff/xditview/draw.c b/gnu/usr.bin/groff/xditview/draw.c
new file mode 100644
index 000000000000..7715cde60bfc
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/draw.c
@@ -0,0 +1,721 @@
+/*
+ * draw.c
+ *
+ * accept dvi function calls and translate to X
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+
+/* math.h on a Sequent doesn't define M_PI, apparently */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#include "DviP.h"
+
+#define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5))
+#define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \
+ (dw)->dvi.text_device_width) + (dw)->dvi.text_x_width)
+#define YPos(dw) (DeviceToX((dw), (dw)->dvi.state->y))
+
+static int FakeCharacter();
+
+HorizontalMove(dw, delta)
+ DviWidget dw;
+ int delta;
+{
+ dw->dvi.state->x += delta;
+}
+
+HorizontalGoto(dw, NewPosition)
+ DviWidget dw;
+ int NewPosition;
+{
+ dw->dvi.state->x = NewPosition;
+}
+
+VerticalMove(dw, delta)
+ DviWidget dw;
+ int delta;
+{
+ dw->dvi.state->y += delta;
+}
+
+VerticalGoto(dw, NewPosition)
+ DviWidget dw;
+ int NewPosition;
+{
+ dw->dvi.state->y = NewPosition;
+}
+
+AdjustCacheDeltas (dw)
+ DviWidget dw;
+{
+ int extra;
+ int nadj;
+ int i;
+
+ nadj = 0;
+ extra = DeviceToX(dw, dw->dvi.text_device_width)
+ - dw->dvi.text_x_width;
+ if (extra == 0)
+ return;
+ for (i = 0; i <= dw->dvi.cache.index; i++)
+ if (dw->dvi.cache.adjustable[i])
+ ++nadj;
+ if (nadj == 0)
+ return;
+ dw->dvi.text_x_width += extra;
+ for (i = 0; i <= dw->dvi.cache.index; i++)
+ if (dw->dvi.cache.adjustable[i]) {
+ int x;
+ int *deltap;
+
+ x = extra/nadj;
+ deltap = &dw->dvi.cache.cache[i].delta;
+#define MIN_DELTA 2
+ if (*deltap > 0 && x + *deltap < MIN_DELTA) {
+ x = MIN_DELTA - *deltap;
+ if (x <= 0)
+ *deltap = MIN_DELTA;
+ else
+ x = 0;
+ }
+ else
+ *deltap += x;
+ extra -= x;
+ --nadj;
+ dw->dvi.cache.adjustable[i] = 0;
+ }
+}
+
+FlushCharCache (dw)
+ DviWidget dw;
+{
+ if (dw->dvi.cache.char_index != 0) {
+ AdjustCacheDeltas (dw);
+ XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ dw->dvi.cache.start_x, dw->dvi.cache.start_y,
+ dw->dvi.cache.cache, dw->dvi.cache.index + 1);
+ }
+ dw->dvi.cache.index = 0;
+ dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
+#if 0
+ if (dw->dvi.noPolyText)
+ dw->dvi.cache.max = 1;
+#endif
+ dw->dvi.cache.char_index = 0;
+ dw->dvi.cache.cache[0].nchars = 0;
+ dw->dvi.cache.start_x = dw->dvi.cache.x = XPos (dw);
+ dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw);
+}
+
+Newline (dw)
+ DviWidget dw;
+{
+ FlushCharCache (dw);
+ dw->dvi.text_x_width = dw->dvi.text_device_width = 0;
+ dw->dvi.word_flag = 0;
+}
+
+Word (dw)
+ DviWidget dw;
+{
+ dw->dvi.word_flag = 1;
+}
+
+#define charWidth(fi,c) (\
+ (fi)->per_char ?\
+ (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
+ :\
+ (fi)->max_bounds.width\
+)
+
+
+static
+int charExists (fi, c)
+ XFontStruct *fi;
+ int c;
+{
+ XCharStruct *p;
+
+ if (fi->per_char == NULL ||
+ c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
+ return 0;
+ p = fi->per_char + (c - fi->min_char_or_byte2);
+ return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
+ || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
+}
+
+static
+DoCharacter (dw, c, wid)
+ DviWidget dw;
+ int c;
+ int wid; /* width in device units */
+{
+ register XFontStruct *font;
+ register XTextItem *text;
+ int x, y;
+
+ x = XPos(dw);
+ y = YPos(dw);
+
+ /*
+ * quick and dirty extents calculation:
+ */
+ if (!(y + 24 >= dw->dvi.extents.y1
+ && y - 24 <= dw->dvi.extents.y2
+#if 0
+ && x + 24 >= dw->dvi.extents.x1
+ && x - 24 <= dw->dvi.extents.x2
+#endif
+ ))
+ return;
+
+ if (y != dw->dvi.cache.y
+ || dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE) {
+ FlushCharCache (dw);
+ x = dw->dvi.cache.x;
+ }
+ /*
+ * load a new font, if the current block is not empty,
+ * step to the next.
+ */
+ if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
+ dw->dvi.cache.font_number != dw->dvi.state->font_number)
+ {
+ dw->dvi.cache.font_size = dw->dvi.state->font_size;
+ dw->dvi.cache.font_number = dw->dvi.state->font_number;
+ dw->dvi.cache.font = QueryFont (dw,
+ dw->dvi.cache.font_number,
+ dw->dvi.cache.font_size);
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
+ }
+ }
+ if (x != dw->dvi.cache.x || dw->dvi.word_flag) {
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ }
+ dw->dvi.cache.adjustable[dw->dvi.cache.index]
+ = dw->dvi.word_flag;
+ dw->dvi.word_flag = 0;
+ }
+ font = dw->dvi.cache.font;
+ text = &dw->dvi.cache.cache[dw->dvi.cache.index];
+ if (text->nchars == 0) {
+ text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
+ text->delta = x - dw->dvi.cache.x;
+ if (font != dw->dvi.font) {
+ text->font = font->fid;
+ dw->dvi.font = font;
+ } else
+ text->font = None;
+ dw->dvi.cache.x += text->delta;
+ }
+ if (charExists(font, c)) {
+ int w;
+ dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
+ ++text->nchars;
+ w = charWidth(font, c);
+ dw->dvi.cache.x += w;
+ if (wid != 0) {
+ dw->dvi.text_x_width += w;
+ dw->dvi.text_device_width += wid;
+ }
+ }
+}
+
+static
+int FindCharWidth (dw, buf, widp)
+ DviWidget dw;
+ char *buf;
+ int *widp;
+{
+ int maxpos;
+ int i;
+
+ if (dw->dvi.device_font == 0
+ || dw->dvi.state->font_number != dw->dvi.device_font_number) {
+ dw->dvi.device_font_number = dw->dvi.state->font_number;
+ dw->dvi.device_font
+ = QueryDeviceFont (dw, dw->dvi.device_font_number);
+ }
+ if (dw->dvi.device_font
+ && device_char_width (dw->dvi.device_font,
+ dw->dvi.state->font_size, buf, widp))
+ return 1;
+
+ maxpos = MaxFontPosition (dw);
+ for (i = 1; i <= maxpos; i++) {
+ DeviceFont *f = QueryDeviceFont (dw, i);
+ if (f && device_font_special (f)
+ && device_char_width (f, dw->dvi.state->font_size,
+ buf, widp)) {
+ dw->dvi.state->font_number = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Return the width of the character in device units. */
+
+int PutCharacter (dw, buf)
+ DviWidget dw;
+ char *buf;
+{
+ int prevFont;
+ int c = -1;
+ int wid = 0;
+ DviCharNameMap *map;
+
+ if (!dw->dvi.display_enable)
+ return 0; /* The width doesn't matter in this case. */
+ prevFont = dw->dvi.state->font_number;
+ if (!FindCharWidth (dw, buf, &wid))
+ return 0;
+ map = QueryFontMap (dw, dw->dvi.state->font_number);
+ if (map)
+ c = DviCharIndex (map, buf);
+ if (c >= 0)
+ DoCharacter (dw, c, wid);
+ else
+ (void) FakeCharacter (dw, buf, wid);
+ dw->dvi.state->font_number = prevFont;
+ return wid;
+}
+
+/* Return 1 if we can fake it; 0 otherwise. */
+
+static
+int FakeCharacter (dw, buf, wid)
+ DviWidget dw;
+ char *buf;
+ int wid;
+{
+ int oldx, oldw;
+ char ch[2];
+ char *chars = 0;
+
+ if (buf[0] == '\0' || buf[1] == '\0' || buf[2] != '\0')
+ return 0;
+#define pack2(c1, c2) (((c1) << 8) | (c2))
+
+ switch (pack2(buf[0], buf[1])) {
+ case pack2('f', 'i'):
+ chars = "fi";
+ break;
+ case pack2('f', 'l'):
+ chars = "fl";
+ break;
+ case pack2('f', 'f'):
+ chars = "ff";
+ break;
+ case pack2('F', 'i'):
+ chars = "ffi";
+ break;
+ case pack2('F', 'l'):
+ chars = "ffl";
+ break;
+ }
+ if (!chars)
+ return 0;
+ oldx = dw->dvi.state->x;
+ oldw = dw->dvi.text_device_width;
+ ch[1] = '\0';
+ for (; *chars; chars++) {
+ ch[0] = *chars;
+ dw->dvi.state->x += PutCharacter (dw, ch);
+ }
+ dw->dvi.state->x = oldx;
+ dw->dvi.text_device_width = oldw + wid;
+ return 1;
+}
+
+PutNumberedCharacter (dw, c)
+ DviWidget dw;
+ int c;
+{
+ char *name;
+ int wid;
+ DviCharNameMap *map;
+
+ if (!dw->dvi.display_enable)
+ return;
+
+ if (dw->dvi.device_font == 0
+ || dw->dvi.state->font_number != dw->dvi.device_font_number) {
+ dw->dvi.device_font_number = dw->dvi.state->font_number;
+ dw->dvi.device_font
+ = QueryDeviceFont (dw, dw->dvi.device_font_number);
+ }
+
+ if (dw->dvi.device_font == 0
+ || !device_code_width (dw->dvi.device_font,
+ dw->dvi.state->font_size, c, &wid))
+ return;
+ if (dw->dvi.native) {
+ DoCharacter (dw, c, wid);
+ return;
+ }
+ map = QueryFontMap (dw, dw->dvi.state->font_number);
+ if (!map)
+ return;
+ for (name = device_name_for_code (dw->dvi.device_font, c);
+ name;
+ name = device_name_for_code ((DeviceFont *)0, c)) {
+ int code = DviCharIndex (map, name);
+ if (code >= 0) {
+ DoCharacter (dw, code, wid);
+ break;
+ }
+ if (FakeCharacter (dw, name, wid))
+ break;
+ }
+}
+
+ClearPage (dw)
+ DviWidget dw;
+{
+ XClearWindow (XtDisplay (dw), XtWindow (dw));
+}
+
+static
+setGC (dw)
+ DviWidget dw;
+{
+ int desired_line_width;
+
+ if (dw->dvi.line_thickness < 0)
+ desired_line_width = (int)(((double)dw->dvi.device_resolution
+ * dw->dvi.state->font_size)
+ / (10.0*72.0*dw->dvi.sizescale));
+ else
+ desired_line_width = dw->dvi.line_thickness;
+
+ if (desired_line_width != dw->dvi.line_width) {
+ XGCValues values;
+ values.line_width = DeviceToX(dw, desired_line_width);
+ if (values.line_width == 0)
+ values.line_width = 1;
+ XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
+ GCLineWidth, &values);
+ dw->dvi.line_width = desired_line_width;
+ }
+}
+
+static
+setFillGC (dw)
+ DviWidget dw;
+{
+ int fill_type;
+
+ if (dw->dvi.fill == DVI_FILL_MAX)
+ fill_type = DVI_FILL_BLACK;
+ else if (dw->dvi.fill == 0)
+ fill_type = DVI_FILL_WHITE;
+ else
+ fill_type = DVI_FILL_GRAY;
+ if (dw->dvi.fill_type != fill_type) {
+ XGCValues values;
+ switch (fill_type) {
+ case DVI_FILL_WHITE:
+ values.foreground = dw->dvi.background;
+ values.fill_style = FillSolid;
+ break;
+ case DVI_FILL_BLACK:
+ values.foreground = dw->dvi.foreground;
+ values.fill_style = FillSolid;
+ break;
+ case DVI_FILL_GRAY:
+ values.foreground = dw->dvi.foreground;
+ values.fill_style = FillOpaqueStippled;
+ break;
+ }
+ XChangeGC(XtDisplay (dw), dw->dvi.fill_GC,
+ GCFillStyle|GCForeground,
+ &values);
+ dw->dvi.fill_type = fill_type;
+ }
+}
+
+DrawLine (dw, x, y)
+ DviWidget dw;
+ int x, y;
+{
+ int xp, yp;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ xp = XPos (dw);
+ yp = YPos (dw);
+ XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ xp, yp,
+ xp + DeviceToX (dw, x), yp + DeviceToX (dw, y));
+}
+
+DrawCircle (dw, diam)
+ DviWidget dw;
+ int diam;
+{
+ int d;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ d = DeviceToX (dw, diam);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+}
+
+DrawFilledCircle (dw, diam)
+ DviWidget dw;
+ int diam;
+{
+ int d;
+
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ d = DeviceToX (dw, diam);
+ XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+}
+
+DrawEllipse (dw, a, b)
+ DviWidget dw;
+ int a, b;
+{
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+}
+
+DrawFilledEllipse (dw, a, b)
+ DviWidget dw;
+ int a, b;
+{
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+}
+
+DrawArc (dw, x0, y0, x1, y1)
+ DviWidget dw;
+ int x0, y0, x1, y1;
+{
+ int angle1, angle2;
+ int rad = (int)((sqrt ((double)x0*x0 + (double)y0*y0)
+ + sqrt ((double)x1*x1 + (double)y1*y1) + 1.0)/2.0);
+ if ((x0 == 0 && y0 == 0) || (x1 == 0 && y1 == 0))
+ return;
+ angle1 = (int)(atan2 ((double)y0, (double)-x0)*180.0*64.0/M_PI);
+ angle2 = (int)(atan2 ((double)-y1, (double)x1)*180.0*64.0/M_PI);
+
+ angle2 -= angle1;
+ if (angle2 < 0)
+ angle2 += 64*360;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+
+ rad = DeviceToX (dw, rad);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw) + DeviceToX (dw, x0) - rad,
+ YPos (dw) + DeviceToX (dw, y0) - rad,
+ rad*2, rad*2, angle1, angle2);
+}
+
+DrawPolygon (dw, v, n)
+ DviWidget dw;
+ int *v;
+ int n;
+{
+ XPoint *p;
+ int i;
+ int dx, dy;
+
+ n /= 2;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
+ p[0].x = XPos (dw);
+ p[0].y = YPos (dw);
+ dx = 0;
+ dy = 0;
+ for (i = 0; i < n; i++) {
+ dx += v[2*i];
+ p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
+ dy += v[2*i + 1];
+ p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
+ }
+ p[n+1].x = p[0].x;
+ p[n+1].y = p[0].y;
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ p, n + 2, CoordModeOrigin);
+ XtFree((char *)p);
+}
+
+
+DrawFilledPolygon (dw, v, n)
+ DviWidget dw;
+ int *v;
+ int n;
+{
+ XPoint *p;
+ int i;
+ int dx, dy;
+
+ n /= 2;
+ if (n < 2)
+ return;
+
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ p = (XPoint *)XtMalloc((n + 1)*sizeof(XPoint));
+ p[0].x = XPos (dw);
+ p[0].y = YPos (dw);
+ dx = 0;
+ dy = 0;
+ for (i = 0; i < n; i++) {
+ dx += v[2*i];
+ p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
+ dy += v[2*i + 1];
+ p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
+ }
+ XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ p, n + 1, Complex, CoordModeOrigin);
+ XtFree((char *)p);
+}
+
+#define POINTS_MAX 10000
+
+static
+appendPoint(points, pointi, x, y)
+ XPoint *points;
+ int *pointi;
+ int x, y;
+{
+ if (*pointi < POINTS_MAX) {
+ points[*pointi].x = x;
+ points[*pointi].y = y;
+ *pointi += 1;
+ }
+}
+
+#define FLATNESS 1
+
+static
+flattenCurve(points, pointi, x2, y2, x3, y3, x4, y4)
+ XPoint *points;
+ int *pointi;
+ int x2, y2, x3, y3, x4, y4;
+{
+ int x1, y1, dx, dy, n1, n2, n;
+
+ x1 = points[*pointi - 1].x;
+ y1 = points[*pointi - 1].y;
+
+ dx = x4 - x1;
+ dy = y4 - y1;
+
+ n1 = dy*(x2 - x1) - dx*(y2 - y1);
+ n2 = dy*(x3 - x1) - dx*(y3 - y1);
+ if (n1 < 0)
+ n1 = -n1;
+ if (n2 < 0)
+ n2 = -n2;
+ n = n1 > n2 ? n1 : n2;
+
+ if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
+ appendPoint (points, pointi, x4, y4);
+ else {
+ flattenCurve (points, pointi,
+ (x1 + x2)/2, (y1 + y2)/2,
+ (x1 + x2*2 + x3)/4, (y1 + y2*2 + y3)/4,
+ (x1 +3*x2 + 3*x3 + x4)/8, (y1 +3*y2 + 3*y3 + y4)/8);
+ flattenCurve (points, pointi,
+ (x2 + x3*2 + x4)/4, (y2 + y3*2 + y4)/4,
+ (x3 + x4)/2, (y3 + y4)/2,
+ x4, y4);
+ }
+}
+
+
+DrawSpline (dw, v, n)
+ DviWidget dw;
+ int *v;
+ int n;
+{
+ int sx, sy, tx, ty;
+ int ox, oy, dx, dy;
+ int i;
+ int pointi;
+ XPoint points[POINTS_MAX];
+
+ if (n == 0 || (n & 1) != 0)
+ return;
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ ox = XPos (dw);
+ oy = YPos (dw);
+ dx = v[0];
+ dy = v[1];
+ sx = ox;
+ sy = oy;
+ tx = sx + DeviceToX (dw, dx);
+ ty = sy + DeviceToX (dw, dy);
+
+ pointi = 0;
+
+ appendPoint (points, &pointi, sx, sy);
+ appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
+
+ for (i = 2; i < n; i += 2) {
+ int ux = ox + DeviceToX (dw, dx += v[i]);
+ int uy = oy + DeviceToX (dw, dy += v[i+1]);
+ flattenCurve (points, &pointi,
+ (sx + tx*5)/6, (sy + ty*5)/6,
+ (tx*5 + ux)/6, (ty*5 + uy)/6,
+ (tx + ux)/2, (ty + uy)/2);
+ sx = tx;
+ sy = ty;
+ tx = ux;
+ ty = uy;
+ }
+
+ appendPoint (points, &pointi, tx, ty);
+
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ points, pointi, CoordModeOrigin);
+}
+
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/groff/xditview/font.c b/gnu/usr.bin/groff/xditview/font.c
new file mode 100644
index 000000000000..ecfba4ee4d12
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/font.c
@@ -0,0 +1,471 @@
+/*
+ * font.c
+ *
+ * map dvi fonts to X fonts
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+#include "XFontName.h"
+
+static DisposeFontSizes();
+
+static char *
+savestr (s)
+ char *s;
+{
+ char *n;
+
+ if (!s)
+ return 0;
+ n = XtMalloc (strlen (s) + 1);
+ if (n)
+ strcpy (n, s);
+ return n;
+}
+
+static DviFontList *
+LookupFontByPosition (dw, position)
+ DviWidget dw;
+ int position;
+{
+ DviFontList *f;
+
+ for (f = dw->dvi.fonts; f; f = f->next)
+ if (f->dvi_number == position)
+ break;
+ return f;
+}
+
+int
+MaxFontPosition (dw)
+ DviWidget dw;
+{
+ DviFontList *f;
+ int n = -1;
+
+ for (f = dw->dvi.fonts; f; f = f->next)
+ if (f->dvi_number > n)
+ n = f->dvi_number;
+ return n;
+}
+
+static DviFontSizeList *
+LookupFontSizeBySize (dw, f, size)
+ DviWidget dw;
+ DviFontList *f;
+ int size;
+{
+ DviFontSizeList *fs, *best = 0, *smallest = 0;
+ int bestsize = 0;
+ XFontName fontName;
+ unsigned int fontNameAttributes;
+ char fontNameString[2048];
+ int decipointsize;
+
+ if (f->scalable) {
+ decipointsize = (10*size)/dw->dvi.sizescale;
+ for (best = f->sizes; best; best = best->next)
+ if (best->size == decipointsize)
+ return best;
+ best = (DviFontSizeList *) XtMalloc(sizeof *best);
+ best->next = f->sizes;
+ best->size = decipointsize;
+ f->sizes = best;
+ XParseFontName (f->x_name, &fontName, &fontNameAttributes);
+ fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
+ fontNameAttributes |= FontNameResolutionX;
+ fontNameAttributes |= FontNameResolutionY;
+ fontNameAttributes |= FontNamePointSize;
+ fontName.ResolutionX = dw->dvi.display_resolution;
+ fontName.ResolutionY = dw->dvi.display_resolution;
+ fontName.PointSize = decipointsize;
+ XFormatFontName (&fontName, fontNameAttributes, fontNameString);
+ best->x_name = savestr (fontNameString);
+ best->doesnt_exist = 0;
+ best->font = 0;
+ return best;
+ }
+ for (fs = f->sizes; fs; fs=fs->next) {
+ if (dw->dvi.sizescale*fs->size <= 10*size
+ && fs->size >= bestsize) {
+ best = fs;
+ bestsize = fs->size;
+ }
+ if (smallest == 0 || fs->size < smallest->size)
+ smallest = fs;
+ }
+ return best ? best : smallest;
+}
+
+static char *
+SkipFontNameElement (n)
+ char *n;
+{
+ while (*n != '-')
+ if (!*++n)
+ return 0;
+ return n+1;
+}
+
+# define SizePosition 8
+# define EncodingPosition 13
+
+static
+ConvertFontNameToSize (n)
+ char *n;
+{
+ int i, size;
+
+ for (i = 0; i < SizePosition; i++) {
+ n = SkipFontNameElement (n);
+ if (!n)
+ return -1;
+ }
+ size = atoi (n);
+ return size;
+}
+
+static char *
+ConvertFontNameToEncoding (n)
+ char *n;
+{
+ int i;
+ for (i = 0; i < EncodingPosition; i++) {
+ n = SkipFontNameElement (n);
+ if (!n)
+ return 0;
+ }
+ return n;
+}
+
+DviFontSizeList *
+InstallFontSizes (dw, x_name, scalablep)
+ DviWidget dw;
+ char *x_name;
+ Boolean *scalablep;
+{
+ char fontNameString[2048];
+ char **fonts;
+ int i, count;
+ int size;
+ DviFontSizeList *sizes, *new;
+ XFontName fontName;
+ unsigned int fontNameAttributes;
+
+ *scalablep = FALSE;
+ if (!XParseFontName (x_name, &fontName, &fontNameAttributes))
+ return 0;
+ fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
+ |FontNameAverageWidth);
+ fontNameAttributes |= FontNameResolutionX;
+ fontNameAttributes |= FontNameResolutionY;
+ fontName.ResolutionX = dw->dvi.display_resolution;
+ fontName.ResolutionY = dw->dvi.display_resolution;
+ XFormatFontName (&fontName, fontNameAttributes, fontNameString);
+ fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
+ sizes = 0;
+ for (i = 0; i < count; i++) {
+ size = ConvertFontNameToSize (fonts[i]);
+ if (size == 0) {
+ DisposeFontSizes (dw, sizes);
+ sizes = 0;
+ *scalablep = TRUE;
+ break;
+ }
+ if (size != -1) {
+ new = (DviFontSizeList *) XtMalloc (sizeof *new);
+ new->next = sizes;
+ new->size = size;
+ new->x_name = savestr (fonts[i]);
+ new->doesnt_exist = 0;
+ new->font = 0;
+ sizes = new;
+ }
+ }
+ XFreeFontNames (fonts);
+ return sizes;
+}
+
+static
+DisposeFontSizes (dw, fs)
+ DviWidget dw;
+ DviFontSizeList *fs;
+{
+ DviFontSizeList *next;
+
+ for (; fs; fs=next) {
+ next = fs->next;
+ if (fs->x_name)
+ XtFree (fs->x_name);
+ if (fs->font) {
+ XUnloadFont (XtDisplay (dw), fs->font->fid);
+ XFree ((char *)fs->font);
+ }
+ XtFree ((char *) fs);
+ }
+}
+
+static DviFontList *
+InstallFont (dw, position, dvi_name, x_name)
+ DviWidget dw;
+ int position;
+ char *dvi_name;
+ char *x_name;
+{
+ DviFontList *f;
+ char *encoding;
+
+ if ((f = LookupFontByPosition (dw, position)) != NULL) {
+ /*
+ * ignore gratuitous font loading
+ */
+ if (!strcmp (f->dvi_name, dvi_name) &&
+ !strcmp (f->x_name, x_name))
+ return f;
+
+ DisposeFontSizes (dw, f->sizes);
+ if (f->dvi_name)
+ XtFree (f->dvi_name);
+ if (f->x_name)
+ XtFree (f->x_name);
+ f->device_font = 0;
+ } else {
+ f = (DviFontList *) XtMalloc (sizeof (*f));
+ f->next = dw->dvi.fonts;
+ dw->dvi.fonts = f;
+ }
+ f->initialized = FALSE;
+ f->dvi_name = savestr (dvi_name);
+ f->device_font = device_find_font (dw->dvi.device, dvi_name);
+ f->x_name = savestr (x_name);
+ f->dvi_number = position;
+ f->sizes = 0;
+ f->scalable = FALSE;
+ if (f->x_name) {
+ encoding = ConvertFontNameToEncoding (f->x_name);
+ f->char_map = DviFindMap (encoding);
+ } else
+ f->char_map = 0;
+ /*
+ * force requery of fonts
+ */
+ dw->dvi.font = 0;
+ dw->dvi.font_number = -1;
+ dw->dvi.cache.font = 0;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ return f;
+}
+
+ForgetFonts (dw)
+ DviWidget dw;
+{
+ DviFontList *f = dw->dvi.fonts;
+
+ while (f) {
+ DviFontList *tem = f;
+
+ if (f->sizes)
+ DisposeFontSizes (dw, f->sizes);
+ if (f->dvi_name)
+ XtFree (f->dvi_name);
+ if (f->x_name)
+ XtFree (f->x_name);
+ f = f->next;
+ XtFree ((char *) tem);
+ }
+
+ /*
+ * force requery of fonts
+ */
+ dw->dvi.font = 0;
+ dw->dvi.font_number = -1;
+ dw->dvi.cache.font = 0;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ dw->dvi.fonts = 0;
+}
+
+
+static char *
+MapDviNameToXName (dw, dvi_name)
+ DviWidget dw;
+ char *dvi_name;
+{
+ DviFontMap *fm;
+
+ for (fm = dw->dvi.font_map; fm; fm=fm->next)
+ if (!strcmp (fm->dvi_name, dvi_name))
+ return fm->x_name;
+ return 0;
+}
+
+#if 0
+static char *
+MapXNameToDviName (dw, x_name)
+ DviWidget dw;
+ char *x_name;
+{
+ DviFontMap *fm;
+
+ for (fm = dw->dvi.font_map; fm; fm=fm->next)
+ if (!strcmp (fm->x_name, x_name))
+ return fm->dvi_name;
+ return 0;
+}
+#endif
+
+ParseFontMap (dw)
+ DviWidget dw;
+{
+ char dvi_name[1024];
+ char x_name[2048];
+ char *m, *s;
+ DviFontMap *fm, *new;
+
+ if (dw->dvi.font_map)
+ DestroyFontMap (dw->dvi.font_map);
+ fm = 0;
+ m = dw->dvi.font_map_string;
+ while (*m) {
+ s = m;
+ while (*m && !isspace (*m))
+ ++m;
+ strncpy (dvi_name, s, m-s);
+ dvi_name[m-s] = '\0';
+ while (isspace (*m))
+ ++m;
+ s = m;
+ while (*m && *m != '\n')
+ ++m;
+ strncpy (x_name, s, m-s);
+ x_name[m-s] = '\0';
+ new = (DviFontMap *) XtMalloc (sizeof *new);
+ new->x_name = savestr (x_name);
+ new->dvi_name = savestr (dvi_name);
+ new->next = fm;
+ fm = new;
+ ++m;
+ }
+ dw->dvi.font_map = fm;
+}
+
+DestroyFontMap (font_map)
+ DviFontMap *font_map;
+{
+ DviFontMap *next;
+
+ for (; font_map; font_map = next) {
+ next = font_map->next;
+ if (font_map->x_name)
+ XtFree (font_map->x_name);
+ if (font_map->dvi_name)
+ XtFree (font_map->dvi_name);
+ XtFree ((char *) font_map);
+ }
+}
+
+/* ARGSUSED */
+
+SetFontPosition (dw, position, dvi_name, extra)
+ DviWidget dw;
+ int position;
+ char *dvi_name;
+ char *extra; /* unused */
+{
+ char *x_name;
+
+ x_name = MapDviNameToXName (dw, dvi_name);
+ if (x_name)
+ (void) InstallFont (dw, position, dvi_name, x_name);
+}
+
+XFontStruct *
+QueryFont (dw, position, size)
+ DviWidget dw;
+ int position;
+ int size;
+{
+ DviFontList *f;
+ DviFontSizeList *fs;
+
+ f = LookupFontByPosition (dw, position);
+ if (!f)
+ return dw->dvi.default_font;
+ if (!f->initialized) {
+ f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
+ f->initialized = TRUE;
+ }
+ fs = LookupFontSizeBySize (dw, f, size);
+ if (!fs)
+ return dw->dvi.default_font;
+ if (!fs->font) {
+ if (fs->x_name)
+ fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
+ if (!fs->font)
+ fs->font = dw->dvi.default_font;
+ }
+ return fs->font;
+}
+
+DeviceFont *
+QueryDeviceFont (dw, position)
+ DviWidget dw;
+ int position;
+{
+ DviFontList *f;
+
+ f = LookupFontByPosition (dw, position);
+ if (!f)
+ return 0;
+ return f->device_font;
+}
+
+DviCharNameMap *
+QueryFontMap (dw, position)
+ DviWidget dw;
+ int position;
+{
+ DviFontList *f;
+
+ f = LookupFontByPosition (dw, position);
+ if (f)
+ return f->char_map;
+ else
+ return 0;
+}
+
+#if 0
+LoadFont (dw, position, size)
+ DviWidget dw;
+ int position;
+ int size;
+{
+ XFontStruct *font;
+
+ font = QueryFont (dw, position, size);
+ dw->dvi.font_number = position;
+ dw->dvi.font_size = size;
+ dw->dvi.font = font;
+ XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
+ return;
+}
+#endif
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/groff/xditview/gxditview.1 b/gnu/usr.bin/groff/xditview/gxditview.1
new file mode 100644
index 000000000000..e4718aa7a0c7
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/gxditview.1
@@ -0,0 +1,217 @@
+.\" -*- nroff -*-
+.TH GXDITVIEW 1 "Release 5" "X Version 11"
+.SH NAME
+gxditview \- display gtroff output files
+.SH SYNOPSIS
+.B gxditview
+.RI [\fB\- toolkitoption\ .\|.\|.\|]
+.RI [\fB\- option\ .\|.\|.\|]
+.RI [ filename ]
+.SH DESCRIPTION
+The
+.I gxditview
+program displays gtroff output on an X display.
+It uses the standard X11 fonts,
+so it does not require access to the server machine for font loading.
+.PP
+If
+.I filename
+is
+.BR \- ,
+.I gxditview
+will read the standard input.
+.PP
+The left mouse button brings up a menu with the following entries:
+.TP 8
+.B "Next Page"
+Display the next page.
+.TP
+.B "Previous Page"
+Display the previous page.
+.TP
+.B "Select Page"
+Select a particular numbered page specified by a dialog box.
+.TP
+.B Print
+Print the gtroff output using a command specified by a dialog box.
+The default command initially displayed is controlled by the
+.B printCommand
+application resource, and by the
+.B \-printCommand
+option.
+.TP
+.B Open
+Open for display a new file specified by a dialog box.
+The file should contain gtroff output.
+If the filename starts with
+.B |
+it will be taken to be a command to read from.
+.TP
+.B Quit
+Exit from
+.IR gxditview .
+.PP
+The
+.BR n ,
+Space
+and Return keys are bound to the
+.B Next\ Page
+action.
+The
+.BR p ,
+BackSpace
+and
+Delete
+keys are bound to the
+.B Previous\ Page
+action.
+The
+.B q
+key is bound to the
+.B Quit
+action.
+The
+.B r
+key is bound to the
+.B Rerasterize
+action which rereads the current file, and redisplays the current page;
+if the current file is a command, the command will be reexecuted.
+.PP
+The
+.B paperlength
+and
+.B paperwidth
+commands in the DESC file specify the length and width in machine units
+of the virtual page displayed by
+.IR gxditview .
+.SH OPTIONS
+.I Gxditview
+accepts all of the standard X Toolkit command line options along with the
+additional options listed below:
+.TP 8
+.B \-help
+This option indicates that a brief summary of the allowed options should be
+printed.
+.TP
+.B \-page
+This option specifies the page number of the document to be displayed.
+.TP
+.BI \-backingStore\ backing-store-type
+Redisplay of the gtroff output window can take upto a second or so,
+this option causes the server to save the window contents so that when
+it is scrolled around the viewport, the window is painted from
+contents saved in backing store.
+.I backing-store-type
+can be one of
+.BR Always ,
+.B WhenMapped
+or
+.BR NotUseful .
+.TP
+.BI \-printCommand\ command
+The default command displayed in the dialog box for the
+.B Print
+menu entry will be
+.IR command .
+.TP
+.BI \-resolution\ res
+The gtroff output file will be displayed at a resolution of
+.I res
+dpi,
+unless the DESC file contains the
+.B X11
+command, in which case the device resolution will be used.
+This corresponds the
+.I Dvi
+widget's
+.B resolution
+resource.
+The default is 75.
+.TP
+.BI \-filename\ string
+The default filename displayed in the dialog box for the
+.B Open
+menu entry will be
+.IR string .
+This can be either a filename, or a command starting with
+.BR | .
+.PP
+The following standard X Toolkit command line arguments are commonly used with
+.IR gxditview :
+.TP 8
+.BI \-bg\ color
+This option specifies the color to use for the background of the window.
+The default is \fIwhite\fP.
+.TP
+.BI \-bd\ color
+This option specifies the color to use for the border of the window.
+The default is \fIblack\fP.
+.TP
+.BI \-bw\ number
+This option specifies the width in pixels of the border surrounding the window.
+.TP
+.BI \-fg\ color
+This option specifies the color to use for displaying text. The default is
+\fIblack\fP.
+.TP
+.BI \-fn\ font
+This option specifies the font to be used for displaying widget text. The
+default is \fIfixed\fP.
+.TP
+.B \-rv
+This option indicates that reverse video should be simulated by swapping
+the foreground and background colors.
+.TP
+.BI \-geometry\ geometry
+This option specifies the preferred size and position of the window.
+.TP
+.BI \-display\ host : display
+This option specifies the X server to contact.
+.TP
+.BI \-xrm\ resourcestring
+This option specifies a resource string to be used.
+.SH X DEFAULTS
+This program uses the
+.I Dvi
+widget in the X Toolkit. It understands all of the core resource names and
+classes as well as:
+.PP
+.TP 8
+.BR width\ (class\ Width )
+Specifies the width of the window.
+.TP
+.BR height\ (class\ Height )
+Specifies the height of the window.
+.TP
+.BR foreground\ (class\ Foreground )
+Specifies the default foreground color.
+.TP
+.BR font\ (class\ Font )
+Specifies the font to be used for error messages.
+.SH "SEE ALSO"
+.IR X (1),
+.IR xrdb (1),
+.IR gtroff (1),
+.IR groff (1)
+.SH ORIGIN
+This program is derived from xditview;
+portions of xditview originated in xtroff which was derived
+from suntroff.
+.SH COPYRIGHT
+Copyright 1989, Massachusetts Institute of Technology.
+.br
+See
+.IR X (1)
+for a full statement of rights and permissions.
+.SH AUTHORS
+Keith Packard (MIT X Consortium)
+.br
+Richard L. Hyde (Purdue)
+.br
+David Slattengren (Berkeley)
+.br
+Malcom Slaney (Schlumberger Palo Alto Research)
+.br
+Mark Moraes (University of Toronto)
+.br
+James Clark
diff --git a/gnu/usr.bin/groff/xditview/lex.c b/gnu/usr.bin/groff/xditview/lex.c
new file mode 100644
index 000000000000..32831bdacd43
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/lex.c
@@ -0,0 +1,103 @@
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include "DviP.h"
+
+DviGetAndPut(dw, cp)
+ DviWidget dw;
+ int *cp;
+{
+ if (dw->dvi.ungot) {
+ dw->dvi.ungot = 0;
+ *cp = getc (dw->dvi.file);
+ }
+ else {
+ *cp = getc (dw->dvi.file);
+ if (*cp != EOF)
+ putc (*cp, dw->dvi.tmpFile);
+ }
+ return *cp;
+}
+
+char *
+GetLine(dw, Buffer, Length)
+ DviWidget dw;
+ char *Buffer;
+ int Length;
+{
+ int i = 0, c;
+
+ Length--; /* Save room for final '\0' */
+
+ while (DviGetC (dw, &c) != EOF) {
+ if (Buffer && i < Length)
+ Buffer[i++] = c;
+ if (c == '\n') {
+ DviUngetC(dw, c);
+ break;
+ }
+ }
+ if (Buffer)
+ Buffer[i] = '\0';
+ return Buffer;
+}
+
+char *
+GetWord(dw, Buffer, Length)
+ DviWidget dw;
+ char *Buffer;
+ int Length;
+{
+ int i = 0, c;
+
+ Length--; /* Save room for final '\0' */
+ while (DviGetC(dw, &c) == ' ' || c == '\n')
+ ;
+ while (c != EOF) {
+ if (Buffer && i < Length)
+ Buffer[i++] = c;
+ if (DviGetC(dw, &c) == ' ' || c == '\n') {
+ DviUngetC(dw, c);
+ break;
+ }
+ }
+ if (Buffer)
+ Buffer[i] = '\0';
+ return Buffer;
+}
+
+GetNumber(dw)
+ DviWidget dw;
+{
+ int i = 0, c;
+ int negative = 0;
+
+ while (DviGetC(dw, &c) == ' ' || c == '\n')
+ ;
+ if (c == '-') {
+ negative = 1;
+ DviGetC(dw, &c);
+ }
+
+ for (; c >= '0' && c <= '9'; DviGetC(dw, &c)) {
+ if (negative)
+ i = i*10 - (c - '0');
+ else
+ i = i*10 + c - '0';
+ }
+ if (c != EOF)
+ DviUngetC(dw, c);
+ return i;
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/groff/xditview/page.c b/gnu/usr.bin/groff/xditview/page.c
new file mode 100644
index 000000000000..9284199cde8d
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/page.c
@@ -0,0 +1,88 @@
+/*
+ * page.c
+ *
+ * map page numbers to file position
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+#ifdef X_NOT_STDC_ENV
+extern long ftell();
+#endif
+
+static DviFileMap *
+MapPageNumberToFileMap (dw, number)
+ DviWidget dw;
+ int number;
+{
+ DviFileMap *m;
+
+ for (m = dw->dvi.file_map; m; m=m->next)
+ if (m->page_number == number)
+ break;
+ return m;
+}
+
+DestroyFileMap (m)
+ DviFileMap *m;
+{
+ DviFileMap *next;
+
+ for (; m; m = next) {
+ next = m->next;
+ XtFree ((char *) m);
+ }
+}
+
+ForgetPagePositions (dw)
+ DviWidget dw;
+{
+ DestroyFileMap (dw->dvi.file_map);
+ dw->dvi.file_map = 0;
+}
+
+RememberPagePosition(dw, number)
+ DviWidget dw;
+ int number;
+{
+ DviFileMap *m;
+
+ if (!(m = MapPageNumberToFileMap (dw, number))) {
+ m = (DviFileMap *) XtMalloc (sizeof *m);
+ m->page_number = number;
+ m->next = dw->dvi.file_map;
+ dw->dvi.file_map = m;
+ }
+ if (dw->dvi.tmpFile)
+ m->position = ftell (dw->dvi.tmpFile);
+ else
+ m->position = ftell (dw->dvi.file);
+}
+
+SearchPagePosition (dw, number)
+ DviWidget dw;
+ int number;
+{
+ DviFileMap *m;
+
+ if (!(m = MapPageNumberToFileMap (dw, number)))
+ return -1;
+ return m->position;
+}
+
+FileSeek(dw, position)
+DviWidget dw;
+long position;
+{
+ if (dw->dvi.tmpFile) {
+ dw->dvi.readingTmp = 1;
+ fseek (dw->dvi.tmpFile, position, 0);
+ } else
+ fseek (dw->dvi.file, position, 0);
+}
+
diff --git a/gnu/usr.bin/groff/xditview/parse.c b/gnu/usr.bin/groff/xditview/parse.c
new file mode 100644
index 000000000000..8367c17b92ae
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/parse.c
@@ -0,0 +1,334 @@
+/*
+ * parse.c
+ *
+ * parse dvi input
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+static int StopSeen = 0;
+static ParseDrawFunction(), ParseDeviceControl();
+static push_env(), pop_env();
+
+#define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta))
+
+
+ParseInput(dw)
+ register DviWidget dw;
+{
+ int n, k;
+ int c;
+ char Buffer[BUFSIZ];
+ int NextPage;
+ int otherc;
+
+ StopSeen = 0;
+
+ /*
+ * make sure some state exists
+ */
+
+ if (!dw->dvi.state)
+ push_env (dw);
+ for (;;) {
+ switch (DviGetC(dw, &c)) {
+ case '\n':
+ break;
+ case ' ': /* when input is text */
+ case 0: /* occasional noise creeps in */
+ break;
+ case '{': /* push down current environment */
+ push_env(dw);
+ break;
+ case '}':
+ pop_env(dw);
+ break;
+ /*
+ * two motion digits plus a character
+ */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ HorizontalMove(dw, (c-'0')*10 +
+ DviGetC(dw,&otherc)-'0');
+ /* fall through */
+ case 'c': /* single ascii character */
+ DviGetC(dw,&c);
+ if (c == ' ')
+ break;
+ Buffer[0] = c;
+ Buffer[1] = '\0';
+ (void) PutCharacter (dw, Buffer);
+ break;
+ case 'C':
+ GetWord (dw, Buffer, BUFSIZ);
+ (void) PutCharacter (dw, Buffer);
+ break;
+ case 't':
+ Buffer[1] = '\0';
+ while (DviGetC (dw, &c) != EOF
+ && c != ' ' && c != '\n') {
+ Buffer[0] = c;
+ HorizontalMove (dw, PutCharacter (dw, Buffer));
+ }
+ break;
+ case 'u':
+ n = GetNumber(dw);
+ Buffer[1] = '\0';
+ while (DviGetC (dw, &c) == ' ')
+ ;
+ while (c != EOF && c != ' ' && c != '\n') {
+ Buffer[0] = c;
+ HorizontalMove (dw,
+ PutCharacter (dw, Buffer) + n);
+ DviGetC (dw, &c);
+ }
+ break;
+
+ case 'D': /* draw function */
+ (void) GetLine(dw, Buffer, BUFSIZ);
+ if (dw->dvi.display_enable)
+ ParseDrawFunction(dw, Buffer);
+ break;
+ case 's': /* ignore fractional sizes */
+ n = GetNumber(dw);
+ dw->dvi.state->font_size = n;
+ break;
+ case 'f':
+ n = GetNumber(dw);
+ dw->dvi.state->font_number = n;
+ break;
+ case 'H': /* absolute horizontal motion */
+ k = GetNumber(dw);
+ HorizontalGoto(dw, k);
+ break;
+ case 'h': /* relative horizontal motion */
+ k = GetNumber(dw);
+ HorizontalMove(dw, k);
+ break;
+ case 'w': /* word space */
+ Word (dw);
+ break;
+ case 'V':
+ n = GetNumber(dw);
+ VerticalGoto(dw, n);
+ break;
+ case 'v':
+ n = GetNumber(dw);
+ VerticalMove(dw, n);
+ break;
+ case 'P': /* new spread */
+ break;
+ case 'p': /* new page */
+ (void) GetNumber(dw);
+ NextPage = dw->dvi.current_page + 1;
+ RememberPagePosition(dw, NextPage);
+ FlushCharCache (dw);
+ return(NextPage);
+ case 'N':
+ n = GetNumber(dw);
+ PutNumberedCharacter (dw, n);
+ break;
+ case 'n': /* end of line */
+ GetNumber(dw);
+ GetNumber(dw);
+ Newline (dw);
+ HorizontalGoto(dw, 0);
+ break;
+ case '+': /* continuation of X device control */
+ case '#': /* comment */
+ GetLine(dw, NULL, 0);
+ break;
+ case 'x': /* device control */
+ ParseDeviceControl(dw);
+ break;
+ case EOF:
+ dw->dvi.last_page = dw->dvi.current_page;
+ FlushCharCache (dw);
+ return dw->dvi.current_page;
+ default:
+ break;
+ }
+ }
+}
+
+static
+push_env(dw)
+ DviWidget dw;
+{
+ DviState *new;
+
+ new = (DviState *) XtMalloc (sizeof (*new));
+ if (dw->dvi.state)
+ *new = *(dw->dvi.state);
+ else {
+ new->font_size = 10;
+ new->font_number = 1;
+ new->x = 0;
+ new->y = 0;
+ }
+ new->next = dw->dvi.state;
+ dw->dvi.state = new;
+}
+
+static
+pop_env(dw)
+ DviWidget dw;
+{
+ DviState *old;
+
+ old = dw->dvi.state;
+ dw->dvi.state = old->next;
+ XtFree ((char *) old);
+}
+
+static
+InitTypesetter (dw)
+ DviWidget dw;
+{
+ while (dw->dvi.state)
+ pop_env (dw);
+ push_env (dw);
+ FlushCharCache (dw);
+}
+
+#define DRAW_ARGS_MAX 128
+
+static
+ParseDrawFunction(dw, buf)
+DviWidget dw;
+char *buf;
+{
+ int v[DRAW_ARGS_MAX];
+ int i;
+ char *ptr;
+
+ v[0] = v[1] = v[2] = v[3] = 0;
+
+ if (buf[0] == '\0')
+ return;
+ ptr = buf+1;
+
+ for (i = 0; i < DRAW_ARGS_MAX; i++) {
+ if (sscanf(ptr, "%d", v + i) != 1)
+ break;
+ while (*ptr == ' ')
+ ptr++;
+ while (*ptr != '\0' && *ptr != ' ')
+ ptr++;
+ }
+
+ switch (buf[0]) {
+ case 'l': /* draw a line */
+ DrawLine(dw, v[0], v[1]);
+ break;
+ case 'c': /* circle */
+ DrawCircle(dw, v[0]);
+ break;
+ case 'C':
+ DrawFilledCircle(dw, v[0]);
+ break;
+ case 'e': /* ellipse */
+ DrawEllipse(dw, v[0], v[1]);
+ break;
+ case 'E':
+ DrawFilledEllipse(dw, v[0], v[1]);
+ break;
+ case 'a': /* arc */
+ DrawArc(dw, v[0], v[1], v[2], v[3]);
+ break;
+ case 'p':
+ DrawPolygon(dw, v, i);
+ break;
+ case 'P':
+ DrawFilledPolygon(dw, v, i);
+ break;
+ case '~': /* wiggly line */
+ DrawSpline(dw, v, i);
+ break;
+ case 't':
+ dw->dvi.line_thickness = v[0];
+ break;
+ case 'f':
+ if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX)
+ dw->dvi.fill = v[0];
+ break;
+ default:
+#if 0
+ warning("unknown drawing function %s", buf);
+#endif
+ break;
+ }
+
+ if (buf[0] == 'e') {
+ if (i > 0)
+ dw->dvi.state->x += v[0];
+ }
+ else {
+ while (--i >= 0) {
+ if (i & 1)
+ dw->dvi.state->y += v[i];
+ else
+ dw->dvi.state->x += v[i];
+ }
+ }
+}
+
+static
+ParseDeviceControl(dw) /* Parse the x commands */
+ DviWidget dw;
+{
+ char str[20], str1[50];
+ int c, n;
+ extern int LastPage, CurrentPage;
+
+ GetWord (dw, str, 20);
+ switch (str[0]) { /* crude for now */
+ case 'T': /* output device */
+ GetWord (dw, str, 20);
+ SetDevice (dw, str);
+ break;
+ case 'i': /* initialize */
+ InitTypesetter (dw);
+ break;
+ case 't': /* trailer */
+ break;
+ case 'p': /* pause -- can restart */
+ break;
+ case 's': /* stop */
+ StopSeen = 1;
+ return;
+ case 'r': /* resolution when prepared */
+ break;
+ case 'f': /* font used */
+ n = GetNumber (dw);
+ GetWord (dw, str, 20);
+ GetLine (dw, str1, 50);
+ SetFontPosition (dw, n, str, str1);
+ break;
+ case 'H': /* char height */
+ break;
+ case 'S': /* slant */
+ break;
+ }
+ while (DviGetC (dw, &c) != '\n') /* skip rest of input line */
+ if (c == EOF)
+ return;
+ return;
+}
+
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/groff/xditview/xdit.bm b/gnu/usr.bin/groff/xditview/xdit.bm
new file mode 100644
index 000000000000..67b9c8ab56bc
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/xdit.bm
@@ -0,0 +1,14 @@
+#define xdit_width 32
+#define xdit_height 32
+static char xdit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x03, 0x02, 0x00, 0x00, 0x02,
+ 0x8a, 0xa2, 0xfc, 0x03, 0x52, 0x14, 0x03, 0x04, 0x02, 0x80, 0x00, 0x08,
+ 0x52, 0x54, 0x00, 0x10, 0x8a, 0x22, 0x8f, 0x23, 0x02, 0x20, 0x06, 0x21,
+ 0x8a, 0x12, 0x8c, 0x40, 0x52, 0x14, 0x8c, 0x40, 0x02, 0x10, 0x58, 0x40,
+ 0x52, 0x14, 0x30, 0x40, 0x8a, 0x12, 0x30, 0x40, 0x02, 0x10, 0x70, 0x40,
+ 0x8a, 0x12, 0xc8, 0x40, 0x52, 0x24, 0xc4, 0xe0, 0x02, 0x20, 0x84, 0xe1,
+ 0x52, 0x54, 0xce, 0xf3, 0x8a, 0xa2, 0x00, 0xf8, 0x02, 0x00, 0x03, 0xfc,
+ 0x8a, 0x22, 0xfc, 0xf3, 0x52, 0x14, 0x00, 0xc2, 0x02, 0x00, 0x00, 0x02,
+ 0x52, 0x14, 0x45, 0x02, 0x8a, 0xa2, 0x28, 0x02, 0x02, 0x00, 0x00, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/usr.bin/groff/xditview/xdit_mask.bm b/gnu/usr.bin/groff/xditview/xdit_mask.bm
new file mode 100644
index 000000000000..f34a4f863f02
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/xdit_mask.bm
@@ -0,0 +1,14 @@
+#define xdit_mask_width 32
+#define xdit_mask_height 32
+static char xdit_mask_bits[] = {
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x1f,
+ 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc7,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/gnu/usr.bin/groff/xditview/xditview.c b/gnu/usr.bin/groff/xditview/xditview.c
new file mode 100644
index 000000000000..7179045bafca
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/xditview.c
@@ -0,0 +1,587 @@
+/*
+ * Copyright 1991 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. M.I.T. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * xditview --
+ *
+ * Display ditroff output in an X window
+ */
+
+#ifndef SABER
+#ifndef lint
+static char rcsid[] = "$XConsortium: xditview.c,v 1.17 89/12/10 17:05:08 rws Exp $";
+#endif /* lint */
+#endif /* SABER */
+
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xaw/Paned.h>
+#include <X11/Xaw/Viewport.h>
+#include <X11/Xaw/Box.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Dialog.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/SimpleMenu.h>
+#include <X11/Xaw/SmeBSB.h>
+
+#include <signal.h>
+
+#include "Dvi.h"
+
+#include "xdit.bm"
+#include "xdit_mask.bm"
+#include "stdio.h"
+
+extern FILE *popen();
+extern void exit();
+
+static struct app_resources {
+ char *print_command;
+ char *filename;
+} app_resources;
+
+#define offset(field) XtOffset(struct app_resources *, field)
+
+/* Application resources. */
+
+static XtResource resources[] = {
+ {"printCommand", "PrintCommand", XtRString, sizeof(char*),
+ offset(print_command), XtRString, NULL},
+ {"filename", "Filename", XtRString, sizeof(char*),
+ offset(filename), XtRString, NULL},
+};
+
+#undef offset
+
+/* Command line options table. Only resources are entered here...there is a
+ pass over the remaining options after XtParseCommand is let loose. */
+
+static XrmOptionDescRec options[] = {
+{"-page", "*dvi.pageNumber", XrmoptionSepArg, NULL},
+{"-backingStore", "*dvi.backingStore", XrmoptionSepArg, NULL},
+{"-resolution", "*dvi.resolution", XrmoptionSepArg, NULL},
+{"-printCommand", ".printCommand", XrmoptionSepArg, NULL},
+{"-filename", ".filename", XrmoptionSepArg, NULL},
+{"-noPolyText", "*dvi.noPolyText", XrmoptionNoArg, "TRUE"},
+};
+
+static char current_print_command[1024];
+
+static char current_file_name[1024];
+static FILE *current_file;
+
+/*
+ * Report the syntax for calling xditview.
+ */
+
+static
+Syntax(call)
+ char *call;
+{
+ (void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call);
+ (void) printf (" [-bd <color>] [-bw <pixels>] [-help]\n");
+ (void) printf (" [-display displayname] [-geometry geom]\n");
+ (void) printf (" [-page <page-number>] [-backing <backing-store>]\n");
+ (void) printf (" [-resolution <res>] [-print <command>]\n");
+ (void) printf (" [-filename <file>] [filename]\n\n");
+ exit(1);
+}
+
+static void NewFile (), SetPageNumber ();
+static Widget toplevel, paned, viewport, dvi;
+static Widget page;
+static Widget simpleMenu;
+
+static void NextPage(), PreviousPage(), SelectPage(), OpenFile(), Quit();
+static void Print();
+
+static struct menuEntry {
+ char *name;
+ void (*function)();
+} menuEntries[] = {
+ "nextPage", NextPage,
+ "previousPage", PreviousPage,
+ "selectPage", SelectPage,
+ "print", Print,
+ "openFile", OpenFile,
+ "quit", Quit,
+};
+
+static void NextPageAction(), PreviousPageAction(), SelectPageAction();
+static void OpenFileAction(), QuitAction();
+static void AcceptAction(), CancelAction();
+static void PrintAction();
+static void RerasterizeAction();
+
+XtActionsRec xditview_actions[] = {
+ "NextPage", NextPageAction,
+ "PreviousPage", PreviousPageAction,
+ "SelectPage", SelectPageAction,
+ "Print", PrintAction,
+ "OpenFile", OpenFileAction,
+ "Rerasterize", RerasterizeAction,
+ "Quit", QuitAction,
+ "Accept", AcceptAction,
+ "Cancel", CancelAction,
+};
+
+#define MenuNextPage 0
+#define MenuPreviousPage 1
+#define MenuSelectPage 2
+#define MenuPrint 3
+#define MenuOpenFile 4
+#define MenuQuit 5
+
+static char pageLabel[256] = "Page <none>";
+
+void main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *file_name = 0;
+ int i;
+ static Arg labelArgs[] = {
+ {XtNlabel, (XtArgVal) pageLabel},
+ };
+ Arg topLevelArgs[2];
+ Widget entry;
+ Arg pageNumberArgs[1];
+ int page_number;
+
+ toplevel = XtInitialize("main", "GXditview",
+ options, XtNumber (options),
+ &argc, argv);
+ if (argc > 2)
+ Syntax(argv[0]);
+
+ XtGetApplicationResources(toplevel, (XtPointer)&app_resources,
+ resources, XtNumber(resources),
+ NULL, (Cardinal) 0);
+ if (app_resources.print_command)
+ strcpy(current_print_command, app_resources.print_command);
+
+ XtAppAddActions(XtWidgetToApplicationContext(toplevel),
+ xditview_actions, XtNumber (xditview_actions));
+
+ XtSetArg (topLevelArgs[0], XtNiconPixmap,
+ XCreateBitmapFromData (XtDisplay (toplevel),
+ XtScreen(toplevel)->root,
+ xdit_bits, xdit_width, xdit_height));
+
+ XtSetArg (topLevelArgs[1], XtNiconMask,
+ XCreateBitmapFromData (XtDisplay (toplevel),
+ XtScreen(toplevel)->root,
+ xdit_mask_bits,
+ xdit_mask_width, xdit_mask_height));
+ XtSetValues (toplevel, topLevelArgs, 2);
+ if (argc > 1)
+ file_name = argv[1];
+
+ /*
+ * create the menu and insert the entries
+ */
+ simpleMenu = XtCreatePopupShell ("menu", simpleMenuWidgetClass, toplevel,
+ NULL, 0);
+ for (i = 0; i < XtNumber (menuEntries); i++) {
+ entry = XtCreateManagedWidget(menuEntries[i].name,
+ smeBSBObjectClass, simpleMenu,
+ NULL, (Cardinal) 0);
+ XtAddCallback(entry, XtNcallback, menuEntries[i].function, NULL);
+ }
+
+ paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel,
+ NULL, (Cardinal) 0);
+ viewport = XtCreateManagedWidget("viewport", viewportWidgetClass, paned,
+ NULL, (Cardinal) 0);
+ dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, viewport, NULL, 0);
+ page = XtCreateManagedWidget ("label", labelWidgetClass, paned,
+ labelArgs, XtNumber (labelArgs));
+ XtSetArg (pageNumberArgs[0], XtNpageNumber, &page_number);
+ XtGetValues (dvi, pageNumberArgs, 1);
+ if (file_name)
+ NewFile (file_name);
+ /* NewFile modifies current_file_name, so do this here. */
+ if (app_resources.filename)
+ strcpy(current_file_name, app_resources.filename);
+ XtRealizeWidget (toplevel);
+ if (file_name)
+ SetPageNumber (page_number);
+ XtMainLoop();
+}
+
+static void
+SetPageNumber (number)
+{
+ Arg arg[2];
+ int actual_number, last_page;
+
+ XtSetArg (arg[0], XtNpageNumber, number);
+ XtSetValues (dvi, arg, 1);
+ XtSetArg (arg[0], XtNpageNumber, &actual_number);
+ XtSetArg (arg[1], XtNlastPageNumber, &last_page);
+ XtGetValues (dvi, arg, 2);
+ if (actual_number == 0)
+ sprintf (pageLabel, "Page <none>");
+ else if (last_page > 0)
+ sprintf (pageLabel, "Page %d of %d", actual_number, last_page);
+ else
+ sprintf (pageLabel, "Page %d", actual_number);
+ XtSetArg (arg[0], XtNlabel, pageLabel);
+ XtSetValues (page, arg, 1);
+}
+
+static void
+SelectPageNumber (number_string)
+char *number_string;
+{
+ SetPageNumber (atoi(number_string));
+}
+
+static int hadFile = 0;
+
+static void
+NewFile (name)
+char *name;
+{
+ Arg arg[2];
+ char *n, *rindex ();
+ FILE *new_file;
+ Boolean seek = 0;
+
+ if (current_file) {
+ if (!strcmp (current_file_name, "-"))
+ ;
+ else if (current_file_name[0] == '|')
+ pclose (current_file);
+ else
+ fclose (current_file);
+ }
+ if (!strcmp (name, "-"))
+ new_file = stdin;
+ else if (name[0] == '|')
+ new_file = popen (name+1, "r");
+ else {
+ new_file = fopen (name, "r");
+ seek = 1;
+ }
+ if (!new_file) {
+ /* XXX display error message */
+ return;
+ }
+ XtSetArg (arg[0], XtNfile, new_file);
+ XtSetArg (arg[1], XtNseek, seek);
+ XtSetValues (dvi, arg, 2);
+ if (hadFile || name[0] != '-' || name[1] != '\0') {
+ XtSetArg (arg[0], XtNtitle, name);
+ if (name[0] != '/' && (n = rindex (name, '/')))
+ n = n + 1;
+ else
+ n = name;
+ XtSetArg (arg[1], XtNiconName, n);
+ XtSetValues (toplevel, arg, 2);
+ }
+ hadFile = 1;
+ SelectPageNumber ("1");
+ strcpy (current_file_name, name);
+ current_file = new_file;
+}
+
+static char fileBuf[1024];
+
+ResetMenuEntry (entry)
+ Widget entry;
+{
+ Arg arg[1];
+
+ XtSetArg (arg[0], XtNpopupOnEntry, entry);
+ XtSetValues (XtParent(entry) , arg, (Cardinal) 1);
+}
+
+/*ARGSUSED*/
+
+static void
+NextPage (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ NextPageAction();
+ ResetMenuEntry (entry);
+}
+
+static void
+NextPageAction ()
+{
+ Arg args[1];
+ int number;
+
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ SetPageNumber (number+1);
+}
+
+/*ARGSUSED*/
+
+static void
+PreviousPage (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ PreviousPageAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+PreviousPageAction ()
+{
+ Arg args[1];
+ int number;
+
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ SetPageNumber (number-1);
+}
+
+/* ARGSUSED */
+
+static void
+SelectPage (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ SelectPageAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+SelectPageAction ()
+{
+ MakePrompt (toplevel, "Page number", SelectPageNumber, "");
+}
+
+
+static void
+DoPrint (name)
+ char *name;
+{
+ FILE *print_file;
+#ifdef SIGNALRETURNSINT
+ int (*handler)();
+#else
+ void (*handler)();
+#endif
+ /* Avoid dieing because of an invalid command. */
+ handler = signal(SIGPIPE, SIG_IGN);
+
+ print_file = popen(name, "w");
+ if (!print_file)
+ /* XXX print error message */
+ return;
+ DviSaveToFile(dvi, print_file);
+ pclose(print_file);
+ signal(SIGPIPE, handler);
+ strcpy(current_print_command, name);
+}
+
+static void
+RerasterizeAction()
+{
+ Arg args[1];
+ int number;
+
+ if (current_file_name[0] == 0) {
+ /* XXX display an error message */
+ return;
+ }
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ NewFile(current_file_name);
+ SetPageNumber (number);
+}
+
+/* ARGSUSED */
+
+static void
+Print (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ PrintAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+PrintAction ()
+{
+ if (current_print_command[0])
+ strcpy (fileBuf, current_print_command);
+ else
+ fileBuf[0] = '\0';
+ MakePrompt (toplevel, "Print command:", DoPrint, fileBuf);
+}
+
+
+/* ARGSUSED */
+
+static void
+OpenFile (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ OpenFileAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+OpenFileAction ()
+{
+ if (current_file_name[0])
+ strcpy (fileBuf, current_file_name);
+ else
+ fileBuf[0] = '\0';
+ MakePrompt (toplevel, "File to open:", NewFile, fileBuf);
+}
+
+/* ARGSUSED */
+
+static void
+Quit (entry, closure, data)
+ Widget entry;
+ caddr_t closure, data;
+{
+ QuitAction ();
+}
+
+static void
+QuitAction ()
+{
+ exit (0);
+}
+
+Widget promptShell, promptDialog;
+void (*promptfunction)();
+
+/* ARGSUSED */
+static
+void CancelAction (widget, event, params, num_params)
+ Widget widget;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ if (promptShell) {
+ XtSetKeyboardFocus(toplevel, (Widget) None);
+ XtDestroyWidget(promptShell);
+ promptShell = (Widget) 0;
+ }
+}
+
+static
+void AcceptAction (widget, event, params, num_params)
+ Widget widget;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ (*promptfunction)(XawDialogGetValueString(promptDialog));
+ CancelAction (widget, event, params, num_params);
+}
+
+MakePrompt(centerw, prompt, func, def)
+Widget centerw;
+char *prompt;
+void (*func)();
+char *def;
+{
+ static Arg dialogArgs[] = {
+ {XtNlabel, NULL},
+ {XtNvalue, NULL},
+ };
+ Arg valueArgs[1];
+ Arg centerArgs[2];
+ Position source_x, source_y;
+ Position dest_x, dest_y;
+ Dimension center_width, center_height;
+ Dimension prompt_width, prompt_height;
+ Widget valueWidget;
+
+ CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
+ promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass,
+ toplevel, NULL, (Cardinal) 0);
+ dialogArgs[0].value = (XtArgVal)prompt;
+ dialogArgs[1].value = (XtArgVal)def;
+ promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass,
+ promptShell, dialogArgs, XtNumber (dialogArgs));
+ XawDialogAddButton(promptDialog, "accept", NULL, (caddr_t) 0);
+ XawDialogAddButton(promptDialog, "cancel", NULL, (caddr_t) 0);
+ valueWidget = XtNameToWidget (promptDialog, "value");
+ if (valueWidget) {
+ XtSetArg (valueArgs[0], XtNresizable, TRUE);
+ XtSetValues (valueWidget, valueArgs, 1);
+ /*
+ * as resizable isn't set until just above, the
+ * default value will be displayed incorrectly.
+ * rectify the situation by resetting the values
+ */
+ XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs));
+ }
+ XtSetKeyboardFocus (promptDialog, valueWidget);
+ XtSetKeyboardFocus (toplevel, valueWidget);
+ XtRealizeWidget (promptShell);
+ /*
+ * place the widget in the center of the "parent"
+ */
+ XtSetArg (centerArgs[0], XtNwidth, &center_width);
+ XtSetArg (centerArgs[1], XtNheight, &center_height);
+ XtGetValues (centerw, centerArgs, 2);
+ XtSetArg (centerArgs[0], XtNwidth, &prompt_width);
+ XtSetArg (centerArgs[1], XtNheight, &prompt_height);
+ XtGetValues (promptShell, centerArgs, 2);
+ source_x = (center_width - prompt_width) / 2;
+ source_y = (center_height - prompt_height) / 3;
+ XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y);
+ XtSetArg (centerArgs[0], XtNx, dest_x);
+ XtSetArg (centerArgs[1], XtNy, dest_y);
+ XtSetValues (promptShell, centerArgs, 2);
+ XtMapWidget(promptShell);
+ promptfunction = func;
+}
+
+/* For DviChar.c */
+
+char *xmalloc(n)
+ int n;
+{
+ return XtMalloc(n);
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 4
+c-label-offset: -4
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/groff/xditview/xtotroff.c b/gnu/usr.bin/groff/xditview/xtotroff.c
new file mode 100644
index 000000000000..16e8c263e8af
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/xtotroff.c
@@ -0,0 +1,303 @@
+/*
+ * xtotroff
+ *
+ * convert X font metrics into troff font metrics
+ */
+
+#include <X11/Xlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "XFontName.h"
+#include "DviChar.h"
+
+#ifdef X_NOT_STDC_ENV
+char *malloc();
+#else
+#include <stdlib.h>
+#endif
+
+#define charWidth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
+#define charHeight(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
+#define charDepth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
+#define charLBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
+#define charRBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
+
+Display *dpy;
+int groff_flag = 0;
+unsigned resolution = 75;
+unsigned point_size = 10;
+
+int charExists (fi, c)
+ XFontStruct *fi;
+ int c;
+{
+ XCharStruct *p;
+
+ if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
+ return 0;
+ p = fi->per_char + (c - fi->min_char_or_byte2);
+ return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
+ || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
+}
+
+/* Canonicalize the font name by replacing scalable parts by *s. */
+
+CanonicalizeFontName (font_name, canon_font_name)
+ char *font_name, *canon_font_name;
+{
+ unsigned int attributes;
+ XFontName parsed;
+
+ if (!XParseFontName(font_name, &parsed, &attributes)) {
+ fprintf (stderr, "not a standard name: %s\n", font_name);
+ return 0;
+ }
+
+ attributes &= ~(FontNamePixelSize|FontNameAverageWidth
+ |FontNamePointSize
+ |FontNameResolutionX|FontNameResolutionY);
+ XFormatFontName(&parsed, attributes, canon_font_name);
+ return 1;
+}
+
+int FontNamesAmbiguous(font_name, names, count)
+char *font_name;
+char **names;
+int count;
+{
+ char name1[2048], name2[2048];
+ int i;
+
+ if (count == 1)
+ return 0;
+
+ for (i = 0; i < count; i++) {
+ if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
+ fprintf(stderr, "bad font name: %s\n", names[i]);
+ return 1;
+ }
+ if (i > 0 && strcmp(name1, name2) != 0) {
+ fprintf(stderr, "ambiguous font name: %s\n", font_name);
+ fprintf(stderr, " matches %s\n", names[0]);
+ fprintf(stderr, " and %s\n", names[i]);
+ return 1;
+ }
+
+ }
+ return 0;
+}
+
+MapFont (font_name, troff_name)
+ char *font_name;
+ char *troff_name;
+{
+ XFontStruct *fi;
+ int count;
+ char **names;
+ FILE *out;
+ int c;
+ unsigned int attributes;
+ XFontName parsed;
+ int j, k;
+ DviCharNameMap *char_map;
+ char encoding[256];
+ char *s;
+ int wid;
+ char name_string[2048];
+
+ if (!XParseFontName(font_name, &parsed, &attributes)) {
+ fprintf (stderr, "not a standard name: %s\n", font_name);
+ return 0;
+ }
+
+ attributes &= ~(FontNamePixelSize|FontNameAverageWidth);
+ attributes |= FontNameResolutionX;
+ attributes |= FontNameResolutionY;
+ attributes |= FontNamePointSize;
+ parsed.ResolutionX = resolution;
+ parsed.ResolutionY = resolution;
+ parsed.PointSize = point_size*10;
+ XFormatFontName(&parsed, attributes, name_string);
+
+ names = XListFonts (dpy, name_string, 100000, &count);
+ if (count < 1) {
+ fprintf (stderr, "bad font name: %s\n", font_name);
+ return 0;
+ }
+
+ if (FontNamesAmbiguous(font_name, names, count))
+ return 0;
+
+ XParseFontName(names[0], &parsed, &attributes);
+ sprintf (encoding, "%s-%s", parsed.CharSetRegistry,
+ parsed.CharSetEncoding);
+ for (s = encoding; *s; s++)
+ if (isupper (*s))
+ *s = tolower (*s);
+ char_map = DviFindMap (encoding);
+ if (!char_map) {
+ fprintf (stderr, "not a standard encoding: %s\n", encoding);
+ return 0;
+ }
+
+ fi = XLoadQueryFont (dpy, names[0]);
+ if (!fi) {
+ fprintf (stderr, "font does not exist: %s\n", names[0]);
+ return 0;
+ }
+
+ printf ("%s -> %s\n", names[0], troff_name);
+
+ (void) unlink (troff_name);
+ out = fopen (troff_name, "w");
+ if (!out) {
+ perror (troff_name);
+ return 0;
+ }
+ fprintf (out, "name %s\n", troff_name);
+ if (!strcmp (char_map->encoding, "adobe-fontspecific"))
+ fprintf (out, "special\n");
+ if (charExists (fi, ' ')) {
+ int w = charWidth (fi, ' ');
+ if (w > 0)
+ fprintf (out, "spacewidth %d\n", w);
+ }
+ fprintf (out, "charset\n");
+ for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
+ char *name = DviCharName (char_map,c,0);
+ if (charExists (fi, c) && (groff_flag || name)) {
+
+ wid = charWidth (fi, c);
+
+ fprintf (out, "%s\t%d",
+ name ? name : "---",
+ wid);
+ if (groff_flag) {
+ int param[5];
+ param[0] = charHeight (fi, c);
+ param[1] = charDepth (fi, c);
+ param[2] = 0 /* charRBearing (fi, c) - wid */;
+ param[3] = 0 /* charLBearing (fi, c) */;
+ param[4] = 0; /* XXX */
+ for (j = 0; j < 5; j++)
+ if (param[j] < 0)
+ param[j] = 0;
+ for (j = 4; j >= 0; j--)
+ if (param[j] != 0)
+ break;
+ for (k = 0; k <= j; k++)
+ fprintf (out, ",%d", param[k]);
+ }
+ fprintf (out, "\t0\t0%o\n", c);
+
+ if (name) {
+ for (k = 1; DviCharName(char_map,c,k); k++) {
+ fprintf (out, "%s\t\"\n",
+ DviCharName (char_map,c,k));
+ }
+ }
+ }
+ }
+ XUnloadFont (dpy, fi->fid);
+ fclose (out);
+ return 1;
+}
+
+static usage(prog)
+ char *prog;
+{
+ fprintf (stderr,
+ "usage: %s [-g] [-r resolution] [-s pointsize FontMap\n",
+ prog);
+ exit (1);
+}
+
+
+/* For use by DviChar.c */
+
+char *xmalloc(n)
+int n;
+{
+ char *p = malloc(n);
+ if (!p) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+main (argc, argv)
+ char **argv;
+{
+ char troff_name[1024];
+ char font_name[1024];
+ char line[1024];
+ char *a, *b, c;
+ int position;
+ FILE *map;
+ int opt;
+ extern int optind;
+ extern char *optarg;
+
+ while ((opt = getopt(argc, argv, "gr:s:")) != EOF) {
+ switch (opt) {
+ case 'g':
+ groff_flag = 1;
+ break;
+ case 'r':
+ sscanf(optarg, "%u", &resolution);
+ break;
+ case 's':
+ sscanf(optarg, "%u", &point_size);
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+ if (argc - optind != 1)
+ usage(argv[0]);
+
+ dpy = XOpenDisplay (0);
+ if (!dpy) {
+ fprintf (stderr, "Can't connect to the X server.\n");
+ fprintf (stderr, "Make sure the DISPLAY environment variable is set correctly.\n");
+ exit (1);
+ }
+ position = 1;
+
+ map = fopen (argv[optind], "r");
+ if (map == NULL) {
+ perror (argv[optind]);
+ exit (1);
+ }
+
+ while (fgets (line, sizeof (line), map)) {
+ for (a=line,b=troff_name; *a; a++,b++) {
+ c = (*b = *a);
+ if (c == ' ' || c == '\t')
+ break;
+ }
+ *b = '\0';
+ while (*a && (*a == ' ' || *a == '\t'))
+ ++a;
+ for (b=font_name; *a; a++,b++)
+ if ((*b = *a) == '\n')
+ break;
+ *b = '\0';
+ if (!MapFont (font_name, troff_name))
+ exit (1);
+ ++position;
+ }
+ exit (0);
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/gnu/usr.bin/gzip/bits.c b/gnu/usr.bin/gzip/bits.c
index 544d6da9d394..694e6475b50c 100644
--- a/gnu/usr.bin/gzip/bits.c
+++ b/gnu/usr.bin/gzip/bits.c
@@ -60,7 +60,7 @@
#endif
#ifdef RCSID
-static char rcsid[] = "$Id: bits.c,v 0.9 1993/06/11 10:16:58 jloup Exp $";
+static char rcsid[] = "bits.c,v 1.3 1993/10/14 00:32:24 nate Exp";
#endif
/* ===========================================================================
diff --git a/gnu/usr.bin/gzip/crypt.c b/gnu/usr.bin/gzip/crypt.c
index cbce024a01aa..6b1267bed0e4 100644
--- a/gnu/usr.bin/gzip/crypt.c
+++ b/gnu/usr.bin/gzip/crypt.c
@@ -2,5 +2,5 @@
* Hardly worth copyrighting :-)
*/
#ifdef RCSID
-static char rcsid[] = "$Id: crypt.c,v 0.6 1993/03/22 09:48:47 jloup Exp $";
+static char rcsid[] = "crypt.c,v 1.3 1993/10/14 00:32:26 nate Exp";
#endif
diff --git a/gnu/usr.bin/gzip/deflate.c b/gnu/usr.bin/gzip/deflate.c
index 7f52b64fa754..78764748894d 100644
--- a/gnu/usr.bin/gzip/deflate.c
+++ b/gnu/usr.bin/gzip/deflate.c
@@ -68,7 +68,7 @@
#include "lzw.h" /* just for consistency checking */
#ifdef RCSID
-static char rcsid[] = "$Id: deflate.c,v 0.15 1993/06/24 10:53:53 jloup Exp $";
+static char rcsid[] = "deflate.c,v 1.3 1993/10/14 00:32:29 nate Exp";
#endif
/* ===========================================================================
diff --git a/gnu/usr.bin/gzip/gzip.c b/gnu/usr.bin/gzip/gzip.c
index 09fe9a16f241..a9629aad7830 100644
--- a/gnu/usr.bin/gzip/gzip.c
+++ b/gnu/usr.bin/gzip/gzip.c
@@ -45,7 +45,7 @@ static char *license_msg[] = {
*/
#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 0.24 1993/06/24 10:52:07 jloup Exp $";
+static char rcsid[] = "gzip.c,v 1.3 1993/10/14 00:32:48 nate Exp";
#endif
#include <ctype.h>
diff --git a/gnu/usr.bin/gzip/inflate.c b/gnu/usr.bin/gzip/inflate.c
index ede365622b46..74ac90b645d1 100644
--- a/gnu/usr.bin/gzip/inflate.c
+++ b/gnu/usr.bin/gzip/inflate.c
@@ -97,7 +97,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp $";
+static char rcsid[] = "inflate.c,v 1.3 1993/10/14 00:32:55 nate Exp";
#endif
#include <sys/types.h>
diff --git a/gnu/usr.bin/gzip/lzw.c b/gnu/usr.bin/gzip/lzw.c
index 12bf5c611d0c..85d5bd892b0f 100644
--- a/gnu/usr.bin/gzip/lzw.c
+++ b/gnu/usr.bin/gzip/lzw.c
@@ -3,7 +3,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: lzw.c,v 0.9 1993/06/10 13:27:31 jloup Exp $";
+static char rcsid[] = "lzw.c,v 1.3 1993/10/14 00:32:59 nate Exp";
#endif
#include "tailor.h"
diff --git a/gnu/usr.bin/gzip/match.S b/gnu/usr.bin/gzip/match.S
index 4a3d681c3d2b..7d235101a1d5 100644
--- a/gnu/usr.bin/gzip/match.S
+++ b/gnu/usr.bin/gzip/match.S
@@ -9,7 +9,7 @@
* Kristoffer Eriksson <ske@pkmab.se>
*/
-/* $Id: match.S,v 0.14 1993/06/11 18:33:24 jloup Exp $ */
+/* match.S,v 1.3 1993/10/14 00:33:02 nate Exp */
/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
* external symbols with an underline character '_'.
diff --git a/gnu/usr.bin/gzip/revision.h b/gnu/usr.bin/gzip/revision.h
index f99b65f9bbd2..c47960249789 100644
--- a/gnu/usr.bin/gzip/revision.h
+++ b/gnu/usr.bin/gzip/revision.h
@@ -13,4 +13,4 @@
# undef LZW
#endif
-/* $Id: revision.h,v 0.25 1993/06/24 08:29:52 jloup Exp $ */
+/* revision.h,v 1.3 1993/10/14 00:33:05 nate Exp */
diff --git a/gnu/usr.bin/gzip/tailor.h b/gnu/usr.bin/gzip/tailor.h
index a97d8bee95b8..33074c915a90 100644
--- a/gnu/usr.bin/gzip/tailor.h
+++ b/gnu/usr.bin/gzip/tailor.h
@@ -8,7 +8,7 @@
* The target dependent functions should be defined in tailor.c.
*/
-/* $Id: tailor.h,v 0.18 1993/06/14 19:32:20 jloup Exp $ */
+/* tailor.h,v 1.3 1993/10/14 00:33:08 nate Exp */
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
diff --git a/gnu/usr.bin/gzip/trees.c b/gnu/usr.bin/gzip/trees.c
index db3b4b700aef..b0685c85e397 100644
--- a/gnu/usr.bin/gzip/trees.c
+++ b/gnu/usr.bin/gzip/trees.c
@@ -59,7 +59,7 @@
#include "gzip.h"
#ifdef RCSID
-static char rcsid[] = "$Id: trees.c,v 0.12 1993/06/10 13:27:54 jloup Exp $";
+static char rcsid[] = "trees.c,v 1.3 1993/10/14 00:33:11 nate Exp";
#endif
/* ===========================================================================
diff --git a/gnu/usr.bin/gzip/unlzh.c b/gnu/usr.bin/gzip/unlzh.c
index e318e5ed9418..d01da999bfee 100644
--- a/gnu/usr.bin/gzip/unlzh.c
+++ b/gnu/usr.bin/gzip/unlzh.c
@@ -4,7 +4,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: unlzh.c,v 1.2 1993/06/24 10:59:01 jloup Exp $";
+static char rcsid[] = "unlzh.c,v 1.2 1993/10/14 00:33:14 nate Exp";
#endif
#include <stdio.h>
diff --git a/gnu/usr.bin/gzip/unlzw.c b/gnu/usr.bin/gzip/unlzw.c
index 15d2a313b4b1..4b33882c24ac 100644
--- a/gnu/usr.bin/gzip/unlzw.c
+++ b/gnu/usr.bin/gzip/unlzw.c
@@ -8,7 +8,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: unlzw.c,v 0.15 1993/06/10 13:28:35 jloup Exp $";
+static char rcsid[] = "unlzw.c,v 1.3 1993/10/14 00:33:17 nate Exp";
#endif
#include <sys/types.h>
diff --git a/gnu/usr.bin/gzip/unpack.c b/gnu/usr.bin/gzip/unpack.c
index a00fdaefc6b2..dc9e2e2284dc 100644
--- a/gnu/usr.bin/gzip/unpack.c
+++ b/gnu/usr.bin/gzip/unpack.c
@@ -5,7 +5,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: unpack.c,v 1.4 1993/06/11 19:25:36 jloup Exp $";
+static char rcsid[] = "unpack.c,v 1.3 1993/10/14 00:33:20 nate Exp";
#endif
#include "tailor.h"
diff --git a/gnu/usr.bin/gzip/unzip.c b/gnu/usr.bin/gzip/unzip.c
index 7e287a157ad3..3e0b76570a48 100644
--- a/gnu/usr.bin/gzip/unzip.c
+++ b/gnu/usr.bin/gzip/unzip.c
@@ -14,7 +14,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: unzip.c,v 0.13 1993/06/10 13:29:00 jloup Exp $";
+static char rcsid[] = "unzip.c,v 1.3 1993/10/14 00:33:24 nate Exp";
#endif
#include "tailor.h"
diff --git a/gnu/usr.bin/gzip/util.c b/gnu/usr.bin/gzip/util.c
index 70375d85362c..691b1ba9b2cc 100644
--- a/gnu/usr.bin/gzip/util.c
+++ b/gnu/usr.bin/gzip/util.c
@@ -5,7 +5,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: util.c,v 0.15 1993/06/15 09:04:13 jloup Exp $";
+static char rcsid[] = "util.c,v 1.3 1993/10/14 00:33:26 nate Exp";
#endif
#include <ctype.h>
diff --git a/gnu/usr.bin/gzip/zip.c b/gnu/usr.bin/gzip/zip.c
index 507d1616efdd..a9b38a114aa9 100644
--- a/gnu/usr.bin/gzip/zip.c
+++ b/gnu/usr.bin/gzip/zip.c
@@ -5,7 +5,7 @@
*/
#ifdef RCSID
-static char rcsid[] = "$Id: zip.c,v 0.17 1993/06/10 13:29:25 jloup Exp $";
+static char rcsid[] = "zip.c,v 1.3 1993/10/14 00:33:32 nate Exp";
#endif
#include <ctype.h>
diff --git a/gnu/usr.bin/kgdb/COPYING b/gnu/usr.bin/kgdb/COPYING
new file mode 100644
index 000000000000..9a1703758111
--- /dev/null
+++ b/gnu/usr.bin/kgdb/COPYING
@@ -0,0 +1,249 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/gnu/usr.bin/kgdb/ChangeLog b/gnu/usr.bin/kgdb/ChangeLog
new file mode 100644
index 000000000000..1f2342b797a7
--- /dev/null
+++ b/gnu/usr.bin/kgdb/ChangeLog
@@ -0,0 +1,4887 @@
+Thu Feb 8 01:11:55 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * GDB 3.5 released.
+
+ * version.c: Change version number to 3.5
+
+Tue Feb 6 15:58:06 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * m-hp9k320.h: define ATTACH_DETACH.
+ hp9k320-dep.c [ATTACH_DETACH]: New code.
+
+Thu Feb 1 17:43:00 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * valprint.c (is_nan, val_print): Use char * not void *.
+
+ * symmisc.c (print_symbol): Print newline after label.
+
+Tue Jan 30 15:35:52 1990 Jim Kingdon (kingdon at albert.ai.mit.edu)
+
+ * Makefile.dist (READLINE): Add {readline,history}.texinfo.
+
+ * m-merlin.h: Put in clarifying comments about SHELL_FILE.
+ config.gdb (merlin): Explain about /usr/local/lib/gdb-sh.
+
+Sat Jan 27 02:30:27 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * version.c: Change version number to 3.5alpha.1.
+
+ * dbxread.c (process_one_symbol): Compare context_stack_depth
+ with !VARIABLES_INSIDE_BLOCK, not VARIABLES_INSIDE_BLOCK.
+
+Fri Jan 26 01:21:51 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * main.c [ALIGN_STACK_ON_STARTUP]: New code.
+ m-i386.h: Define ALIGN_STACK_ON_STARTUP.
+
+ * m-merlin.h (NO_SIGINTERRUPT, SHELL_FILE): Define.
+
+ * umax-dep.c (exec_file_command): Add commas to call to
+ read_section_hdr.
+
+Tue Jan 23 15:49:47 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * dbxread.c (define_symbol): Deal with deftype 'X'.
+
+ * convex-dep.c (wait): Make it pid_t.
+
+ * convex-dep.c (comm_registers_info): accept decimal comm register
+ specification, as "i comm 32768".
+
+ * dbxread.c (process_one_symbol): Make VARIABLES_INSIDE_BLOCK
+ macro say by itself where variables are. Pass it desc.
+ m-convex.h (VARIABLES_INSIDE_BLOCK): Nonzero for native compiler.
+
+ * m-convex.h (SET_STACK_LIMIT_HUGE): Define.
+ (IGNORE_SYMBOL): Take out #ifdef N_MONPT and put in 0xc4.
+
+Fri Jan 19 20:04:15 1990 Jim Kingdon (kingdon at albert.ai.mit.edu)
+
+ * printcmd.c (print_frame_args): Always set highest_offset to
+ current_offset when former is -1.
+
+ * dbxread.c (read_struct_type): Print nice error message
+ when encountering multiple inheritance.
+
+Thu Jan 18 13:43:30 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Always treat N_FN as a potential
+ source for a x.o or -lx symbol, ignoring OFILE_FN_FLAGGED.
+
+ * printcmd.c (print_frame_args): Cast -1 to (CORE_ADDR).
+
+ * hp300bsd-dep.c (_initialize_hp300_dep): Get kernel_u_addr.
+ m-hp300bsd.h (KERNEL_U_ADDR): Use kernel_u_addr.
+
+ * infcmd.c (run_command): #if 0 out call to
+ breakpoint_clear_ignore_counts.
+
+Thu Jan 11 12:58:12 1990 Jim Kingdon (kingdon at mole)
+
+ * printcmd.c (print_frame_args) [STRUCT_ARG_SYM_GARBAGE]:
+ Try looking up name of var before giving up & printing '?'.
+
+Wed Jan 10 14:00:14 1990 Jim Kingdon (kingdon at pogo)
+
+ * many files: Move stdio.h before param.h.
+
+ * sun3-dep.c (store_inferior_registers): Only try to write FP
+ regs #ifdef FP0_REGNUM.
+
+Mon Jan 8 17:56:15 1990 Jim Kingdon (kingdon at pogo)
+
+ * symtab.c: #if 0 out "info methods" code.
+
+Sat Jan 6 12:33:04 1990 Jim Kingdon (kingdon at pogo)
+
+ * dbxread.c (read_struct_type): Set TYPE_NFN_FIELDS_TOTAL
+ from all baseclasses; remove vestigial variable baseclass.
+
+ * findvar.c (read_var_value): Check REG_STRUCT_HAS_ADDR.
+ printcmd.c (print_frame_args): Check STRUCT_ARG_SYM_GARBAGE.
+ m-sparc.h: Define REG_STRUCT_HAS_ADDR and STRUCT_ARG_SYM_GARBAGE.
+
+ * blockframe.c (get_frame_block): Subtract one from pc if not
+ innermost frame.
+
+Fri Dec 29 15:26:33 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * printcmd.c (print_frame_args): check highest_offset != -1, not i.
+
+Thu Dec 28 16:21:02 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * valops.c (value_struct_elt): Clean up error msg.
+
+ * breakpoint.c (describe_other_breakpoints):
+ Delete extra space before "also set at" and add period at end.
+
+Tue Dec 19 10:28:42 1989 Jim Kingdon (kingdon at pogo)
+
+ * source.c (print_source_lines): Tell user which line number
+ was out of range when printing error message.
+
+Sun Dec 17 14:14:09 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * blockframe.c (find_pc_partial_function): Use
+ BLOCK_START (SYMBOL_BLOCK_VALUE (f)) instead of
+ SYMBOL_VALUE (f) to get start of function.
+
+ * dbxread.c: Make xxmalloc just a #define for xmalloc.
+
+Thu Dec 14 16:13:16 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * m68k-opcode.h (fseq & following fp instructions):
+ Change @ to $.
+
+Fri Dec 8 19:06:44 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * breakpoint.c (breakpoint_clear_ignore_counts): New function.
+ infcmd.c (run_command): Call it.
+
+Wed Dec 6 15:03:38 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * valprint.c: Change it so "array-max 0" means there is
+ no limit.
+
+ * expread.y (yylex): Change error message "invalid token in
+ expression" to "invalid character '%c' in expression".
+
+Mon Dec 4 16:12:54 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * blockframe.c (find_pc_partial_function): Always return 1
+ for success, 0 for failure, and set *NAME and *ADDRESS to
+ match the return value.
+
+ * dbxread.c (symbol_file_command): Use perror_with_name on
+ error from stat.
+ (psymtab_to_symtab, add_file_command),
+ core.c (validate_files), source.c (find_source_lines),
+ default-dep.c (exec_file_command): Check for errors from stat,
+ fstat, and myread.
+
+Fri Dec 1 05:16:42 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * valops.c (check_field): When following pointers, just get
+ their types; don't call value_ind.
+
+Thu Nov 30 14:45:29 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * config.gdb (pyr): New machine.
+ core.c [REG_STACK_SEGMENT]: New code.
+ dbxread.c (process_one_symbol): Cast return from copy_pending
+ to long before casting to enum namespace.
+ infrun.c: Split registers_info into DO_REGISTERS_INFO
+ and registers_info.
+ m-pyr.h, pyr-{dep.c,opcode.h,pinsn.c}: New files.
+
+ * hp300bsd-dep.c: Stay in sync with default-dep.c.
+
+ * m-hp300bsd.h (IN_SIGTRAMP): Define.
+
+Mon Nov 27 23:48:21 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE):
+ Return floating point values in %f0.
+
+Tue Nov 21 00:34:46 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c (read_type): #if 0 out code which skips to
+ comma following x-ref.
+
+Sat Nov 18 20:10:54 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * valprint.c (val_print): Undo changes of Nov 11 & 16.
+ (print_string): Add parameter force_ellipses.
+ (val_print): Pass force_ellipses true when we stop fetching string
+ before we get to the end, else pass false.
+
+Thu Nov 16 11:59:50 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * infrun.c (restore_inferior_status): Don't try to restore
+ selected frame if the inferior no longer exists.
+
+ * valprint.c (val_print): Rewrite string printing code not to
+ call print_string.
+
+ * Makefile.dist (clean): Remove xgdb and xgdb.o.
+
+Tue Nov 14 12:41:47 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * Makefile.dist (XGDB, bindir, xbindir, install, all): New stuff.
+
+Sat Nov 11 15:29:38 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * valprint.c (val_print): chars_to_get: New variable.
+
+Thu Nov 9 12:31:47 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * main.c (main): Process "-help" as a switch that doesn't
+ take an argument.
+
+Wed Nov 8 13:07:02 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * Makefile.dist (gdb.tar.Z): Add "else true".
+
+Tue Nov 7 12:25:14 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * infrun.c (restore_inferior_status): Don't dereference fid if NULL.
+
+ * config.gdb (sun3, sun4): Accept "sun3" and "sun4".
+
+Mon Nov 6 09:49:23 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * Makefile.dist (Makefile): Move comments after commands.
+
+ * *-dep.c [READ_COFF_SYMTAB]: Pass optional header size to
+ read_section_hdr().
+
+ * inflow.c: Include <fcntl.h> regardless of USG.
+
+ * coffread.c (read_section_hdr): Add optional_header_size.
+ (symbol_file_command): Pass optional header size to
+ read_section_hdr().
+ (read_coff_symtab): Initialize filestring.
+
+ * version.c: Change version to 3.4.xxx.
+
+ * GDB 3.4 released.
+
+Sun Nov 5 11:39:01 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * version.c: Change version to 3.4.
+
+ * symtab.c (decode_line_1): Only skip past "struct" if it
+ is there.
+
+ * valops.c (value_ind), eval.c (evaluate_subexp, case UNOP_IND):
+ Have "*" <int-valued-exp> return an int, not a LONGEST.
+
+ * utils.c (fprintf_filtered): Pass arg{4,5,6} to sprintf.
+
+ * printcmd.c (x_command): Use variable itself rather
+ than treating it as a pointer only if it is a function.
+ (See comment "this makes x/i main work").
+
+ * coffread.c (symbol_file_command): Use error for
+ "%s does not have a symbol-table.\n".
+
+Wed Nov 1 19:56:18 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c [BELIEVE_PCC_PROMOTION_TYPE]: New code.
+ m-sparc.h: Define BELIEVE_PCC_PROMOTION_TYPE.
+
+Thu Oct 26 12:45:00 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * infrun.c: Include <sys/dir.h>.
+
+ * dbxread.c (read_dbx_symtab, case N_LSYM, case 'T'):
+ Check for enum types and put constants in psymtab.
+
+Mon Oct 23 15:02:25 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c (define_symbol, read_dbx_symtab): Handle enum
+ constants (e.g. "b:c=e6,0").
+
+Thu Oct 19 14:57:26 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * stack.c (frame_info): Use FRAME_ARGS_ADDRESS_CORRECT
+ m-vax.h (FRAME_ARGS_ADDRESS_CORRECT): New macro.
+ (FRAME_ARGS_ADDRESS): Restore old meaning.
+
+ * frame.h (Frame_unknown): New macro.
+ stack.c (frame_info): Check for Frame_unknown return from
+ FRAME_ARGS_ADDRESS.
+ m-vax.h (FRAME_ARGS_ADDRESS): Sometimes return Frame_unknown.
+
+ * utils.c (fatal_dump_core): Add "internal error" to message.
+
+ * infrun.c (IN_SIGTRAMP): New macro.
+ (wait_for_inferior): Use IN_SIGTRAMP.
+ m-vax.h (IN_SIGTRAMP): New macro.
+
+Wed Oct 18 15:09:22 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * config.gdb, Makefile.dist: Shorten m-i386-sv32.h.
+
+ * coffread.c (symbol_file_command): Pass 0 to select_source_symtab.
+
+Tue Oct 17 12:24:41 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * i386-dep.c (i386_frame_num_args): Take function from m-i386.h
+ file. Check for pfi null.
+ m-i386.h (FRAME_NUM_ARGS): Use i386_frame_num_args.
+
+ * infrun.c (wait_for_inferior): set stop_func_name to 0
+ before calling find_pc_partial_function.
+
+Thu Oct 12 01:08:50 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * breakpoint.c (_initialize_breakpoint): Add "disa".
+
+ * Makefile.dist: Add GLOBAL_CFLAGS and pass to readline.
+
+ * config.gdb (various): "$machine =" -> "machine =".
+
+Wed Oct 11 11:54:31 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * inflow.c (try_writing_regs): #if 0 out this function.
+
+ * main.c (main): Add "-help" option.
+
+ * dbxread.c (read_dbx_symtab): Merge code for N_FUN with
+ N_STSYM, etc.
+
+Mon Oct 9 14:21:55 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * inflow.c (try_writing_regs_command): Don't write past end
+ of struct user.
+
+ * dbxread.c (read_struct_type): #if 0 out code which checks for
+ bitpos and bitsize 0.
+
+ * config.gdb: Accept sequent-i386 (not seq386).
+ (symmetry): Set depfile and paramfile.
+
+ * m-convex.h (IGNORE_SYMBOL): Check for N_MONPT if defined.
+
+Thu Oct 5 10:14:26 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * default-dep.c (read_inferior_memory): Put #if 0'd out comment
+ within /* */.
+
+Wed Oct 4 18:44:41 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * config.gdb: Change /dev/null to m-i386.h for various
+ 386 machine "opcodefile" entries.
+
+ * config.gdb: Accept seq386 for sequent symmetry.
+
+Mon Oct 2 09:59:50 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * hp300bsd-dep.c: Fix copyright notice.
+
+Sun Oct 1 16:25:30 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * Makefile.dist (DEPFILES): Add isi-dep.c.
+
+ * default-dep.c (read_inferior_memory): Move #endif after else.
+
+Sat Sep 30 12:50:16 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * version.c: Change version number to 3.3.xxx.
+
+ * GDB 3.3 released.
+
+ * version.c: Change version number to 3.3.
+
+ * Makefile.dist (READLINE): Add vi_mode.c
+
+ * config.gdb (i386): Change /dev/null to m-i386.h
+
+ * config.gdb: Add ';;' before 'esac'.
+
+ * Makefile.dist (gdb.tar.Z): Move comment above dependency.
+
+ * dbxread.c (read_ofile_symtab): Check symbol before start
+ of source file for GCC_COMPILED_FLAG_SYMBOL.
+ (start_symtab): Don't clear processing_gcc_compilation.
+
+Thu Sep 28 22:30:23 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
+
+ * valprint.c (print_string): If LENGTH is zero, print "".
+
+Wed Sep 27 10:15:10 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * config.gdb: "rm tmp.c" -> "rm -f tmp.c".
+
+Tue Sep 26 13:02:10 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * utils.c (_initialize_utils): Use termcap to set lines_per_page
+ and chars_per_line.
+
+Mon Sep 25 10:06:43 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab, N_SOL): Do not add the same file
+ more than once.
+
+Thu Sep 21 12:43:18 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * infcmd.c (unset_environment_command): Delete all variables
+ if called with no arg.
+
+ * remote.c, inferior.h (remote_{read,write}_inferior_memory):
+ New functions.
+ core.c ({read,write}_memory): Use remote_{read,write}_inferior_memory.
+
+ * valops.c (call_function): When reserving stack space for
+ arguments, call value_arg_coerce.
+
+ * m-hp9k320.h: define BROKEN_LARGE_ALLOCA.
+
+ * breakpoint.c (delete_command): Ask for confirmation only
+ when there are breakpoints.
+
+ * dbxread.c (read_struct_type): If lookup_basetype_type has
+ copied a stub type, call add_undefined_type.
+
+ * sparc_pinsn.c (compare_opcodes): Check for "1+i" anywhere
+ in args.
+
+ * val_print.c (type_print_base): Print stub types as
+ "<incomplete type>".
+
+Wed Sep 20 07:32:00 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * sparc-opcode.h (swapa): Remove i bit from match.
+ (all alternate space instructions): Delete surplus "foo rs1+0"
+ patterns.
+
+ * Makefile.dist (LDFLAGS): Set to $(CFLAGS).
+
+ * remote-multi.shar (remote_utils.c, putpkt): Change csum to unsigned.
+
+Tue Sep 19 14:15:16 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * sparc-opcode.h: Set i bit in lose for many instructions which
+ aren't immediate.
+
+ * stack.c (print_frame_info): add "func = 0".
+
+Mon Sep 18 16:19:48 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * sparc-opcode.h (mov): Add mov to/from %tbr, %psr, %wim.
+
+ * sparc-opcode.h (rett): Fix notation to use suggested assembler
+ syntax from architecture manual.
+
+ * symmetry-dep.c (I386_REGNO_TO_SYMMETRY): New macro.
+ (i386_frame_find_saved_regs): Use I386_REGNO_TO_SYMMETRY.
+
+Sat Sep 16 22:21:17 1989 Jim Kingdon (kingdon at spiff)
+
+ * remote.c (remote_close): Set remote_desc to -1.
+
+ * gdb.texinfo (Output): Fix description of echo to match
+ reality and ANSI C.
+
+Fri Sep 15 14:28:59 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * symtab.c (lookup_symbol): Add comment about "asm".
+
+ * sparc-pinsn.c: Use NUMOPCODES.
+
+ * sparc-opcode.h (NUMOPCODES): Use sparc_opcodes[0] not *sparc_opcodes.
+
+Thu Sep 14 15:25:20 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (xxmalloc): Print error message before calling abort().
+
+ * infrun.c (wait_for_inferior): Check for {stop,prev}_func_name
+ null before passing to strcmp.
+
+Wed Sep 13 12:34:15 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * sparc-opcode.h: New field delayed.
+ sparc-pinsn.c (is_delayed_branch): New function.
+ (print_insn): Check for delayed branches.
+
+ * stack.c (print_frame_info): Use misc_function_vector in
+ case where ar truncates file names.
+
+Tue Sep 12 00:16:14 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * convex-dep.c (psw_info): Move "struct pswbit *p" with declarations.
+
+Mon Sep 11 14:59:57 1989 Jim Kingdon (kingdon at spiff)
+
+ * convex-dep.c (core_file_command): Delete redundant printing
+ of "Program %s".
+
+ * m-convex.h (ENTRY_POINT): New macro.
+
+ * m-convex.h (FRAME_CHAIN_VALID): Change outside_first_object_file
+ to outside_startup_file
+
+ * main.c: #if 0 out catch_termination and related code.
+
+ * command.c (lookup_cmd_1): Consider underscores part of
+ command names.
+
+Sun Sep 10 09:20:12 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * printcmd.c: Change asdump_command to disassemble_command
+ (_initialize_printcmd): Change asdump to diassemble.
+
+ * main.c (main): Exit with code 0 if we hit the end of a batch
+ file.
+
+ * Makefile.dist (libreadline.a): Fix syntax of "CC=${CC}".
+
+Sat Sep 9 01:07:18 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * values.c (history_info): Renamed to value_history_info.
+ Command renamed to "info value" (with "info history" still
+ accepted).
+
+ * sparc-pinsn.c (print_insn): Extend symbolic address printing
+ to cover "sethi" following by an insn which uses 1+i.
+
+Fri Sep 8 14:24:01 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * m-hp9k320.h, m-hp300bsd.h, m-altos.h, m-sparc.h, m-sun3.h
+ (READ_GDB_SYMSEGS): Remove.
+ dbxread.c [READ_GDB_SYMSEGS]: Remove code to read symsegs.
+
+ * sparc-pinsn.c (print_insn): Detect "sethi-or" pairs and
+ print symbolic address.
+
+ * sparc-opcode.h (sethi, set): Change lose from 0xc0000000 to
+ 0xc0c00000000.
+
+ * remote.c (remote_desc): Initialize to -1.
+
+ * Makefile.dist (libreadline.a): Pass CC='${CC}' to readline makefile.
+
+Thu Sep 7 00:07:17 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_struct_type): Check for static member functions.
+ values.c, eval.c, valarith.c, valprint.c, valops.c: Merge changes
+ from Tiemann for static member functions.
+
+ * sparc-opcode.h (tst): Fix all 3 patterns.
+
+ * Makefile.dist (gdb1): New rule.
+
+ * sparc-opcode.h: Change comment about what the disassembler
+ does with the order of the opcodes.
+
+ * sparc-pinsn.c (compare_opcodes): Put 1+i before i+1.
+ Also fix mistaken comment about preserving order of original table.
+
+ * sparc-opcode.h (clr, mov): Fix incorrect lose entries.
+
+ * m-symmetry.h (FRAME_NUM_ARGS): Add check to deal with code that
+ GCC sometimes generates.
+
+ * config.gdb: Change all occurances of "skip" to "/dev/null".
+
+ * README (about languages other than C): Update comments about
+ Pascal and FORTRAN.
+
+ * sparc-opcode.h (nop): Change lose from 0xae3fffff to 0xfe3fffff.
+
+ * values.c (value_virtual_fn_field): #if 0-out assignment to
+ VALUE_TYPE(vtbl).
+
+Wed Sep 6 12:19:22 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * utils.c (fatal_dump_core): New function.
+ Makefile.dist (MALLOC_FLAGS): use -Dbotch=fatal_dump_core
+
+Tue Sep 5 15:47:18 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * breakpoint.c (enable_command): With no arg, enable all bkpts.
+
+ * Makefile.dist (Makefile): Remove \"'s around $(MD).
+
+ * Makefile.dist: In "cd readline; make . . ." change first
+ SYSV_DEFINE to SYSV.
+
+ * m68k-pinsn.c (_initialize_pinsn): Use alternate assembler
+ syntax #ifdef HPUX_ASM
+
+Sat Sep 2 23:24:43 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * values.c (history_info): Don't check num_exp[0] if num_exp
+ is nil (just like recent editing_info change).
+
+Fri Sep 1 19:19:01 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * gdb.texinfo (inc-history, inc-readline): Copy in the inc-* files
+ because people might not have makeinfo.
+
+ * README (xgdb): Strengthen nasty comments.
+
+ * gdb.texinfo: Change @setfilename to "gdb.info".
+
+Thu Aug 31 17:23:50 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * main.c (editing_info): Don't check arg[0] if arg is null.
+
+ * m-vax.h: Add comment about known sigtramp bug.
+
+ * sun3-dep.c, sparc-dep.c (IS_OBJECT_FILE, exec_file_command):
+ Get right text & data addresses for .o files.
+
+Wed Aug 30 13:54:19 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * utils.c (tilde_expand): Remove function (it's in readline).
+
+ * sparc-opcode.h (call): Change "8" to "9" in first two
+ patterns (%g7->%o7).
+
+Tue Aug 29 16:44:41 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * printcmd.c (whatis_command): Change 4th arg to type_print
+ from 1 to -1.
+
+Mon Aug 28 12:22:41 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c (psymtab_to_symtab_1): In "and %s ..." change
+ pst->filename to pst->dependencies[i]->filename.
+
+ * blockframe.c (FRAMELESS_LOOK_FOR_PROLOGUE): New macro
+ made from FRAMELESS_FUNCTION_INVOCATION from m-sun3.h except
+ that it checks for zero return from get_pc_function_start.
+ m-hp9k320.h, m-hp300bsd.h, m-i386.h, m-isi.h, m-altos.h,
+ m-news.h, m-sparc.h, m-sun2.h, m-sun3.h, m-symmetry.h
+ (FRAMELESS_FUNCTION_INVOCATION): Use FRAMELESS_LOOK_FOR_PROLOGUE.
+
+ * dbxread.c (read_struct_type): Give warning and ignore field
+ if bitpos and bitsize are zero.
+
+Sun Aug 27 04:55:20 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (psymtab_to_symtab{,_1}): Print message about
+ reading in symbols before reading stringtab, not after.
+
+Sat Aug 26 02:01:53 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c (IS_OBJECT_FILE, ADDR_OF_TEXT_SEGMENT): New macros.
+ (read_dbx_symtab): Use text_addr & text_size to set end_of_text_addr.
+ (symbol_file_command): pass text_addr & text_size to read_dbx_symtab.
+
+Fri Aug 25 23:08:13 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * valprint.c (value_print): Try to give the name of function
+ pointed to when printing a function pointer.
+
+Thu Aug 24 23:18:40 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * core.c (xfer_core_file): In cases where MEMADDR is above the
+ largest address that makes sense, set i to len.
+
+Thu Aug 24 16:04:17 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
+
+ * valprint.c (print_string): New function to print a character
+ string, doing array-max limiting and repeat count processing.
+ (val_print, value_print): Use print_string.
+ (REPEAT_COUNT_THRESHOLD): New #define, the max number of elts to print
+ without using a repeat count. Set to ten.
+ (value_print, val_print): Use REPEAT_COUNT_THRESHOLD.
+
+ * utils.c (printchar): Use {fputs,fprintf}_filtered.
+
+ * valprint.c (val_print): Pass the repeat count arg to the
+ fprintf_filtered call for "<repeats N times>" messages.
+
+Wed Aug 23 22:53:47 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
+
+ * utils.c: Include <pwd.h>.
+
+ * main.c: Declare free.
+
+Wed Aug 23 05:05:59 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * utils.c, defs.h: Add tilde_expand.
+ source.c (directory_command),
+ main.c (cd_command),
+ main.c (set_history_filename),
+ dbxread.c (symbol_file_command),
+ coffread.c (symbol_file_command),
+ dbxread.c (add_file_command),
+ symmisc.c (print_symtabs),
+ *-dep.c (exec_file_command, core_file_command),
+ main.c (source_command): Use tilde_expand.
+
+ * dbxread.c (read_type): When we get a cross-reference, resolve
+ it immediately if possible, only calling add_undefined_type if
+ necessary.
+
+ * gdb.texinfo: Uncomment @includes and put comment at start
+ of file telling people to use makeinfo.
+
+ * valprint.c (type_print_base): Print the right thing for
+ bitfields.
+
+ * config.gdb (sun3os3): Set paramfile and depfile.
+
+Tue Aug 22 05:38:36 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c (symbol_file_command): Pass string table size to
+ read_dbx_symtab().
+ (read_dbx_symtab): Before indexing into string table, check
+ string table index for reasonableness.
+ (psymtab_to_symtab{,_1}, read_ofile_symtab): Same.
+
+Tue Aug 22 04:04:39 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
+
+ * m68k-pinsn.c: Replaced many calls to fprintf and fputs with
+ calls to fprintf_filtered and fputs_filtered.
+ (print_insn_arg): Use normal MIT 68k syntax for postincrement,
+ predecrement, and register indirect addressing modes.
+
+Mon Aug 21 10:08:02 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * main.c (initialize_signals): Set signal handler for SIGQUIT
+ and SIGHUP to do_nothing.
+
+ * ns32k-opcode.h (ord): Change 1D1D to 1D2D.
+
+ * ns32k-pinsn.c (print_insn_arg, print_insn): Handle index
+ bytes correctly.
+
+ * ns32k-opcode.h: Add comments.
+
+ * dbxread.c (read_type): Put enum fields in type.fields in order
+ that they were found in the debugging symbols (not reverse order).
+
+Sun Aug 20 21:17:13 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * main.c (source_command): Read .gdbinit if run without argument.
+
+ * source.c (directory_command): Only print "foo already in path"
+ if from_tty.
+
+ * version.c: Change version number to 3.2.xxx
+
+Sat Aug 19 00:24:08 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * m-news.h: Define HAVE_WAIT_STRUCT.
+
+ * m-isi.h, isi-dep.c: Replace with new version from Adam de Boor.
+ config.gdb: Remove isibsd43.
+
+ * main.c (catch_termination): Don't say we have written
+ .gdb_history until after we really have.
+
+ * convex-dep.c (attach): Add "sleep (1)".
+ (write_vector_register): Use "LL" with long long constant.
+ (wait): Close comment.
+ (wait): Change "unix 7.1 bug" to "unix 7.1 feature" & related
+ changes in comment.
+ (scan_stack): And fp with 0x80000000 in while loop test.
+ (core_file_command): Move code to set COREFILE.
+ (many places): Change printf to printf_filtered.
+ (psw_info): Allow argument giving value to print as a psw.
+ (_initialize_convex_dep): Update docstrings.
+
+ * m-convex.h (WORDS_BIG_ENDIAN): Correct typo ("WRODS")
+ define NO_SIGINTERRUPT.
+ define SET_STACK_LIMIT_HUGE.
+ add "undef BUILTIN_TYPE_LONGEST" before defining it.
+ Use "LL" after constants in CALL_DUMMY.
+
+ * dbxread.c: In the 3 places it says error "ridiculous string
+ table size"... delete extra parameter to error.
+
+ * dbxread.c (scan_file_globals): Check for FORTRAN common block.
+ Allow multiple references for the sake of common blocks.
+
+ * main.c (initialize_main): Set history_filename to include
+ current directory.
+
+ * valprint.c (decode_format): Don't return a defaulted size
+ field if osize is zero.
+
+ * gdb.texinfo (Compilation): Update information on -gg symbols.
+ Document problem with ar.
+
+Fri Aug 18 19:45:20 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * valprint.c (val_print, value_print): Add "<repeats %d times>" code.
+ Also put "..." outside quotes for strings.
+
+ * main.c (initialize_main): Add comment about history output file
+ being different from history input file.
+
+ * m-newsos3.h: Undefine NO_SIGINTERRUPT. Rearrange a few comments.
+
+ * m-newsos3.h (REGISTER_U_ADDR): Use new version from Hikichi.
+
+ * sparc-opcode.h: Add comment clarifying meaning of the order of
+ the entries in sparc_opcodes.
+
+ * eval.c (evaluate_subexp, case UNOP_IND): Deal with deferencing
+ things that are not pointers.
+
+ * valops.c (value_ind): Make dereferencing an int give a LONGEST.
+
+ * expprint.c (print_subexp): Add (int) cast in OP_LAST case.
+
+ * dbxread.c (read_array_type): Set lower and upper if adjustable.
+
+ * symtab.c (lookup_symbol): Don't abort if symbol found in psymtab
+ but not in symtab.
+
+Thu Aug 17 15:51:20 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * config.gdb: Changed "Makefile.c" to "Makefile.dist".
+
+Thu Aug 17 01:58:04 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu)
+
+ * sparc-opcode.h (or): Removed incorrect lose bit 0x08000000.
+ [many]: Changed many `lose' entries to have the 0x10 bit set, so
+ they don't think %l0 is %g0.
+
+Wed Aug 16 00:30:44 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * m-symmetry.h (STORE_STRUCT_RETURN): Also write reg 0.
+ (EXTRACT_RETURN_VALUE): Call symmetry_extract_return_value.
+ symmetry-dep.c (symmetry_extract_return_value): New fn.
+
+ * main.c (symbol_completion_function): Deal with changed
+ result_list from lookup_cmd_1 for ambiguous return.
+ command.c (lookup_cmd): Same.
+
+ * inflow.c [TIOCGETC]: Move #include "param.h" back before
+ system #includes. Change all #ifdef TIOCGETC to
+ #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+ m-i386-sysv3.2.h, m-i386gas-sysv3.2.h: Remove "#undef TIOCGETC"
+ and add "#define TIOCGETC_BROKEN".
+
+ * command.c (lookup_cmd_1): Give the correct result_list in the
+ case of an ambiguous return where there is a partial match
+ (e.g. "info a"). Add comment clarifying what is the correct
+ result_list.
+
+ * gdb.texinfo (GDB History): Document the two changes below.
+
+ * main.c (command_line_input): Make history expansion not
+ just occur at the beginning of a line.
+
+ * main.c (initialize_main): Make history expansion off by default.
+
+ * inflow.c: Move #include "param.h" after system #includes.
+
+ * i386-dep.c (i386_float_info): Use U_FPSTATE macro.
+
+ * m-i386-sysv3.2.h, m-i386gas-sysv3.2.h: New files.
+ Makefile.dist, config.gdb: Know about these new files.
+
+Tue Aug 15 21:36:11 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * symtab.c (lookup_struct_elt_type): Use type_print rather
+ than assuming type has a name.
+
+Tue Aug 15 02:25:43 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu)
+
+ * sparc-opcode.h (mov): Removed bogus "or i,0,d" pattern.
+
+ * sparc-opcode.h (mov, or): Fixed incorrect `lose' members.
+
+ * sparc-dep.c: Don't include "sparc-opcode.h".
+ (skip_prologue, isanulled): Declare special types to recognize
+ instructions, and use them.
+
+ * sparc-pinsn.c (print_insn): Sign-extend 13-bit immediate args.
+ If they are less than +9, print them in signed decimal instead
+ of unsigned hex.
+
+ * sparc-opcode.h, sparc-pinsn.c: Completely rewritten to share an
+ opcode table with gas, and thus produce disassembly that looks
+ like what the assembler accepts.
+
+Tue Aug 15 16:20:52 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * symtab.c (find_pc_psymbol): Move best_pc=psymtab->textlow-1
+ after test for psymtab null.
+
+ * main.c (editing_info): Remove variable retval.
+
+ * config.gdb (sun3, isi): Comment out obsolete message about telling
+ it whether you have an FPU (now that it detects it).
+
+ * config.gdb (sun3): Accept sun3os3.
+
+ * m68k-insn.h: Include <signal.h>.
+
+ * m68k-pinsn.h (convert_{to,from}_68881): Add have_fpu code
+
+ * m-newsos3.h: Undefine USE_PCB. That code didn't seem to work.
+
+ * sparc-dep.c: Put in insn_fmt and other stuff from the old
+ sparc-opcode.h.
+
+ * sparc-opcode.h, sparc-pinsn.c: Correct copyright notice.
+
+ * sparc-opcode.h, sparc-pinsn.c: Replace the old ones with the new
+ ones by roland.
+
+Tue Aug 15 02:25:43 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu)
+
+ * Makefile.dist: Don't define CC at all.
+
+ * Makefile.dist (Makefile): Remove tmp.c after preprocessing.
+ Use $(MD) instead of M_MAKEDEFINE in the cc command.
+
+ * Makefile.dist: Don't define RL_LIB as
+ "${READLINE}/libreadline.a", since READLINE is a list of files.
+
+Mon Aug 14 23:49:29 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * main.c (print_version): Change 1988 to 1989.
+
+ * main.c (copying_info, initialize_main): Remove #if 0'd code.
+
+Tue Aug 1 14:44:56 1989 Hikichi (hikichi at sran203)
+
+ * m-newsos3.h
+ (NO_SIGINTERRUPT): have SIGINTERRUPT on NEWS os 3.
+
+ * m-news.h(FRAME_FIND_SAVED_REGS): use the sun3's instead of old
+ one.
+
+Mon Aug 14 15:27:01 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * m-news.h, m-newsos3.h, news-dep.c: Merge additional changes
+ by Hikichi (ChangeLog entries above).
+
+ * Makefile.dist (READLINE): List readline files individually
+ so we don't accidently get random files from the readline
+ directory.
+
+ * m-news.h (STORE_RETURN_VALUE, EXTRACT_RETURN_VALUE):
+ Expect floating point returns to be in fp0.
+
+ * gdb.texinfo (Format options): New node.
+
+ * gdb.texinfo: Comment out "@include"s until bfox fixes the
+ readline & history docs.
+
+ * dbxread.c (read_addl_syms): Set startup_file_* if necessary at
+ the end (as well as when we hit ".o").
+
+ * printcmd.c (decode_format): Set val.format & val.size to '?' at
+ start and set defaults at end.
+
+ * symtab.c (decode_line_1): Check for class_name null.
+
+ * valops.c: Each place where it compares against field names,
+ check for null field names. (new t_field_name variables).
+
+ * utils.c (fputs_filtered): Check for linebuffer null before
+ checking whether to call fputs. Remove later check for linebuffer
+ null.
+
+Sun Aug 13 15:56:50 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * m-isi.h, m-sun3.h ({PUSH,POP}_FP_REGS): New macros.
+ m-sun3.h (NUM_REGS): Conditionalize on FPU.
+ config.gdb (sun3, isi): Add message about support for machines
+ without FPU.
+
+ * main.c (catch_termination, initialize_signals): new functions.
+
+ * main.c (editing_info): Add "info editing n" and "info editing +".
+ Rewrite much of this function.
+ gdb.texinfo (GDB Readline): Document it.
+
+ * values.c (history_info): Add "info history +". Also add code to
+ do "info history +" when command is repeated.
+ gdb.texinfo (Value History): Document "info history +".
+
+ * expprint.c (print_subexp): Add OP_THIS to case stmt.
+
+ * config.gdb (sun4os4): Put quotes around make define.
+
+ * config.gdb: Canonicalize machine name at beginning.
+
+Sat Aug 12 00:50:59 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * config.gdb: define M_MAKEDEFINE
+ Makefile (Makefile, MD): Be able to re-make Makefile.
+
+ * main.c (command_line_input): Add comments to
+ the command history.
+
+ * Makefile.dist (Makefile): Add /bin/false.
+
+Fri Aug 11 14:35:33 1989 Jim Kingdon (kingdon at spiff)
+
+ * Makefile.dist: Comment out .c.o rule and add TARGET_ARCH.
+
+ * m-altos.h: Include sys/page.h & sys/net.h
+
+ * m-altos.h (FRAME_CHAIN{,_VALID}): Use outside_startup_file.
+
+ * config.gdb (altos, altosgas): Add M_SYSV & M_BSD_NM and remove
+ M_ALLOCA=alloca.o from makedefine.
+
+ * coffread.c (complete_symtab): Change a_entry to entry.
+
+ * m-altosgas.h: New file.
+
+ * m-symmetry (REGISTER_BYTE): Fix dumb mistake.
+
+Fri Aug 11 06:39:49 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
+
+ * utils.c (set_screensize_command): Check for ARG being nil, since
+ that's what execute_command will pass if there's no argument.
+
+ * expread.y (yylex): Recognize "0x" or "0X" as the beginning of a
+ number.
+
+Thu Aug 10 15:43:12 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * config.gdb, Makefile.dist: Rename Makefile.c to Makefile.dist.
+
+ * m-altos.h: Add comment about porting to USGR2.
+
+ * config.gdb (sparc): Add -Usparc.
+
+Wed Aug 9 14:20:39 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * m-sun3os4.h: Define BROKEN_LARGE_ALLOCA.
+
+ * values.c (modify_field): Check for value too large to fit in
+ bitfield.
+
+ * utils.c (fputs_filtered): Allow LINEBUFFER to be NULL.
+
+ * breakpoint.c (condition_command): Check for attempt to specify
+ non-numeric breakpoint number.
+
+ * config.gdb, Makefile, m-altos.h, altos-dep.c: Merge Altos
+ port.
+
+ * README: Change message about editing Makefile.
+
+ * config.gdb: Edit Makefile.
+ Copied Makefile to Makefile.c and changed to let config.gdb
+ run us through the C preprocessor.
+
+ * expread.y (yylex): Test correctly for definition of number.
+
+Wed Aug 9 11:56:05 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Put bracketing of entry point in
+ test case for .o symbols so that it will be correct even without
+ debugging symbols.
+ (end_psymtab): Took bracketing out.
+
+ * blockframe.c (outside_startup_file): Reverse the sense of the
+ return value to make the functionality implied by the name
+ correct.
+
+Tue Aug 8 11:48:38 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * coffread.c (symbol_file_command): Do not assume presence of a.out
+ header.
+
+ * blockframe.c: Replace first_object_file_end with
+ startup_file_{start,end}
+ (outside_startup_file): New function.
+ dbxread.c (read_addl_syms, read_dbx_symtab, end_psymbol): set
+ startup_file_*. Delete first_object_file_end code.
+ Add entry_point and ENTRY_POINT
+ coffread.c (complete_symtab): Set startup_file_*.
+ (first_object_file_end): Add as static.
+ m-*.h (FRAME_CHAIN, FRAME_CHAIN_VALID): Call outside_startup_file
+ instead of comparing with first_object_file_end.
+
+ * breakpoint.c (breakpoint_1): Change -1 to (CORE_ADDR)-1.
+
+ * config.gdb (i386, i386gas): Add missing quotes at end of "echo"
+
+ * source.c (directory_command): Add dont_repeat ();
+
+Mon Aug 7 18:03:51 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * dbxread.c (read_addl_syms): Change strcmp to strncmp and put 3rd
+ arg back.
+
+ * command.h (struct cmd_list_element): Add comment clarifying
+ purpose of abbrev_flag.
+
+Mon Aug 7 12:51:03 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * printcmd.c (_initialize_printcmd): Changed "undisplay" not to
+ have abbrev flag set; it isn't an abbreviation of "delete
+ display", it's an alias.
+
+Mon Aug 7 00:25:15 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * symtab.c (lookup_symtab_1): Remove filematch (never used).
+
+ * expread.y [type]: Add second argument to 2 calls to
+ lookup_member_type which were missing them.
+
+ * dbxread.c (symbol_file_command): Add from_tty arg.
+ Check it before calling query.
+
+ * infcmd.c (tty_command): Add from_tty arg.
+
+ * eval.c (evaluate_subexp): Remove 3rd argument from
+ calls to value_x_unop.
+
+ * dbxread.c (read_addl_syms): Remove 3rd argument from
+ call to strcmp.
+
+ * gdb.texinfo (Command editing): @include inc-readline.texinfo
+ and inc-history.texinfo and reorganize GDB-specific stuff.
+
+ * Makefile: Add line MAKE=make.
+
+ * README (second paragraph): Fix trivial errors.
+
+ * dbxread.c (read_struct_type): Make sure p is initialized.
+
+ * main.c (symbol_completion_function): Complete correctly
+ on the empty string.
+
+Sun Aug 6 21:01:59 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * symmetry-dep.c: Remove "long" from definition of i386_follow_jump.
+
+ * gdb.texinfo (Backtrace): Document "where" and "info stack".
+
+ * dbxread.c (cleanup_undefined_types): Strip off "struct "
+ or "union " from type names before doing comparison
+
+Sat Aug 5 02:05:36 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * config.gdb (i386, i386gas): Improve makefile editing instructions.
+
+ * Makefile: Fix typo in CLIBS for SYSV.
+
+ * dbxread.c (read_dbx_symtab): Deal with N_GSYM typedefs.
+
+ * dbxread.c (add_file_command): Do not free name. We didn't
+ allocate it; it just points into arg_string.
+
+ * Makefile, m-*.h: Change LACK_VPRINTF to HAVE_VPRINTF.
+
+Fri Jul 28 00:07:48 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * valprint.c (val_print): Made sure that all returns returned a
+ value (usually 0, indicating no memory printed).
+
+ * core.c (read_memory): Changed "return" to "return 0".
+
+ * expread.y (parse_number): Handle scientific notation when the
+ string does not contain a '.'.
+
+Thu Jul 27 15:14:03 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * infrun.c (signals_info): Error if signal number passed is out of
+ bounds.
+
+ * defs.h: Define alloca to be __builtin_alloca if compiling with
+ gcc and localized inclusion of alloca.h on the sparc with the
+ other alloca stuff.
+ * command.c: Doesn't need to include alloca.h on the sparc; defs.h
+ does it for you.
+
+ * printcmd.c (print_frame_args): Changed test for call to
+ print_frame_nameless_args to check i to tell if any args had been
+ printed.
+
+Thu Jul 27 04:40:56 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
+
+ * blockframe.c (find_pc_partial_function): Always check that NAME
+ and/or ADDRESS are not nil before storing into them.
+
+Wed Jul 26 23:41:21 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
+
+ * m-newsos3.h: Define BROKEN_LARGE_ALLOCA.
+ * dbxread.c (symbol_file_command, psymtab_to_symtab):
+ Use xmalloc #ifdef BROKEN_LARGE_ALLOCA.
+
+Tue Jul 25 16:28:18 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu)
+
+ * m68k-opcode.h: moved some of the fmovem entries so they're
+ all consecutive. This way the assembler doesn't bomb.
+
+Mon Jul 24 22:45:54 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * symtab.c (lookup_symbol): Changed error to an informational (if
+ not very comforting) message about internal problems. This will
+ get a null symbol returned to decode_line_1, which should force
+ things to be looked up in the misc function vector.
+
+Wed Jul 19 13:47:34 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symtab.c (lookup_symbol): Changed "fatal" to "error" in
+ external symbol not found in symtab in which it was supposed to be
+ found. This can be reached because of a bug in ar.
+
+Tue Jul 18 22:57:43 1989 Randy Smith (roland at hobbes.ai.mit.edu)
+
+ * m-news.h [REGISTER_U_ADDR]: Decreased the assumed offset of fp0
+ by 4 to bring it into (apparently) appropriate alignment with
+ reality.
+
+Tue Jul 18 18:14:42 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * Makefile: pinsn.o should depend on opcode.h
+
+ * m68k-opcode.h: Moved fmovemx with register lists to before other
+ fmovemx.
+
+Tue Jul 18 11:21:42 1989 Jim Kingdon (kingdon at susie)
+
+ * Makefile, m*.h: Only #define vprintf (to _doprnt or printf,
+ depends on the system) if the library lacks it (controlled by
+ LACK_VPRINTF_DEFINE in makefile). Unpleasant, but necessary to
+ make this work with the GNU C library.
+
+Mon Jul 17 15:17:48 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * breakpoint.c (breakpoint_1): Change addr-b->address to
+ b->address-addr.
+
+Sun Jul 16 16:23:39 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * eval.c (evaluate_subexp): Change error message printed when
+ right operand of '@' is not an integer to English.
+
+ * infcmd.c (registers_info): Fix call to print_spaces_filtered
+ to specify right # of arguments.
+
+ * gdb.texinfo (Command Editing): Document info editing command.
+
+ * coffread.c (read_file_hdr): Add MC68MAGIC.
+
+ * source.c (select_source_symtab): Change MAX to max.
+
+Fri Jul 14 21:19:11 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * infcmd.c (registers_info): Clean up display to look good with long
+ register names, to say "register" instead of "reg", and to put the
+ "relative to selected stack frame" bit at the top.
+
+Fri Jul 14 18:23:09 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (record_misc_function): Put parens around | to force
+ correct evaluation.
+
+Wed Jul 12 12:25:53 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * m-newsos3, m-news, infrun.c, Makefile, config.gdb, news-dep.c:
+ Merge in Hikichi's changes for Sony/News-OS 3 support.
+
+Tue Jul 11 21:41:32 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * utils.c (fputs_filtered): Don't do any filtering if output is
+ not to stdout, or if stdout is not a tty.
+ (fprintf_filtered): Rely on fputs_filtered's check for whether to
+ do filtering.
+
+Tue Jul 11 00:33:58 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * GDB 3.2 Released.
+
+ * valprint.h: Deleted.
+
+ * utils.c (fputs_filtered): Don't do any filtering if filtering is
+ disabled (lines_per_page == 0).
+
+Mon Jul 10 22:27:53 1989 Randy Smith (roland at hobbes.ai.mit.edu)
+
+ * expread.y [typebase]: Added "unsigned long int" and "unsigned
+ short int" to specs.
+
+Mon Jul 10 21:44:55 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * main.c (main): Make -cd use cd_command to avoid
+ current_directory with non-absolute pathname.
+
+Mon Jul 10 00:34:29 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (symbol_file_command): Catch errors from stat (even
+ though they should never happen).
+
+ * source.c (openp): If the path is null, use the current
+ directory.
+
+ * dbxread.c (read_dbx_symtab): Put N_SETV symbols into the misc
+ function vector ...
+ (record_misc_function): ... as data symbols.
+
+ * utils.c (fprintf_filtered): Return after printing if we aren't
+ going to do filtering.
+
+ * Makefile: Added several things for make clean to take care of.
+
+ * expread.y: Lowered "@" in precedence below +,-,*,/,%.
+
+ * eval.c (evaluate_subexp): Return an error if the rhs of "@"
+ isn't integral.
+
+ * Makefile: Added removal of core and gdb[0-9] files to clean
+ target.
+
+ * Makefile: Made a new target "distclean", which cleans things up
+ correctly for making a distribution.
+
+Sun Jul 9 23:21:27 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * dbxread.c: Surrounded define of gnu symbols with an #ifndef
+ NO_GNU_STABS in case you don't want them on some machines.
+ * m-npl.h, m-pn.h: Defined NO_GNU_STABS.
+
+Sun Jul 9 19:25:22 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * utils.c (fputs_filtered): New function.
+ (fprintf_filtered): Use fputs_filtered.
+ utils.c (print_spaces_filtered),
+ command.c (help_cmd,help_cmd_list),
+ printcmd.c (print_frame_args),
+ stack.c (print_block_frame_locals, print_frame_arg_vars),
+ valprint.c (many functions): Use fputs_filtered instead of
+ fprintf_filtered to avoid arbitrary limit.
+
+ * utils.c (fprintf_filtered): Fix incorrect comment.
+
+Sat Jul 8 18:12:01 1989 Randy Smith (randy at hobbes.ai.mit.edu)
+
+ * valprint.c (val_print): Changed assignment of pretty to use
+ prettyprint as a conditional rather than rely on values of the
+ enum.
+
+ * Projects: Cleaned up a little for release.
+
+ * main.c (initialize_main): Initialize
+ rl_completion_entry_function instead of completion_entry_function.
+
+ * Makefile: Modified to use the new readline library setup.
+
+ * breakpoint.c (break_command_1, delete_breakpoint,
+ enable_breakpoint, disable_breakpoint): Put in new printouts for
+ xgdb usage triggered off of xgdb_verbose.
+ * main.c (main): Added check for flag to set xgdb_verbose.
+ * stack.c (frame_command): Set frame_changed when frame command
+ used.
+
+Fri Jul 7 16:20:58 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * Remove valprint.h and move contents to value.h (more logical).
+
+Fri Jul 7 02:28:06 1989 Randall Smith (randy at rice-chex)
+
+ * m68k-pinsn.c (print_insn): Included a check for register list;
+ if there is one, make sure to start p after it.
+
+ * breakpoint.c (break_command_1, delete_breakpoint,
+ enable_breakpoint, disable_breakpoint): #ifdef'd out changes
+ below; they produce unwanted output in gdb mode in gnu-emacs.
+
+ * gdb.texinfo: Spelled. Also removed index references from
+ command editing section; the relevance/volume ratio was too low.
+ Removed all references to the function index.
+
+ * ns32k-opcode.h, ns32k-pinsn.c: Backed out changes of June 24th;
+ haven't yet received legal papers.
+
+ * .gdbinit: Included message telling the user what it is doing.
+
+ * symmetry-dep.c: Added static decls for i386_get_frame_setup,
+ i386_follow_jump.
+ * values.c (unpack_double): Added a return (double)0 at the end to
+ silence a compiler warning.
+
+ * printcmd.c (containing_function_bounds, asdump_command): Created
+ to dump the assembly code of a function (support for xgdb and a
+ useful hack).
+ (_initialize_printcmd): Added this to command list.
+ * gdb.texinfo [Memory]: Added documentation for the asdump
+ command.
+ * breakpoint.c (break_command_1, delete_breakpoint,
+ enable_breakpoint, disable_breakpoint): Added extra verbosity for
+ xgdb conditionalized on the new external frame_full_file_name.
+ * source.c (identify_source_line): Increase verbosity of fullname
+ prointout to include pc value.
+ * stack.c: Added a new variable; "frame_changed" to indicate when
+ a frame has been changed so that gdb can print out a frame change
+ message when the frame only changes implicitly.
+ (print_frame_info): Check the new variable in determining when to
+ print out a new message and set it to zero when done.
+ (up_command): Increment it.
+ (down_command): Decrement it.
+
+ * m68k-pinsn.c (print_insn_arg [lL]): Modified cases for register
+ lists to reset the point to point to after the word from which the
+ list is grabbed *if* that would cause point to point farther than
+ it currently is.
+
+Thu Jul 6 14:28:11 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * valprint.c (val_print, value_print): Add parameter to control
+ prettyprinting.
+ valprint.h: New file containing constants used for passing
+ prettyprinting parameter to val{,ue}_print.
+ expprint.c, infcmd.c, printcmd.c, valprint.c, values.c:
+ Change all calls to val{,ue}_print to use new parameter.
+
+Mon Jul 3 22:38:11 1989 Randy Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (,process_one_symbol): Moved extern declaration for
+ index out of function to beginning of file.
+
+Mon Jul 3 18:40:14 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
+
+ * gdb.texinfo (Registers): Add "ps" to list of standard registers.
+
+Sun Jul 2 23:13:03 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * printcmd.c (enable_display): Change d->next to d = d->next so
+ that "enable display" without args works.
+
+Fri Jun 30 23:42:04 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * source.c (list_command): Made error message given when no
+ symtab is loaded clearer.
+
+ * valops.c (value_assign): Make it so that when assigning to an
+ internal variable, the type of the assignment exp is the type of
+ the value being assigned.
+
+Fri Jun 30 12:12:43 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c (verbose_info): Created.
+ (initialize_main): Put "info verbose" into command list.
+
+ * utils.c (screensize_info): Created.
+ (_initialize_utils): Defined "info screensize" as a normal command.
+
+ * valprint.c (format_info): Added information about maximum number
+ of array elements to function.
+
+ * blockframe.c (find_pc_partial_function): Again.
+
+ * blockframe.c (find_pc_partial_function): Replaced a "shouldn't
+ happen" (which does) with a zero return.
+
+ * main.c (dont_repeat): Moved ahead of first use.
+
+Thu Jun 29 19:15:08 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * vax-opcode.h: Made minor modifications (moved an instruction and
+ removed a typo) to bring this into accord with gas' table; also
+ changed copyright to reflect it being part of both gdb and gas.
+
+ * m68k-opcode.h: Added whole scads and bunches of new stuff for
+ the m68851 and changed the coptyrightto recognize that the file
+ was shared between gdb and gas.
+
+ * main.c (stop_sig): Use "dont_repeat ()" instead of *line = 0;
+
+ * core.c (read_memory): Don't do anything if length is 0.
+
+ * Makefile: Added readline.c to the list of files screwed by
+ having the ansi ioctl.h compilation with gcc.
+
+ * config.gdb: Added sun4os3 & sun4-os3 as availible options.
+
+Wed Jun 28 02:01:26 1989 Jim Kingdon (kingdon at apple-gunkies.ai.mit.edu)
+
+ * command.c (lookup_cmd): Add ignore_help_classes argument.
+ (lookup_cmd_1): Add ignore_help_classes argument.
+ command.c, main.c: Change callers of lookup_cmd{,_1} to supply
+ value for ignore_help_classes.
+
+Tue Jun 27 18:01:31 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * utils.c (print_spaces_filtered): Made more efficient.
+ * defs.h: Declaration.
+ * valprint.c (val_print): Used in a couple of new places.
+
+Mon Jun 26 18:27:28 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * m68k-pinsn.c (print_insn_arg ['#', '^']): Combined them into one
+ case which always gets the argument from the word immediately
+ following the instruction.
+ (print_insn_arg ["[lL]w"]): Make sure to always get the register
+ mask from the word immediately following the instruction.
+
+Sun Jun 25 19:14:56 1989 Randall Smith (randy at galapas.ai.mit.edu)
+
+ * Makefile: Added hp-include back in as something to distribute.
+
+ * stack.c (print_block_frame_locals): Return value changed from
+ void to int; return 1 if values printed. Use _filtered.
+ (print_frame_local_vars): Use return value from
+ print_block_frame_locals to mention if nothing printed; mention
+ lack of symbol table, use _filtered.
+ (print_frame_arg_vars): Tell the user if no symbol table
+ or no values printed. Use fprintf_filtered instead of fprintf.
+ * blockframe.c (get_prev_frame_info): Check for no inferior or
+ core file before crashing.
+
+ * inflow.c (inferior_died): Set current frame to zero to keep from
+ looking like we're in start.
+
+Sat Jun 24 15:50:53 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * stack.c (frame_command): Added a check to make sure that there
+ was an inferior or a core file.
+
+ * expread.y (yylex): Allow floating point numbers of the form ".5"
+ to be parsed.
+
+ Changes by David Taylor at TMC:
+ * ns32k-pinsn.c: Added define for ?floating point coprocessor? and
+ tables for register names to be used for each of the possibilities.
+ (list_search): Created; searches a list of options for a specific
+ value.
+ (print_insn_arg): Added 'Q', 'b', 'M', 'P', 'g', and 'G' options
+ to the value location switch.
+ * ns32k-opcode.h: Added several new location flags.
+ [addr, enter, exit, ext[bwd], exts[bwd], lmr, lpr[bwd], restore,
+ rett, spr[bwd], smr]: Improved insn format output.
+
+ * symtab.c (list_symbols): Rearrange printing to produce readable
+ output for "info types".
+
+ * eval.c (evaluate_subexp_for_address): Fixed typo.
+
+ * dbxread.c (read_type): Don't output an error message when
+ there isn't a ',' after a cross-reference.
+
+ * dbxread.c (read_dbx_symtab): #if'd out N_FN case in
+ read_dbx_symtab if it has the EXT bit set (otherwise multiple
+ cases with the same value).
+
+Fri Jun 23 13:12:08 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * symmisc.c: Changed decl of print_spaces from static to extern
+ (since it's defined in utils.c).
+
+ * remote.c (remote_open): Close remote_desc if it's already been
+ opened.
+
+ * Remote_Makefile, remote_gutils.c, remote_inflow.c,
+ remote_server.c, remote_utils.c: Combined into remote-multi.shar.
+ * remote-multi.shar: Created (Vikram Koka's remote stub).
+ * remote-sa.m68k.shar: Created (Glenn Engel's remcom.c).
+ * README: Updated to reflect new organization of remote stubs.
+
+ * dbxread.c (read_dbx_symtab): Put an N_FN in with N_FN | N_EXT to
+ account for those machines which don't use the external bit here.
+ Sigh.
+
+ * m-symmetry.h: Defined NO_SIGINTERRUPT.
+
+Thu Jun 22 12:51:37 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * printcmd.c (decode_format): Make sure characters are printed
+ using a byte size.
+
+ * utils.c (error): Added a terminal_ours here.
+
+ * stack.c (locals_info): Added check for selected frame.
+
+ * dbxread.c (read_type): Checked to make sure that a "," was
+ actually found in the symbol to end a cross reference.
+
+Wed Jun 21 10:30:01 1989 Randy Smith (randy at tartarus.uchicago.edu)
+
+ * expread.y (parse_number, [exp]): Allowed for the return of a
+ number marked as unsigned; this will allow inclusion of unsigned
+ constants.
+
+ * symtab.h: Put in default definitions for BUILTIN_TYPE_LONGEST
+ and BUILTIN_TYPE_UNSIGNED_LONGEST.
+
+ * expread.y (parse_number): Will now accept integers suffixed with
+ a 'u' (though does nothing special with it).
+
+ * valarith.c (value_binop): Added cases to deal with unsigned
+ arithmetic correctly.
+
+Tue Jun 20 14:25:54 1989 Randy Smith (randy at tartarus.uchicago.edu)
+
+ * dbxread.c (psymtab_to_symtab_1): Changed reading in info message
+ to go through printf_filtered.
+
+ * symtab.c (list_symbols): Placed header message after all calls
+ to psymtab_to_symtab.
+
+ * symtab.c (smash_to_{function, reference, pointer}_type): Carried
+ attribute of permanence for the type being smashed over the bzero
+ and allowed any type to point at this one if it is permanent.
+
+ * symtab.c (smash_to_{function, reference, pointer}_type): Fix
+ typo: check flags of to_type instead of type.
+
+ * m-hp9k320.h: Changed check on __GNU__ predefine to __GNUC__.
+
+ * Makefile: Made MUNCH_DEFINE seperate and based on SYSV_DEFINE;
+ they aren't the same on hp's.
+
+Mon Jun 19 17:10:16 1989 Randy Smith (randy at tartarus.uchicago.edu)
+
+ * Makefile: Fixed typo.
+
+ * valops.c (call_function): Error if the inferior has not been
+ started.
+
+ * ns32k-opcode.h [check[wc], cmpm[bwd], movm[bwd], skpsb]: Fixed
+ typos.
+
+Fri Jun 9 16:23:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-news.h [NO_SIGINTERRUPT]: Defined.
+
+ * dbxread.c (read_type): Start copy of undefined structure name
+ past [sue] defining type of cross ref.
+
+ * dbxread.c (process_one_symbol): Changed strchr to index.
+
+ * ns32k-opcode.h, ns32k-pinsn.c: More changes to number of
+ operands, addition of all of the set condition opcodes, addition
+ of several flag letters, all patterned after the gas code.
+
+ * ns32k-opcode.h [mov{su,us}[bwd], or[bwd]]: Changed number of
+ operands from 1 to 2.
+
+Wed Jun 7 15:04:24 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symseg.h [TYPE_FLAG_STUB]: Created.
+ * dbxread.c (read_type): Set flag bit if type is stub.
+ (cleanup_undefined_types): Don't mark it as a stub if it's been
+ defined since we first learned about it.
+ * valprint.c (val_print): Print out a message to that effect if
+ this type is encountered.
+
+ * symseg.h, symtab.h: Moved the definition of TYPE_FLAG_PERM over
+ to symseg.h so that all such definitions would be in the same place.
+
+ * valprint.c (val_print): Print out <No data fields> for a
+ structure if there aren't any.
+
+ * dbxread.c (read_type): Set type name of a cross reference type
+ to "struct whatever" or something.
+
+Tue Jun 6 19:40:52 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * breakpoint.c (breakpoint_1): Print out symbolic location of
+ breakpoints for which there are no debugging symbols.
+
+Mon Jun 5 15:14:51 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * command.c (help_cmd_list): Made line_size static.
+
+Sat Jun 3 17:33:45 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * Makefile: Don't include the binutils hp-include directory in the
+ distribution anymore; refer the users to the binutils distribution.
+
+Thu Jun 1 16:33:07 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * printcmd.c (disable_display_command): Fixed loop iteration for
+ no arg case.
+
+ * printcmd.c (disable_display_command): Added from_tty parameter
+ to function.
+
+ * valops.c (value_of_variable): Call read_var_value with 0 cast to
+ FRAME instead of CORE_ADDR.
+
+ * eval.c (evaluate_subexp): Corrected number of args passed to
+ value_subscript (to 2).
+
+ * infrun.c (wait_for_inferior), symtab.c (decode_line_1),
+ m-convex.h: Changed name of FIRSTLINE_DEBUG_BROKEN to
+ PROLOGUE_FIRSTLINE_OVERLAP.
+
+ * m-merlin.h: Fixed typo.
+ * ns32k-opcode.h: Added ns32381 opcodes and "cinv" insn, and fixed
+ errors in movm[wd], rett, and sfsr.
+
+ * eval.c (evaluate_subexp, evaluate_subexp_for_address), valops.c
+ (value_zero): Change value_zero over to taking two arguments
+ instead of three.
+
+ * eval.c (evaluate_subexp)
+ [OP_VAR_VALUE]: Get correct lval type for AVOID_SIDE_EFFECTS for
+ all types of symbols.
+ [BINOP_DIV]: Don't divide if avoiding side effects; just return
+ an object of the correct type.
+ [BINOP_REPEAT]: Don't call value_repeat, just allocate a
+ repeated value.
+ (evaluete_subexp_for_address) [OP_VAR_VALUE]: Just return a thing
+ of the right type (after checking to make sure that we are allowed
+ to take the address of whatever variable has been passed).
+
+Mon May 29 11:01:02 1989 Randall Smith (randy at galapas.ai.mit.edu)
+
+ * breakpoint.c (until_break_command): Set the breakpoint with a
+ frame specification so that it won't trip in inferior calls to the
+ function. Also set things up so that it works based on selected
+ frame, not current one.
+
+Sun May 28 15:05:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * eval.c (evalue_subexp): Change subscript case to use value_zero
+ in EVAL_AVOID_SIDE_EFFECTS case.
+
+Fri May 26 12:03:56 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_addl_syms, psymtab_to_symtab): Removed
+ cleanup_undefined_types; this needs to be done on a symtab basis.
+ (end_symtab): Called cleanup_undefined_types from here.
+ (cleanup_undefined_types): No longer uses lookup_symbol (brain
+ dead idea; oh, well), now it searches through file_symbols.
+
+Wed May 24 15:52:43 1989 Randall Smith (randy at galapas)
+
+ * source.c (select_source_symtab): Only run through
+ partial_symtab_list if it exists.
+
+ * coffread.c (read_coff_symtab): Don't unrecord a misc function
+ when a function symbol is seen for it.
+
+ * expread.y [variable]: Make sure to write a type for memvals if
+ you don't get a mft you recognize.
+
+Tue May 23 12:15:57 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * dbxread.c (read_ofile_symtab, psymtab_to_symtab): Moved cleanup
+ of undefined types to psymtab_to_symtab. That way it will be
+ called once for all readins (which will, among other things,
+ help reduce infinite loops).
+
+ * symtab.h [misc_function_type]: Forced mf_unknown to 0.
+ * dbxread.c (record_misc_function): Cast enum to unsigned char (to
+ fit).
+ * expread.y [variable]: Cast unsigned char back to enum to test.
+
+Mon May 22 13:08:25 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ Patches by John Gilmore for dealing well with floating point:
+ * findvar.c (value_from_register, locate_var_value): Used
+ BYTES_BIG_ENDIAN instead of an inline test.
+ * m-sparc.h [IEEE_FLOAT]: Created to indicate that the sparc is
+ IEEE compatible.
+ * printcmd.c (print_scalar_formatted): Use BYTES_BIG_ENDIAN and
+ the stream argument for printing; also modify default type for
+ 'f'. Change handling of invalid floats; changed call syntax for
+ is_nan.
+ (print_command): Don't print out anything indicating that
+ something was recorded on the history list if it wasn't.
+ * valprint.c (val_print): Fixed to deal properley with new format
+ of is_nan and unpacking doubles without errors occuring.
+ (is_nan): Changed argument list and how it figures big endianness
+ (uses macros).
+ * values.c (record_latest_value): Return -1 and don't record if
+ it's an invalid float.
+ (value_as_double): Changed to use new unpack_double calling
+ convention.
+ (unpack_double): Changed not to call error if the float was
+ invalid; simply to set invp and return. Changed calling syntax.
+ (unpack_field_as_long, modify_field): Changed to use
+ BITS_BIG_ENDIAN to determine correct action.
+
+ * m-hp9k320.h [HP_OS_BUG]: Created; deals with problem where a
+ trap happens after a continue.
+ * infrun.c (wait_for_inferior): Used.
+
+ * m-convex.h [FIRSTLINE_DEBUG_BROKEN]: Defined a flag to indicate
+ that the debugging symbols output by the compiler for the first
+ line of a function were broken.
+ * infrun.c (wait_for_inferior), symtab.c (decode_line_1): Used.
+
+ * gdb.texinfo [Data, Memory]: Minor cleanups of phrasing.
+
+Fri May 19 00:16:59 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (add_undefined_type, cleanup_undefined_types): Created
+ to keep a list of cross references to as yet undefined types.
+ (read_type): Call add_undefined_type when we run into such a case.
+ (read_addl_syms, read_ofile_symtab): Call cleanup_undefined_types
+ when we're done.
+
+ * dbxread.c (psymtab_to_symtab, psymtab_to_symtab_1): Broke
+ psymtab_to_symtab out into two routines; made sure the string
+ table was only readin once and the globals were only scanned once,
+ for any number of dependencies.
+
+Thu May 18 19:59:18 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-*.h: Defined (or not, as appropriate per machine)
+ BITS_BIG_ENDIAN, BYTES_BIG_ENDIAN, and WORDS_BIG_ENDIAN.
+
+Wed May 17 13:37:45 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c (symbol_completion_function): Always complete on result
+ command list, even if exact match found. If it's really an exact
+ match, it'll find it again; if there's something longer than it,
+ it'll get the right result.
+
+ * symtab.c (make_symbol_completion_function): Fixed typo; strcmp
+ ==> strncmp.
+
+ * dbxread.c (read_dbx_symtab): Change 'G' case to mark symbols as
+ LOC_EXTERNAL.
+
+ * expread.y [variables]: Changed default type of text symbols to
+ function returning int so that one can use, eg. strcmp.
+
+ * infrun.c (wait_for_inferior): Include a special flag indicating
+ that one shouldn't insert the breakpoints on the next step for
+ returning from a sigtramp and forcing at least one move forward.
+
+ * infrun.c (wait_for_inferior): Change test for nexting into a
+ function to check for current stack pointer inner than previous
+ stack pointer.
+
+ * infrun.c (wait_for_inferior): Check for step resume break
+ address before dealing with normal breakpoints.
+
+ * infrun.c (wait_for_inferior): Added a case to deal with taking
+ and passing along a signal when single stepping past breakpoints
+ before inserting breakpoints.
+
+ * infrun.c (wait_for_inferior): Inserted special case to keep
+ going after taking a signal we are supposed to be taking.
+
+Tue May 16 12:49:55 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * inflow.c (terminal_ours_1): Cast result of signal to (int
+ (*)()).
+
+ * gdb.texinfo: Made sure that references to the program were in
+ upper case. Modify description of the "set prompt" command.
+ [Running]: Cleaned up introduction.
+ [Attach]: Cleaned up.
+ [Stepping]: Change "Proceed" to "Continue running" or "Execute".
+ Minor cleanup.
+ [Source Path]: Cleaned up intro. Cleared up distinction between
+ the executable search path and the source path. Restated effect
+ of the "directory" command with no arguments.
+ [Data]: Fixed typos and trivial details.
+ [Stepping]: Fixed up explanation of "until".
+
+ * source.c (print_source_lines): Print through filter.
+
+ * printcmd.c (x_command): If the format with which to print is
+ "i", use the address of anything that isn't a pointer instead of
+ the value. This is for, eg. "x/10i main".
+
+ * gdb.texinfo: Updated last modification date on manual.
+
+Mon May 15 12:11:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symtab.c (lookup_symtab): Fixed typo (name ==> copy) in call to
+ lookup_symtab_1.
+
+ * gdb.texinfo: Added documentation for "break [+-]n" and for new
+ actions of "directory" command (taking multiple directory names at
+ the same time).
+
+ * m68k-opcode.h: Replaced the version in gdb with an up-to-date
+ version from the assembler directory.
+ * m68k-pinsn.c (print_insn_arg): Added cases 'l' & 'L' to switch
+ to print register lists for movem instructions.
+
+ * dbxread.c, m-convex.h: Moved convex dependent include files over
+ from dbxread.c to m-convex.h.
+
+ * printcmd.c (disable_display, disable_display_command): Changed
+ name of first to second, and created first which takes an int as
+ arg rather than a char pointer. Changed second to use first.
+ (_initialize_printcmd): Changed to use second as command to call.
+ (delete_current_display, disable_current_display): Changed name of
+ first to second, and changed functionality to match.
+ * infrun.c (normal_stop), main.c (return_to_top_level): Changed to
+ call disable_current_display.
+
+ * dbxread.c (process_one_symbol, read_dbx_symtab): Changed N_FN to
+ be N_FN | N_EXT to deal with new Berkeley define; this works with
+ either the old or the new.
+
+ * Remote_Makefile, remote_gutils.c, remote_inflow.c,
+ remote_server.c, remote_utils.c: Created.
+ * Makefile: Included in tag and tar files.
+ * README: Included a note about them.
+
+ * printcmd.c (print_address): Use find_pc_partial_function to
+ remove need to readin symtabs for symbolic addresses.
+
+ * source.c (directory_command): Replaced function with new one
+ that can accept lists of directories seperated by spaces or :'s.
+
+ * inflow.c (new_tty): Replaced calls to dup2 with calls to dup.
+
+Sun May 14 12:33:16 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * stack.c (args_info): Make sure that you have an inferior or core
+ file before taking action.
+
+ * ns32k-opcode.h [deiw, deid]: Fixed machine code values for these
+ opcodes.
+
+ * dbxread.c (scan_file_globals): Modified to use misc function
+ vector instead of file itself. Killed all arguments to the
+ funciton; no longer needed.
+ (psymtab_to_symtab): Changed call for above to reflect new (void)
+ argument list.
+
+ * dbxread.c (read_dbx_symtab, ): Moved HASH_OFFSET define out of
+ read_dbx_symtab.
+
+ * expread.y [variable]: Changed default type of misc function in
+ text space to be (void ()).
+
+ * Makefile: Modified for proper number of s/r conflicts (order is
+ confusing; the mod that necessitated this change was on May 12th,
+ not today).
+
+ * expread.y (yylex): Added SIGNED, LONG, SHORT, and INT keywords.
+ [typename]: Created.
+ [typebase]: Added rules for LONG, LONG INT, SHORT, SHORT INT,
+ SIGNED name, and UNSIGNED name (a good approximation of ansi
+ standard).
+
+ * Makefile: Included .c.o rule to avoid sun's make from throwing
+ any curves at us.
+
+ * blockframe.c: Included <obstack.h>
+
+ * command.c (lookup_cmd): Clear out trailing whitespace.
+
+ * command.c (lookup_cmd_1): Changed malloc to alloca.
+
+Fri May 12 12:13:12 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * printcmd.c (print_frame_args): Only print nameless args when you
+ know how many args there are supposed to be and when you've
+ printed fewer than them. Don't print nameless args between
+ printed args.
+
+ * symtab.c (make_symbol_completion_function): Fixed typo (= ==>
+ ==).
+
+ * remote.c (remote_open): ifdef'd out siginterrupt call by #ifndef
+ NO_SIGINTERRUPT.
+ * m-umax.h: Defined NO_SIGINTERRUPT.
+
+ * expread.y [ptype, array_mod, func_mod, direct_abs_decl,
+ abs_decl]: Added rules for parsing and creating arbitrarily
+ strange types for casts and sizeofs.
+
+ * symtab.c, symtab.h (create_array_type): Created. Some minor
+ misfeatures; see comments for details (main one being that you
+ might end up creating two arrays when you only needed one).
+
+Thu May 11 13:11:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * valops.c (value_zero): Add an argument for type of lval.
+ * eval.c (evaluate_subexp_for_address): Take address properly in
+ the avoid side affects case (ie. keep track of whether we have an
+ lval in memory and we can take the address).
+ (evaluate_subexp): Set the lval type of expressions created with
+ value_zero properley.
+
+ * valops.c, value.h (value_zero): Created--will return a value of
+ any type with contents filled with zero.
+ * symtab.c, symtab.h (lookup_struct_elt_type): Created.
+ * eval.c (evaluate_subexp): Modified to not read memory when
+ called with EVAL_AVOID_SIDE_EFFECTS.
+
+ * Makefile: Moved dbxread.c ahead of coffread.c in the list of
+ source files.
+
+Wed May 10 11:29:19 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * munch: Make sure that sysv version substitutes for the whole
+ line.
+
+ * symtab.h: Created an enum misc_function_type to hold the type of
+ the misc function being recorded.
+ * dbxread.c (record_misc_function): Branched on dbx symbols to
+ decide which type to assign to a misc function.
+ * coffread.c (record_misc_function): Always assign type unknown.
+ * expread.y [variable]: Now tests based on new values.
+
+Tue May 9 13:03:54 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symtab.c: Changed inclusion of <strings.h> (doesn't work on
+ SYSV) to declaration of index.
+
+ * Makefile: Changed last couple of READLINE_FLAGS SYSV_DEFINE
+
+ * source.c ({forward, reverse}_search_command): Made a default
+ search file similar to for the list command.
+
+Mon May 8 18:07:51 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * printcmd.c (print_frame_args): If we don't know how many
+ arguments there are to this function, don't print the nameless
+ arguments. We don't know enough to find them.
+
+ * printcmd.c (print_frame_args): Call print_frame_nameless_args
+ with proper arguments (start & end as offsets from addr).
+
+ * dbxread.c (read_addl_syms): Removed cases to deal with global
+ symbols; this should all be done in scan_global_symbols.
+
+Sun May 7 11:36:23 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * Makefile: Added copying.awk to ${OTHERS}.
+
+Fri May 5 16:49:01 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * valprint.c (type_print_varspec_prefix): Don't pass
+ passed_a_pointer onto children.
+
+ * valprint.c (type_print_varspec_suffix): Print "array of" with
+ whatever the "of" is after tha array brackets.
+
+ * valprint.c (type_print_varspec_{prefix,suffix}): Arrange to
+ parenthesisze pointers to arrays as well as pointers to other
+ objects.
+
+ * valprint.c (type_print_varspec_suffix): Make sure to print
+ subscripts of multi-dimensional arrays in the right order.
+
+ * infcmd.c (run_command): Fixed improper usages of variables
+ within remote debugging branch.
+
+ * Makefile: Added Convex.notes to the list of extra files to carry
+ around.
+
+ * dbxread.c (symbol_file_command): Made use of alloca or malloc
+ dependent on macro define.
+
+Thu May 4 15:47:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * Makefile: Changed READLINE_FLAGS to SYSV_DEFINE and called munch
+ with it also.
+ * munch: Check first argument for -DSYSV and be looser about
+ picking up init routines if you find it.
+
+ * coffread.c: Made fclose be of type int.
+
+ * breakpoint.c (_initialize_breakpoint): Put "unset" into class
+ alias.
+
+Wed May 3 14:09:12 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h [STACK_END_ADDR]: Parameterized off of
+ machine/vmparam.h (as per John Gilmore's suggestion).
+
+ * blockframe.c (get_prev_frame_info): Changed this function back
+ to checking frameless invocation first before checking frame
+ chain. This means that a backtrace up from start will produce the
+ wrong value, but that a backtrace from a frameless function called
+ in main will show up correctly.
+
+ * breakpoint.c (_initialize_breakpoint): Added entry in help for
+ delete that indicates that unset is an alias for it.
+
+ * main.c (symbol_completion_function): Modified recognition of
+ being within a single command.
+
+Tue May 2 15:13:45 1989 Randy Smith (randy at gnu)
+
+ * expread.y [variable]: Add some parens to get checking of the
+ misc function vector right.
+
+Mon May 1 13:07:03 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * default-dep.c (core_file_command): Made reg_offset unsigned.
+
+ * default-dep.c (core_file_command): Improved error messages for
+ reading in registers.
+
+ * expread.y: Allowed a BLOCKNAME to be ok for a variable name (as
+ per C syntax).
+
+ * dbxread.c (psymtab_to_symtab): Flushed stdout after printing
+ starting message about reading in symbols.
+
+ * printcmd.c (print_frame_args): Switched starting place for
+ printing of frameless args to be sizeof int above last real arg
+ printed.
+
+ * printcmd.c (print_frame_args): Modified final call to
+ print_nameless_args to not use frame slots used array if none had
+ been used.
+
+ * infrun.c (wait_for_inferior): Take FUNCTION_START_OFFSET into
+ account when dealing with comparison of pc values to function
+ addresses.
+
+ * Makefile: Added note about compiling gdb on a Vax running 4.3.
+
+Sun Apr 30 12:59:46 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * command.c (lookup_cmd): Got correct error message on bad
+ command.
+
+ * m-sun3.h [ABOUT_TO_RETURN]: Modified to allow any of the return
+ instructions, including trapv and return from interupt.
+
+ * command.c (lookup_cmd): If a command is found, use it's values
+ for error reporting and determination of needed subcommands.
+
+ * command.c (lookup_cmd): Use null string for error if cmdtype is
+ null; pass *line to error instead of **.
+
+ * command.c (lookup_cmd_1): End of command marked by anything but
+ alpha numeric or '-'. Included ctype.h.
+
+Fri Apr 28 18:30:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * source.c (select_source_symtab): Kept line number from ever
+ being less than 1 in main decode.
+
+Wed Apr 26 13:03:20 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * default-dep.c (core_file_command): Fixed typo.
+
+ * utils.c (fprintf_filtered): Don't use return value from
+ numchars.
+
+ * main.c, command.c (complete_on_cmdlist): Moved function to
+ command.c.
+
+ * command.c (lookup_cmd): Modified to use my new routine. Old
+ version is still there, ifdef'd out.
+
+ * command.c, command.h (lookup_cmd_1): Added a routine to do all
+ of the work of lookup_cmd with no error reporting and full return
+ of information garnered in search.
+
+Tue Apr 25 12:37:54 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * breakpoint.c (_initialize_breakpoint): Change "delete
+ breakpionts" to be in class alias and not have the abbrev flag
+ set.
+
+ * main.c (symbol_completion_function): Fix to correctly complete
+ things that correspond to multiword aliases.
+
+ * main.c (complete_on_cmdlist): Don't complete on something if it
+ isn't a command or prefix (ie. if it's just a help topic).
+
+ * main.c (symbol_completion_function): Set list index to be 0 if
+ creating a list with just one element.
+
+ * main.c (complete_on_cmdlist): Don't allow things with
+ abbrev_flag set to be completion values.
+ (symbol_completion_function): Don't accept an exact match if the
+ abbrev flag is set.
+
+ * dbxread.c (read_type): Fixed typo in comparision to check if
+ type number existed.
+
+ * dbxread.c (read_type): Made sure to only call dbx_lookup_type on
+ typenums if typenums were not -1.
+
+Mon Apr 24 17:52:12 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symtab.c: Added strings.h as an include file.
+
+Fri Apr 21 15:28:38 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symtab.c (lookup_partial_symtab): Changed to only return a match
+ if the name match is exact (which is what I want in all cases in
+ which this is currently used.
+
+Thu Apr 20 11:12:34 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * m-isi.h [REGISTER_U_ADDR]: Installed new version from net.
+ * default-dep.c: Deleted inclusion of fcntl.h; apparently not
+ necessary.
+ * Makefile: Added comment about compiling on isi under 4.3.
+
+ * breakpoint.c (break_command_1): Only give decode_line_1 the
+ default_breakpoint_defaults if there's nothing better (ie. make
+ the default be off of the current_source notes if at all
+ possible).
+
+ * blockframe.c (get_prev_frame_info): Clean up comments and
+ delete code ifdefed out around FRAMELESS_FUNCTION_INVOCATION test.
+
+ * remote.c: Added a "?" message to protocol.
+ (remote_open): Used at startup.
+ (putpkt): Read whatever garbage comes over the line until we see a
+ '+' (ie. don't treat garbage as a timeout).
+
+ * valops.c (call_function): Eliminated no longer appropriate
+ comment.
+
+ * infrun.c (wait_for_inferior): Changed several convex conditional
+ compilations to be conditional on CANNOT_EXECUTE_STACK.
+
+Wed Apr 19 10:18:17 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * printcmd.c (print_frame_args): Added code to attempt to deal
+ with arguments that are bigger than an int.
+
+ Continuation of Convex/Fortran changes:
+ * printcmd.c (print_scalar_formatted): Added leading zeros to
+ printing of large integers.
+ (address_info, print_frame_args): Added code to deal with
+ LOC_REF_ARG.
+ (print_nameless_args): Allow param file to specify a routine with
+ which to print typeless integers.
+ (printf_command): Deal with long long values well.
+ * stack.c (print_frame_arg_vars): Change to deal with LOC_REF_ARG.
+ * symmisc.c (print_symbol): Change to deal with LOC_REF_ARG.
+ * symseg.h: Added LOC_REF_ARG to enum address_class.
+ * symtab.c (lookup_block_symbol): Changed to deal with
+ LOC_REF_ARG.
+ * valarith.c (value_subscripted_rvalue): Created.
+ (value_subscript): Used above when app.
+ (value_less, value_equal): Change to cast to (char *) before doing
+ comparison, for machines where that casting does something.
+ * valops.c (call_function): Setup to deal with machines where you
+ cannot execute code on the stack segment.
+ * valprint.c (val_print): Make sure that array element size isn't
+ zero before printing. Set address of default array to address of
+ first element. Put in a couple of int cast. Removed some convex
+ specific code. Added check for endianness of machine in case of a
+ packed structure. Added code for printing typeless integers and
+ for LONG LONG's.
+ (set_maximum_command): Change to use parse_and_eval_address to get
+ argument (so can use expressions there).
+ * values.c (value_of_internalvar, set_internalvar_component,
+ set_internalvar, convenience_info): Add in hooks for trapped
+ internal vars.
+ (unpack_long): Deal with LONG_LONG.
+ (value_field): Remove LONGEST cast.
+ (using_struct_return): Fixed typo ENUM ==> UNION.
+ * xgdb.c (_initialize_xgdb): Make sure that specify_exec_file_hook
+ is not called unless we are setting up a windowing environ.
+
+Tue Apr 18 13:43:37 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ Various changes involved in 1) getting gdb to work on the convex,
+ and 2) Getting gdb to work with fortran (due to convex!csmith):
+ * convex-dep.c, convex-opcode.h, m-convex.h, convex-pinsn.c:
+ Created (or replaced with new files).
+ * Makefile: Add convex dependent files. Changed default flags to
+ gnu malloc to be CFLAGS.
+ * config.gdb: Added convex to list of machines.
+ * core.c (files_info): Added a FILES_INFO_HOOK to be used if
+ defined.
+ (xfer_core_file): Conditionalized compilation of xfer_core_file on
+ the macro XFER_CORE_FILE.
+ * coffread.c (record_misc_function): Made sure it zerod type field
+ (which is now being used; see next).
+ * dbxread.c: Included some convex dependent include files.
+ (copy_pending, fix_common_blocks): Created.
+ [STAB_REG_REGNUM, BELIEVE_PCC_PROMOTION]: Created default values;
+ may be overridden in m-*.h.
+ Included data structures for keeping track of common blocks.
+ (dbx_alloc_type): Modified; if called with negative 1's will
+ create a type without putting it into the type vector.
+ (read_dbx_symtab, read_addl_syms): Modified calls to
+ record_misc_function to include the new information.
+ (symbol_file_command, psymtab_to_symtab, add_file_command):
+ Modified reading in of string table to adapt to machines which
+ *don't* store the size of the string table in the first four bytes
+ of the string table.
+ (read_dbx_symtab, scan_file_globals, read_ofile_symtab,
+ read_addl_syms): Modified assignment of namestring to accept null
+ index into symtab as ok.
+ (read_addl_syms): Modified readin of a new object file to fiddle
+ with common blocks correctly.
+ (process_one_symbol): Fixed incorrect comment about convex. Get
+ symbols local to a lexical context from correct spot on a per
+ machine basis. Catch a bug in pcc which occaisionally puts an SO
+ where there should be an SOL. Seperate sections for N_BCOMM &
+ N_ECOMM.
+ (define_symbol): Ignore symbols with no ":". Use
+ STAB_REG_TO_REGNUM. Added support for function args calling by
+ reference.
+ (read_type): Only read type number if one is there. Remove old
+ (#if 0'd out) array code.
+ (read_array_type): Added code for dealing with adjustable (by
+ parameter) arrays half-heartedly.
+ (read_enum_type): Allow a ',' to end a list of values.
+ (read_range_type): Added code to check for long long.
+ * expread.y: Modified to use LONGEST instead of long where
+ necessary. Modified to use a default type of int for objects that
+ weren't in text space.
+ * findvar.c (locate_var_value, read_var_value): Modified to deal
+ with args passed by reference.
+ * inflow.c (create_inferior): Used CREATE_INFERIOR_HOOK if it
+ exists.
+ * infrun.c (attach_program): Run terminal inferior when attaching.
+ (wait_for_inferior): Removed several convex dependencies.
+ * main.c (float_handler): Created.
+ Made whatever signal indicates a stop configurable (via macro
+ STOP_SIGNAL).
+ (main): Setup use of above as a signal handler. Added check for
+ "-nw" in args already processed.
+ (command_line_input): SIGTSTP ==>STOP_SIGNAL.
+
+ * expread.y: Added token BLOCKNAME to remove reduce/reduce
+ conflict.
+ * Makefile: Change message to reflect new grammar.
+
+Mon Apr 17 13:24:59 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * printcmd.c (compare_ints): Created.
+ (print_frame_args): Modified to always print arguments in the
+ order in which they were found in the symbol table. Figure out
+ what apots are missing on the fly.
+
+ * stack.c (up_command): Error if no inferior or core file.
+
+ * m-i386.h, m-symmetry.h [FRAMELESS_FUNCTION_INVOCATION]: Created;
+ same as m68k.
+
+ * dbxread.c (define_symbol): Changed "desc==0" test to
+ "processing_gcc_compilation", which is the correct way to do it.
+
+Sat Apr 15 17:18:38 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * expread.y: Added precedence rules for arglists, ?:, and sizeof
+ to eliminate some shift-reduce conflicts.
+ * Makefile: Modified "Expect" message to conform to new results.
+
+Thu Apr 13 12:29:26 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * inflow.c (terminal_init_inferior): Fixed typo in recent diff
+ installation; TIOGETC ==> TIOCGETC.
+
+ * m-vax.h, m-sun2.h, m-sun3.h, m-sparc.h, m-hp*.h, m-isi.h,
+ m-news.h [FRAMELESS_FUNCTION_INVOCATION]: Created macro with
+ appropriate definition.
+
+Wed Apr 12 15:30:29 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * blockframe.c (get_prev_frame_info): Added in a macro to specify
+ when a "frame" is called without a frame pointer being setup.
+
+ * Makefile [clean]: Made sure to delete gnu malloc if it was being
+ used.
+
+Mon Apr 10 12:43:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (process_one_symbol): Reset within_function to 0 after
+ last RBRAC of a function.
+
+ * dbxread.c (read_struct_type): Changed check for filling in of
+ TYPE_MAIN_VARIANT of type.
+
+ * inflow.c (create_inferior): Conditionalized fork so that it
+ would be used if USG was defined and HAVE_VFORK was not defined.
+
+ * defs.h: Added comment about enum command_class element
+ class_alias.
+
+ * dbxread.c (process_one_symbol): Fixed a typo with interesting
+ implications for associative processing in the brain (':' ==> 'c').
+
+ * sparc-dep.c (isabranch): Changed name to isannulled, modified to
+ deal with coprocessor branches, and improved comment.
+ (single_step): Changed to trap at npc + 4 instead of pc +8 on
+ annulled branches. Changed name in call to isabranch as above.
+
+ * m-sun4os4.h (STACK_END_ADDRESS): Changed it to 0xf8000000 under
+ os 4.0.
+
+Sat Apr 8 17:04:07 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (process_one_symbol): In the case N_FUN or N_FNAME the
+ value being refered to is sometimes just a text segment variable.
+ Catch this case.
+
+ * infrun.c (wait_for_inferior), breakpoint.c
+ (breakpoint_stop_status): Move the selection of the frame to
+ inside breakpoint_stop_status so that the frame only gets selected
+ (and the symbols potentially read in) if the symbols are needed.
+
+ * symtab.c (find_pc_psymbol): Fixed minor misthough (pc >=
+ fucntion start, not >).
+
+ * breakpoint.c (_initialize_breakpoint): Change "delete" internal
+ help entry to simply refer to it being a prefix command (since the
+ list of subcommands is right there on a "help delete").
+
+Fri Apr 7 15:22:18 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * blockframe.c (find_pc_partial_function): Created; figures out
+ what function pc is in (name and address) without reading in any
+ new symbols.
+ * symtab.h: Added decl for above.
+ * infrun.c (wait_for_inferior): Used instead of
+ find_pc_function_start.
+ * stack.c (print_frame_info): Used instead of hand coding for same
+ thing.
+
+ * dbxread.c (psymtab_to_symtab): No longer patch readin pst's out
+ of the partial_symtab_list; need them there for some checks.
+ * blockframe.c (block_for_pc), source.c (select_source_symtab),
+ symtab.c (lookup_symbol, find_pc_symtab, list_symbols): Made extra
+ sure not to call psymtab_to_symtab with ->readin == 1, since these
+ psymtab now stay on the list.
+ * symtab.c (sources_info): Now distinguishes between psymtabs with
+ readin set and those with it not set.
+
+ * symtab.c (lookup_symtab): Added check through partial symtabs
+ for name with .c appended.
+
+ * source.c (select_source_symtab): Changed semantics a little so
+ that the argument means something.
+ * source.c (list_command), symtab.c (decode_line_1): Changed call
+ to select_source_symtab to match new conventions.
+
+ * dbxread.c (add_file_command): This command no longer selects a
+ symbol table to list from.
+
+ * infrun.c (wait_for_inferior): Only call find_pc_function (to
+ find out if we have debugging symbols for a function and hence if
+ we should step over or into it) if we are doing a "step".
+
+Thu Apr 6 12:42:28 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c (command_line_input): Added a local buffer and only
+ copied information into the global main.c buffer when it is
+ appropriate for it to be saved (and repeated).
+ (dont_repeat): Only nail line when we are reading from stdin
+ (otherwise null lines won't repeat and what's in line needs to be
+ saved).
+ (read_command_lines): Fixed typo; you don't what to repeat when
+ reading command lines from the input stream unless it's standard
+ input.
+
+ John Gilmore's (gnu@toad.com) mods for USG gdb:
+ * inflow.c: Removed inclusion of sys/user.h; no longer necessary.
+ (, terminal_init_inferior, terminal_inferior, terminal_ours_1,
+ term_status_command, _initialize_inflow) Seperated out declaration
+ and usage of terminal mode structures based on the existence of
+ the individual ioctls.
+ * utils.c (request_quit): Restore signal handler under USG. If
+ running under USG initialize sys_siglist at run time (too much
+ variation between systems).
+
+Wed Apr 5 13:47:24 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ John Gilmore's (gnu@toad.com) mods for USG gdb:
+ * default-dep.c: Moved include of sys/user.h to after include of
+ a.out.h.
+ (store_inferior_registers): Fixed error message.
+ (core_file_command): Improved error messages from reading in of
+ u area in core file. Changed calculation of offset of registers
+ to account for some machines putting it in as an offset rather
+ than an absolute address. Changed error messages for reading of
+ registers from core file.
+
+ * coffread.c (read_file_hdr): Added final check for BADMAG macro
+ to use if couldn't recognize magic number.
+ * Makefile: Added explicit directions for alloca addition.
+ Included alloca.c in list of possible library files. Cleaned up
+ possible library usage. Included additional information on gcc
+ and include files.
+
+ * source.c, remote.c, inflow.c, dbxread.c, core.c, coffread.c:
+ Changed include of sys/fcntl.h to an include of fcntl.h (as per
+ posix; presumably this will break fewer machines. I hopw).
+ * README: Added a pointer to comments at top of Makefile.
+ * Makefile: Added a comment about machines which need fcntl.h in
+ sys.
+
+Tue Apr 4 11:29:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * valprint.c (set_prettyprint_command, set_unionprint_command,
+ format_info): Created.
+ (_initialize_valprint): Added to lists of commands.
+
+ * gdb.texinfo [Backtrace]: Added a section describing the format
+ if symbols have not yet been read in.
+
+ * valprint.c (val_print): Added code to prettyprint structures if
+ "prettyprint" is set and only to print unions below the top level
+ if "unionprint" is set.
+
+ * infcmd.c (registers_info), valprint.c (value_print, val_print):
+ Added argument to call to val_print indicating deptch of recursion.
+
+ * symtab.[ch] (find_pc_psymbol): Created; finds static function
+ psymbol with value nearest to but under value passed.
+ * stack.c (print_frame_info): Used above to make sure I have best
+ fit to pc value.
+
+ * symseg.h (struct partial_symbol): Added value field.
+ * dbxread.c (read_dbx_symtab): Set value field for partial symbols
+ saved (so that we can lookup static symbols).
+
+ * symtab.[ch] (find_pc_symtab): Changed to external.
+ * stack.c (select_frame): Call above to make sure that symbols for
+ a selected frame is readin.
+
+Mon Apr 3 12:48:16 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * stack.c (print_frame_info): Modified to only print out full
+ stack frame info on symbols whose tables have been read in.
+ * symtab.c, symtab.h (find_pc_psymtab): Made function external;
+ above needed it.
+
+ * main.c (,set_verbose_command, initialize_main): Created a
+ variable "info_verbose" which says to talk it up in various and
+ sundry places. Added command to set this variable.
+ * gdb.texinfo (GDB Output): Added documentation on "set verbose"
+ and changed the name of the "Screen Output" section to "GDB
+ Output".
+ * dbxread.c (psymtab_to_symtab): Added information message about
+ symbol readin. Conditionalized on above.
+
+ * dbxread.c (define_symbol): Made an "i" constant be of class
+ LOC_CONST and an "r" constant be of class LOC_CONST_BYTES.
+
+ * README: Made a note about modifications which may be necessary
+ to the manual for this version of gdb.
+
+ * blockframe.c (get_prev_frame_info): Now we get saved address and
+ check for validity before we check for leafism. This means that
+ we will catch the fact that we are in start, but we will miss any
+ fns that start calls without an fp. This should be fine.
+
+ * m-*.h (FRAME_CHAIN): Modified to return 0 if we are in start.
+ This is usually a test for within the first object file.
+ * m-sparc.h (FRAME_CHAIN): The test here is simply if the fp saved
+ off the the start sp is 0.
+
+ * blockframe.c (get_prev_frame_info): Removed check to see if we
+ were in start. Screws up sparc.
+
+ * m-sparc.h (FRAME_FIND_SAVED_REGISTERS): Changed test for dummy
+ frame to not need frame to be innermost.
+
+ * gdb.texinfo: Added section on frameless invocations of functions
+ and when gdb can and can't deal with this.
+
+ * stack.c (frame_info): Disallowed call if no inferior or core
+ file; fails gracefully if truely bad stack specfication has been
+ given (ie. parse_frame_specification returns 0).
+
+Fri Mar 31 13:59:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * infrun.c (normal_stop): Changed references to "unset-env" to
+ "delete env".
+
+ * infcmd.c (_initialize_infcmd): Change reference to set-args in
+ help run to "set args".
+
+ * remote.c (getpkt): Allow immediate quit when reading from
+ device; it could be hung.
+
+ * coffread.c (process_coff_symbol): Modify handling of REG
+ parameter symbols.
+
+Thu Mar 30 15:27:23 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (symbol_file_command): Use malloc to allocate the
+ space for the string table in symbol_file_command (and setup a
+ cleanup for this). This allows a more graceful error failure if
+ there isn't any memory availible (and probably allows more memory
+ to be avail, depending on the machine).
+
+ Additional mods for handling GNU C++ (from Tiemann):
+ * dbxread.c (read_type): Added case for '#' type (method type, I
+ believe).
+ (read_struct_type): If type code is undefined, make the main
+ variant for the type be itself. Allow recognition of bad format
+ in reading of structure fields.
+ * eval.c (evaluate_subexp): Modify evaluation of a member of a
+ structure and pointer to same to make sure that the syntax is
+ being used correctly and that the member is being accessed correctly.
+ * symseg.h: Added TYPE_CODE_METHOD to enum type_code. Add a
+ pointer to an array of argument types to the type structure.
+ * symtab.c (lookout_method_type, smash_to_method_type): Created.
+ * symtab.h (TYPE_ARG_TYPES): Created.
+ * valops.c (call_function): Modified handling of methods to be the
+ same as handling of functions; no longer check for members.
+ * valprint.c (val_print, type_print_varspec_{prefix,suffix},
+ type_print_base): Added code to print method args correctly.
+ * values.c (value_virtual_fn_field): Modify access to virtual
+ function table.
+
+Wed Mar 29 13:19:34 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * findvar.c: Special cases for REGISTER_WINDOWS: 1) Return 0 if we
+ are the innermost frame, and 2) return the next frame in's value
+ if the SP is being looked for.
+
+ * blockframe.c (get_next_frame): Created; returns the next (inner)
+ frame of the called frame.
+ * frame.h: Extern delcaration for above.
+
+ * main.c (command_line_input): Stick null at end before doing
+ history expansion.
+
+Tue Mar 28 17:35:50 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Added namestring assignment to
+ N_DATA/BSS/ABS case. Sigh.
+
+Sat Mar 25 17:49:07 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * expread.y: Defined YYDEBUG.
+
+Fri Mar 24 20:46:55 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symtab.c (make_symbol_completion_list): Completely rewrote to
+ never call psymtab_to_symtab, to do a correct search (no
+ duplicates) through the visible symbols, and to include structure
+ and union fields in the things that it can match.
+
+Thu Mar 23 15:27:44 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (dbx_create_type): Created; allocates and inits space
+ for a type without putting it on the type vector lists.
+ (dbx_alloc_type): Uses above.
+
+ * Makefile: xgdb.o now produced by default rules for .o.c.
+
+Fri Mar 17 14:27:50 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * infrun.c: Fixed up inclusion of aouthdr.h on UMAX_PTRACE.
+
+ * Makefile, config.gdb: Added hp300bsd to potential
+ configurations.
+ * hp300bsd-dep.c, m-hp300bsd.h: Created.
+
+ * infrun.c (wait_for_inferior): Rewrote to do no access to
+ inferior until we make sure it's still there.
+
+ * inflow.c (inferior_died): Added a select to force the selected
+ frame to null when inferior dies.
+
+ * dbxread.c (symbol_file_command): free and zero symfile when
+ discarding symbols.
+
+ * core.c (xfer_core_file): Extended and cleaned up logic in
+ interpeting memory address.
+
+ * core.c (xfer_core_file): Extended opening comment.
+
+Thu Mar 16 15:39:42 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * coffread.c (symbol_file_command): Free symfile name when freeing
+ contents.
+
+ * blockframe.c (get_prev_frame_info): Added to fatal error message
+ to indicate that it should never happen.
+
+ * stack.c (frame_info): Printed out value of "saved" sp seperately
+ to call attention to the fact that it isn't stored in memory
+ anywhere; the actual previous frames address is printed.
+
+ * m-sparc.h (FRAME_FIND_SAVED_REGS): Set address of sp saved in
+ frame to value of fp (rather than value of sp in current frame).
+
+ * expread.y: Allow "unsigned" as a type itself, as well as a type
+ modifier.
+
+ * coffread.c: Added declaration for fclose
+
+Fri Mar 10 17:22:31 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c (command_line_input): Checked for -1 return from
+ readline; indicates EOF.
+
+Fri Mar 3 00:31:27 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * remote.c (remote_open): Cast return from signal to (void (*)) to
+ avoid problems on machines where the return type of signal is (int
+ (*)).
+
+ * Makefile: Removed deletion of version control from it (users
+ will need it for their changes).
+
+Thu Mar 2 15:32:21 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symmetry-dep.c (print_1167_regs): Print out effective doubles on
+ even number regs.
+ (fetch_inferior_registers): Get the floating point regs also.
+
+ * xgdb.c (do_command): Copied command before calling execute
+ command (so that execute_command wouldn't write into text space).
+
+ * copying.awk: Created (will produce copying.c as output when
+ given COPYING as input).
+ * Makefile: Used above to create copying.c.
+ * main.c: Took out info_warranty and info_copying.
+
+ * *.*: Changed copyright notice to use new GNU General Public
+ License (includes necessary changes to manual).
+
+ * xgdb.c (create_text_widget): Created text_widget before I create
+ the source and sink.
+ (print_prompt): Added fflush (stdout).
+
+ * Makefile: Added -lXmu to the compilation line for xgdb. Left
+ the old one there incase people still had R2.
+
+ * README: Added note about -gg format.
+
+ * remote.c (getpkt): Fixed typo; && ==> &.
+
+ * Makefile: Added new variable READLINE_FLAGS so that I could
+ force compilation of readline.c and history.c with -DSYSV on
+ system V machines. Mentioned in Makefile comments at top.
+
+Wed Mar 1 17:01:01 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * hp9k320-dep.c (store_inferior_registers): Fixed typo.
+
+Fri Feb 24 14:58:45 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * hp9k320-dep.c (store_inferior_registers,
+ fetch_inferior_registers): Added support for remote debugging.
+
+ * remote.c (remote_timer): Created.
+ (remote_open, readchar): Setup to timeout reads if they take
+ longer than "timeout". This allows one to debug how long such
+ things take.
+ (putpkt): Modified to print a debugging message (if such things
+ are enabled) each time it resends a packet.
+ (getpkt): Modified to make the variable CSUM unsigned and read it
+ CSUM with an & 0xff (presumably to deal with poor sign extension
+ on some machines). Also made c1 and c2 unsigned.
+ (remote_wait): Changed buffer to unsigned status.
+ (remote_store_registers, remote_write_bytes): Puts a null byte at
+ the end of the control string.
+
+ * infcmd.c (attach_command, detach_command, _initialize_infcmd):
+ Made attach_command and detach_command always availible, but
+ modified them to only allow device file attaches if ATTACH_DETACH
+ is not defined.
+
+ * gdb.texinfo: Added cross reference from attach command to remote
+ debugging.
+
+Thu Feb 23 12:37:59 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * remote.c (remote_close): Created to close the remote connection
+ and set the remote_debugging flag to 0.
+ * infcmd.c (detach_command): Now calls the above when appropriate.
+
+ * gdb.texinfo: Removed references to the ``Distribution'' section
+ in the copyright.
+
+ * main.c, utils.c (ISATTY): Created default defintions of this
+ macro which use isatty and fileno.
+ * utils.c (fprintf_filtered, print_spaces_filtered), main.c
+ (command_loop, command_line_input): Used this macro.
+ * m-news.h: Created a definition to override this one.
+
+ * utils.c (fprintf_filtered): Made line_size static (clueless).
+
+ * utils.c (fprintf_filtered): Changed max length of line printed
+ to be 255 chars or twice the format length.
+
+ * symmetry-dep.c, m-symmetry: Fixed typo (^L ==> ).
+
+ * printcmd.c (do_examine): Fixed typo (\n ==> \t).
+
+Wed Feb 22 16:00:33 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ Contributed by Jay Vosburgh (jay@mentor.cc.purdue.edu)
+ * m-symmetry.h, symmetry-dep.c: Created.
+ * Makefile: Added above in appropriate lists.
+ * config.gdb: Added "symmetry" target.
+
+ * utils.c (prompt_for_continue): Zero'd chars_printed also.
+
+ * utils.c (fprintf_filtered): Call prompt for continue instead of
+ doing it yourself.
+
+ * dbxread.c (read_dbx_symtab): Added code to conditionalize what
+ symbol type holds to "x.o" or "-lx" symbol that indicates the
+ beginning of a new file.
+
+Tue Feb 21 16:22:13 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * gdb.texinfo: Deleted @ignore block at end of file.
+
+ * findvar.c, stack.c: Changed comments that refered to "frame
+ address" to "frame id".
+
+ * findvar.c (locate_var_value): Modified so that taking the
+ address of an array generates an object whose type is a pointer to
+ the elements of the array.
+
+Sat Feb 18 16:35:14 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * gdb.texinfo: Removed reference to "!" as a shell escape
+ character. Added a section on controling screen output
+ (pagination); changing "Input" section to "User Interface"
+ section. Changed many inappropriate subsubsection nodes into
+ subsections nodes (in the readline and history expansion
+ sections).
+
+Fri Feb 17 11:10:54 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * utils.c (set_screensize_command): Created.
+ (_initialize_utils): Added above to setlist.
+
+ * main.c (main): Added check to see if ~/.gdbinit and .gdbinit
+ were the same file; only one gets read if so. Had to include
+ sys/stat.h for this.
+
+ * valprint.c (type_print_base): Changed calls to print_spaces to
+ print_spaces_filtered.
+
+ * main.c (command_line_input): Chaned test for command line
+ editing to check for stdin and isatty.
+
+ * main.c (command_loop): Call reinitialize_more_filter before each
+ command (if reading from stdin and it's a tty).
+ utils.c (initialize_more_filter): Changed name to
+ reinitialize_more_filter; killed arguments.
+ utils.c (_initialize_utils): Created; initialized lines_per_page
+ and chars_per_line here.
+
+ * utils.c (fprintf_filtered): Removed printing of "\\\n" after
+ printing linesize - 1 chars; assume that the screen display will
+ take care of that. Still watching that overflow.
+
+ * main.c: Created the global variables linesize and pagesize to
+ describe the number of chars per line and lines per page.
+
+Thu Feb 16 17:27:43 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * printcmd.c (do_examine, print_scalar_formatted, print_address,
+ whatis_command, do_one_display, ptype_command), valprint.c
+ (value_print, val_print, type_print_method_args, type_print_1,
+ type_print_derivation_info, type_print_varspec_suffix,
+ type_print_base), breakpoint.c (breakpoints_info, breakpoint_1),
+ values.c (history_info), main.c (editing_info, warranty_info,
+ copying_info), infcmd.c (registers_info), inflow.c
+ (term_status_command), infrun.c (signals_info), stack.c
+ (backtrace_command, print_frame_info), symtab.c (list_symbols,
+ output_source_filename), command.c (help_cmd, help_list,
+ help_command_list): Replaced calls to printf, fprintf, and putc
+ with calls to [f]printf_filtered to handle more processing.
+ Killed local more emulations where I noticed them.
+
+Wed Feb 15 15:27:36 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * defs.h, utils.c (initialize_more_filter, fprintf_filtered,
+ printf_filtered): Created a printf that will also act as a more
+ filter, prompting the user for a <return> whenever the page length
+ is overflowed.
+
+ * symtab.c (list_symbols): Elminated some code inside of an #if 0.
+
+Tue Feb 14 11:11:24 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * Makefile: Turned off backup versions for this file; it changes
+ too often.
+
+ * command.c (lookup_cmd, _initialize_command): Changed '!' so that
+ it was no longer a shell escape. "sh" must be used.
+
+ * main.c (command_line_input, set_history_expansion,
+ initialize_main): Turned history expansion on, made it the
+ default, and only execute it if the first character in the line is
+ a '!'.
+
+ * version.c, gdb.texinfo: Moved version to 3.2 (as usual, jumping
+ the gun some time before release).
+
+ * gdb.texinfo: Added sections (adapted from Brian's notes) on
+ command line editing and history expansion.
+
+ * main.c (set_command_editing, initialize_main): Modified name to
+ set_editing and modified command to "set editing".
+
+ * Makefile: Put in dependencies for READLINEOBJS.
+
+ * main.c (history_info, command_info): Combined into new command
+ info; deleted history_info.
+ (initialize_main): Deleted "info history" command; it was
+ interfering with the value history.
+
+ * coffread.c (enter_linenos): Modified to do bit copy instead of
+ pointer dereference, since the clipper machine can't handle having
+ longs on short boundaries.
+ (read_file_hdr): Added code to get number of syms for clipper.
+
+ * stack.c (return_command): Fixed method for checking when all of
+ the necessary frames had been popped.
+
+ * dbxread.c (read_dbx_symtab (ADD_PSYMBOL_TO_LIST)): Fixed typo in
+ allocation length.
+
+Mon Feb 13 10:03:27 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Split assignment to namestring into
+ several different assignments (so that it wouldn't be done except
+ when it had to be). Shortened switches and duplicated code to
+ produce the lowest possible execution time. Commented (at top of
+ switch) which code I duplicated.
+
+ * dbxread.c (read_dbx_symtab): Modified which variables were
+ register and deleted several variables which weren't used. Also
+ eliminated 'F' choice from subswitch, broke out strcmp's, reversed
+ compare on line 1986, and elminated test for !namestring[0]; it is
+ caught by following test for null index of ':'.
+
+Sun Feb 12 12:57:56 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * main.c (gdb_completer_word_break_characters): Turned \~ into ~.
+
+Sat Feb 11 15:39:06 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * symtab.c (find_pc_psymtab): Created; checks all psymtab's till
+ it finds pc.
+ (find_pc_symtab): Used; fatal error if psymtab found is readin
+ (should have been caught in symtab loop).
+ (lookup_symbol): Added check before scan through partial symtab
+ list for symbol name to be on the misc function vector (only if in
+ VAR_NAMESPACE). Also made sure that psymtab's weren't fooled with
+ if they had already been read in.
+ (list_symbols): Checked through misc_function_vector for matching
+ names if we were looking for functions.
+ (make_symbol_completion_list): Checked through
+ misc_function_vector for matching names.
+ * dbxread.c (read_dbx_symtab): Don't bother to do processing on
+ global function types; this will be taken care of by the
+ misc_function hack.
+
+ * symtab.h: Modified comment on misc_function structure.
+
+Fri Feb 10 18:09:33 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * symseg.h, dbxread.c (read_dbx_symtab, init_psymbol_list,
+ start_psymtab, end_psymtab), coffread.c (_initialize_coff),
+ symtab.c (lookup_partial_symbol, list_symbols,
+ make_symbol_completion_list): Changed separate variables for
+ description of partial symbol allocation into a specific kind of
+ structure.
+
+ (read_dbx_symtab, process_symbol_for_psymtab): Moved most of
+ process_symbol_for_psymtab up into read_dbx_symtab, moved a couple
+ of symbol types down to the ingore section, streamlined (I hope)
+ code some, modularized access to psymbol lists.
+
+Thu Feb 9 13:21:19 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c (command_line_input): Made sure that it could recognize
+ newlines as indications to repeat the last line.
+
+ * symtab.c (_initialize_symtab): Changed size of builtin_type_void
+ to be 1 for compatibility with gcc.
+
+ * main.c (initialize_main): Made history_expansion the default
+ when gdb is compiled with HISTORY_EXPANSION.
+
+ * readline.c, readline.h, history.c, history.h, general.h,
+ emacs_keymap.c, vi_keymap.c, keymaps.c, funmap.c: Made all of
+ these links to /gp/gnu/bash/* to keep them updated.
+ * main.c (initialize_main): Made default be command editing on.
+
+Wed Feb 8 13:32:04 1989 & Smith (randy at hobbes)
+
+ * dbxread.c (read_dbx_symtab): Ignore N_BSLINE on first
+ readthrough.
+
+ * Makefile: Removed convex-dep.c from list of distribution files.
+
+Tue Feb 7 14:06:25 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c: Added command lists sethistlist and unsethistlist to
+ accesible command lists.
+ (parse_binary_operation): Created to parse a on/1/yes vs. off/0/no
+ spec.
+ (set_command_edit, set_history, set_history_expansion,
+ set_history_write, set_history_size, set_history_filename,
+ command_info, history_info): Created to allow users to control
+ various aspects of command line editing.
+
+ * main.c (symbol_creation_function): Created.
+ (command_line_input, initialize_main): Added rest of stuff
+ necessary for calling bfox' command editing routines under
+ run-time control.
+ * Makefile: Included readline and history source files for command
+ editing; also made arrangements to make sure that the termcap
+ library was available.
+ * symtab.c (make_symbol_completion_list): Created.
+
+Mon Feb 6 16:25:25 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c: Invented variables to control command editing.
+ command_editing_p, history_expansion_p, history_size,
+ write_history_p, history_filename. Initialized them to default
+ values in initialize_main.
+
+ * infcmd.c (registers_info), infrun.c (signals_info),
+ * main.c (gdb_read_line): Changed name to command_line_input.
+ (readline): Changed name to gdb_readline; added second argument
+ indicating that the read value shouldn't be saved (via malloc).
+ * infcmd.c (registers_info), infrun.c (signals_info), main.c
+ (copying_info), symtab.c (output_source_filename, MORE,
+ list_symbols): Converted to use gdb_readline in place of
+ gdb_read_line.
+
+
+Sun Feb 5 17:34:38 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * blockframe.c (get_frame_saved_regs): Removed macro expansion
+ that had accidentally been left in the code.
+
+Sat Feb 4 17:54:14 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * main.c (gdb_read_line, readline): Added function readline and
+ converted gdb_read_line to use it. This was a conversion to the
+ line at a time style of input, in preparation for full command
+ editing.
+
+Fri Feb 3 12:39:03 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Call end_psymtab at the end of
+ read_dbx_symtab if any psymtab still needs to be completed.
+
+ * config.gdb, sun3-dep.c: Brought these into accord with the
+ actual sun2 status (no floating point period; sun3-dep.c unless
+ has os > 3.0).
+ * m-sun2os2.h: Deleted; not needed.
+
+ * config.gdb: Added a couple of aliases for machines in the
+ script.
+
+ * infrun.c: Added inclusion of aouthdr.h inside of #ifdef UMAX
+ because ptrace needs to know about the a.out header.
+
+ * Makefile: Made dep.o depend on dep.c and config.status only.
+
+ * expread.y: Added declarations of all of the new write_exp_elt
+ functions at the include section in the top.
+
+ * Makefile: Added a YACC definition so that people can use bison
+ if they wish.
+
+ * Makefile: Added rms' XGDB-README to the distribution.
+
+ * Makefile: Added removal of init.o on a "make clean".
+
+Thu Feb 2 16:27:06 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * *-dep.c: Deleted definition of COFF_FORMAT if AOUTHDR was
+ defined since 1) We *may* (recent mail message) want to define
+ AOUTHDR under a basically BSD system, and 2) AOUTHDR is sometimes
+ a typedef in coff encapsulation setups. Also removed #define's of
+ AOUTHDR if AOUTHDR is already defined (inside of coff format).
+ * core.c, dbxread.c: Removed #define's of AOUTHDR if AOUTHDR is
+ already defined (inside of coff format).
+
+Tue Jan 31 12:56:01 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * GDB 3.1 released.
+
+ * values.c (modify_field): Changed test for endianness to assign
+ to integer and reference character (so that all bits would be
+ defined).
+
+Mon Jan 30 11:41:21 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * news-dep.c: Deleted inclusion of fcntl.h; just duplicates stuff
+ found in sys/file.h.
+
+ * i386-dep.c: Included default definition of N_SET_MAGIC for
+ COFF_FORMAT.
+
+ * config.gdb: Added checks for several different operating
+ systems.
+
+ * coffread.c (read_struct_type): Put in a flag variable so that
+ one could tell when you got to the end of a structure.
+
+ * sun3-dep.c (core_file_command): Changed #ifdef based on SUNOS4
+ to ifdef based on FPU.
+
+ * infrun.c (restore_inferior_status): Changed error message to
+ "unable to restore previously selected frame".
+
+ * dbxread.c (read_dbx_symtab): Used intermediate variable in error
+ message reporting a bad symbol type. (scan_file_globals,
+ read_ofile_symtab, read_addl_syms): Data type of "type" changed to
+ unsigned char (which is what it is).
+ * i386-dep.c: Removed define of COFF_FORMAT if AOUTHDR is defined.
+ Removed define of a_magic to magic (taken care of by N_MAGIC).
+ (core_file_command): Zero'd core_aouthdr instead of setting magic
+ to zero.
+ * i386-pinsn.c: Changed jcxz == jCcxz in jump table.
+ (putop): Added a case for 'C'.
+ (OP_J): Added code to handle possible masking of PC value on
+ certain kinds of data.
+ m-i386gas.h: Moved COFF_ENCAPSULATE to before inclusion of
+ m-i386.h and defined NAMES_HAVE_UNDERSCORE.
+
+ * coffread.c (unrecrod_misc_function, read_coff_symtab): Added
+ symbol number on which error occured to error output.
+
+Fri Jan 27 11:55:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * Makefile: Removed init.c in make clean. Removed it without -f
+ and with leading - in make ?gdb.
+
+Thu Jan 26 15:08:03 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ Changes to get it to work on gould NP1.
+ * dbxread.c (read_dbx_symtab): Included cases for N_NBDATA and
+ N_NBBSS.
+ (psymtab_to_symtab): Changed declaration of hdr to
+ DECLARE_FILE_HEADERS. Changed access to use STRING_TABLE_SIZE and
+ SYMBOL_TABLE_SIZE.
+ * gld-pinsn.c (findframe): Added declaration of framechain() as
+ FRAME_ADDR.
+
+ * coffread.c (read_coff_symtab): Avoided treating typedefs as
+ external symbol definitions.
+
+Wed Jan 25 14:45:43 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * Makefile: Removed reference to alloca.c. If they need it, they
+ can pull alloca.o from the gnu-emacs directory.
+
+ * version.c, gdb.texinfo: Updated version to 3.1 (jumping the gun
+ a bit so that I won't forget when I release).
+
+ * m-sun2.h, m-sun2os2.h, m-sun3os4.h, config.gdb: Modified code so
+ that default includes new sun core, ptrace, and attach-detach.
+ Added defaults for sun 2 os 2.
+
+ Modifications to reset stack limit back to what it used to be just
+ before exec. All mods inside of #ifdef SET_STACK_LIMIT_HUGE.
+ * main.c: Added global variable original_stack_limit.
+ (main): Set original_stack_limit to original stack limit.
+ * inflow.c: Added inclusion of necessary files and external
+ reference to original_stack_limit.
+ (create_inferior): Reset stack limit to original_stack_limit.
+
+ * dbxread.c (read_dbx_symtab): Killed PROFILE_SYMBOLS ifdef.
+
+ * sparc-dep.c (isabranch): Multiplied offset by 4 before adding it
+ to addr to get target.
+
+ * Makefile: Added definition of SHELL to Makefile.
+
+ * m-sun2os4.h: Added code to define NEW_SUN_PTRACE, NEW_SUN_CORE,
+ and ATTACH_DETACH.
+ * sun3-dep.c: Added code to avoid fp regs if we are on a sun2.
+
+Tue Jan 24 17:59:14 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_array_type): Added function.
+ (read_type): Added call to above instead of inline code.
+
+ * Makefile: Added ${GNU_MALLOC} to the list of dependencies for
+ the executables.
+
+Mon Jan 23 15:08:51 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * gdb.texinfo: Added paragraph to summary describing languages
+ with which gdb can be run. Also added descriptions of the
+ "info-methods" and "add-file" commands.
+
+ * symseg.h: Commented a range type as having TYPE_TARGET_TYPE
+ pointing at the containing type for the range (often int).
+ * dbxread.c (read_range_type): Added code to do actual range types
+ if they are defined. Assumed that the length of a range type is
+ the length of the target type; this is a lie, but will do until
+ somebody gets back to me as to what these silly dbx symbols mean.
+
+ * dbxread.c (read_range_type): Added code to be more picky about
+ recognizing builtins as range types, to treat types defined as
+ subranges of themselves to be subranges of int, and to recognize
+ the char type idiom from dbx as a special case.
+
+Sun Jan 22 01:00:13 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-vax.h: Removed definition of FUNCTION_HAS_FRAME_POINTER.
+ * blockframe.c (get_prev_frame_info): Removed default definition
+ and use of above. Instead conditionalized checking for leaf nodes
+ on FUNCTION_START_OFFSET (see comment in code).
+
+Sat Jan 21 16:59:19 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_range_type): Fixed assumption that integer was
+ always type 1.
+
+ * gdb.texinfo: Fixed spelling mistake and added a note in the
+ running section making it clear that users may invoke subroutines
+ directly from gdb.
+
+ * blockframe.c: Setup a default definition for the macro
+ FUNCTION_HAS_FRAME_POINTER.
+ (get_prev_frame_info): Used this macro instead of checking
+ SKIP_PROLOGUE directly.
+ * m-vax.h: Overroad definition; all functions on the vax have
+ frame pointers.
+
+Fri Jan 20 12:25:35 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * core.c: Added default definition of N_MAGIC for COFF_FORMAT.
+
+ * xgdb.c: Installed a fix to keep the thing from dying when there
+ isn't any frame selected.
+
+ * core.c: Made a change for the UMAX system; needs a different
+ file included if using that core format.
+
+ * Makefile: Deleted duplicate obstack.h in dbxread.c dependency.
+
+ * munch: Modified (much simpler) to cover (I hope) all cases.
+
+ * utils.c (save_cleanups, restore_cleanups): Added functions to
+ allow you to push and pop the chain of cleanups to be done.
+ * defs.h: Declared the new functions.
+ * main.c (catch_errors): Made sure that the only cleanups which
+ would be done were the ones put on the chain *after* the current
+ location.
+
+ * m-*.h (FRAME_CHAIN_VALID): Removed check on pc in the current
+ frame being valid.
+ * blockframe.c (get_prev_frame_info): Made the assumption that if
+ a frame's pc value was within the first object file (presumed to
+ be /lib/crt0.o), that we shouldn't go any higher.
+
+ * infrun.c (wait_for_inferior): Do *not* execute check for stop pc
+ at step_resume_break if we are proceeding over a breakpoint (ie.
+ if trap_expected != 0).
+
+ * Makefile: Added -g to LDFLAGS.
+
+ * m-news.h (POP_FRAME) Fixed typo.
+
+ * printcmd.c (print_frame_args): Modified to print out register
+ params in order by .stabs entry, not by register number.
+
+ * sparc-opcode.h: Changed declaration of (struct
+ arith_imm_fmt).simm to be signed (as per architecture manual).
+ * sparc-pinsn.c (fprint_addr1, print_insn): Forced a cast to an
+ int, so that we really would get signed behaivior (default for sun
+ cc is unsigned).
+
+ * i386-dep.c (i386_get_frame_setup): Replace function with new
+ function provided by pace to fix bug in recognizing prologue.
+
+Thu Jan 19 11:01:22 1989 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * infcmd.c (run_command): Changed error message to "Program not
+ restarted."
+
+ * value.h: Changed "frame" field in value structure to be a
+ FRAME_ADDR (actually CORE_ADDR) so that it could survive across
+ calls.
+
+ * m-sun.h (FRAME_FIND_SAVED_REGS): Fixed a typo.
+
+ * value.h: Added lval: "lval_reg_frame_relative" to indicate a
+ register that must be interpeted relative to a frame. Added
+ single entry to value structure: "frame", used to indicate which
+ frame a relative regnum is relative to.
+ * findvar.c (value_from_register): Modified to correctly setup
+ these fields when needed. Deleted section to fiddle with last
+ register copied on little endian machine; multi register
+ structures will always occupy an integral number of registers.
+ (find_saved_register): Made extern.
+ * values.c (allocate_value, allocate_repeat_value): Zero frame
+ field on creation.
+ * valops.c (value_assign): Added case for lval_reg_frame_relative;
+ copy value out, modify it, and copy it back. Desclared
+ find_saved_register as being external.
+ * value.h: Removed addition of kludgy structure; thoroughly
+ commented file.
+ * values.c (free_value, free_all_values, clear_value_history,
+ set_internalvar, clear_internavars): Killed free_value.
+
+Wed Jan 18 20:09:39 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * value.h: Deleted struct partial_storage; left over from
+ yesterday.
+
+ * findvar.c (value_from_register): Added code to create a value of
+ type lval_reg_partsaved if a value is in seperate registers and
+ saved in different places.
+
+Tue Jan 17 13:50:18 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * value.h: Added lval_reg_partsaved to enum lval_type and
+ commented enum lval_type. Commented value structure.
+ Added "struct partial_register_saved" to value struct; added
+ macros to deal with structure to value.h.
+ * values.c (free_value): Created; special cases lval_reg_partsaved
+ (which has a pointer to an array which also needs to be free).
+ (free_all_values, clear_value_history, set_internalvar,
+ clear_internalvars): Modified to use free_values.
+
+ * m-sunos4.h: Changed name to sun3os4.h.
+ * m-sun2os4.h, m-sun4os4.h: Created.
+ * config.gdb: Added configuration entries for each of the above.
+ * Makefile: Added into correct lists.
+
+ * Makefile: Added dependencies on a.out.encap.h. Made
+ a.out.encap.h dependent on a.out.gnu.h and dbxread.c dependent on
+ stab.gnu.h.
+
+ * infrun.c, remote.c: Removed inclusion of any a.out.h files in
+ these files; they aren't needed.
+
+ * README: Added comment about bug reporting and comment about
+ xgdb.
+
+ * Makefile: Added note to HPUX dependent section warning about
+ problems if compiled with gcc and mentioning the need to add
+ -Ihp-include to CFLAGS if you compile on those systems. Added a
+ note about needing the GNU nm with compilers *of gdb* that use the
+ coff encapsulate feature also. * hp-include: Made symbolic link
+ over to /gp/gnu/binutils.
+
+ * Makefile: Added TSOBS NTSOBS OBSTACK and REGEX to list of things
+ to delete in "make clean". Also changed "squeakyclean" target as
+ "realclean".
+
+ * findvar.c (value_from_register): Added assignment of VALUE_LVAL
+ to be lval_memory when that is appropriate (original code didn't
+ bother because it assumed that it was working with a pre lval
+ memoried value).
+
+ * expread.y (yylex): Changed to only return type THIS if the
+ symbol "$this" is defined in some block superior or equal to the
+ current expression context block.
+
+Mon Jan 16 13:56:44 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-*.h (FRAME_CHAIN_VALID): On machines which check the relation
+ of FRAME_SAVED_PC (thisframe) to first_object_file_end (all except
+ gould), make sure that the pc of the current frame also passes (in
+ case someone stops in _start).
+
+ * findvar.c (value_of_register): Changed error message in case of
+ no inferior or core file.
+
+ * infcmd.c (registers_info): Added a check for inferior or core
+ file; error message if not.
+
+ * main.c (gdb_read_line): Modified to take prompt as argument and
+ output it to stdout.
+ * infcmd.c (registers_info, signals_info), main.c (command_loop,
+ read_command_lines, copying_info), symtab.c (decode_line_2,
+ output_source_filename, MORE, list_symbols): Changed calling
+ convention used to call gdb_read_line.
+
+ * infcmd.c, infrun.c, main.c, symtab.c: Changed the name of the
+ function "read_line" to "gdb_read_line".
+ * breakpoint.c: Deleted external referenced to function
+ "read_line" (not needed by code).
+
+Fri Jan 13 12:22:05 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * i386-dep.c: Include a.out.encap.h if COFF_ENCAPSULATE.
+ (N_SET_MAGIC): Defined if not defined by include file.
+ (core_file_command): Used N_SET_MAGIC instead of assignment to
+ a_magic.
+ (exec_file_command): Stuck in a HEADER_SEEK_FD.
+
+ * config.gdb: Added i386-dep.c as depfile for i386gas choice.
+
+ * munch: Added -I. to cc to pick up things included by the param
+ file.
+
+ * stab.gnu.def: Changed name to stab.def (stab.gnu.h needs this name).
+ * Makefile: Changed name here also.
+ * dbxread.c: Changed name of gnu-stab.h to stab.gnu.h.
+
+ * gnu-stab.h: Changed name to stab.gnu.h.
+ * stab.gnu.def: Added as link to binutils.
+ * Makefile: Put both in in the distribution.
+
+Thu Jan 12 11:33:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c: Made which stab.h is included dependent on
+ COFF_ENCAPSULATE; either <stab.h> or "gnu-stab.h".
+ * Makefile: Included gnu-stab.h in the list of files to include in
+ the distribution.
+ * gnu-stab.h: Made a link to /gp/gnu/binutils/stab.h
+
+ * Makefile: Included a.out.gnu.h and m-i386gas.h in list of
+ distribution files.
+ * m-i386gas.h: Changed to include m-i386.h and fiddle with it
+ instead of being a whole new file.
+ * a.out.gnu.h: Made a link to /gp/gnu/binutils/a.out.gnu.h.
+
+ Chris Hanson's changes to gdb for hp Unix.
+ * Makefile: Modified comments on hpux.
+ * hp9k320-dep.c: #define'd WOPR & moved inclusion of signal.h
+ * inflow.c: Moved around declaratiosn of <sys/fcntl.h> and
+ <sys/ioctl.h> inside of USG depends and deleted all SYSV ifdef's
+ (use USG instead).
+ * munch: Modified to accept any number of spaces between the T and
+ the symbol name.
+
+ Pace's changes to gdb to work with COFF_ENCAPSULATE (robotussin):
+ * config.gdb: Added i386gas to targets.
+ * default-dep.c: Include a.out.encap.h if COFF_ENCAPSULATE.
+ (N_SET_MAGIC): Defined if not defined by include file.
+ (core_file_command): Used N_SET_MAGIC instead of assignment to a_magic.
+ (exec_file_command): Stuck in a HEADER_SEEK_FD.
+ * infrun.c, remote.c: Added an include of a.out.encap.h if
+ COFF_ENCAPSULATE defined. This is commented out in these two
+ files, I presume because the definitions aren't used.
+ * m-i386gas.h: Created.
+ * dbxread.c: Included defintions for USG.
+ (READ_FILE_HEADERS): Now uses HEADER_SEEK_FD if it exists.
+ (symbol_file_command): Deleted use of HEADER_SEEK_FD.
+ * core.c: Deleted extra definition of COFF_FORMAT.
+ (N_MAGIC): Defined to be a_magic if not already defined.
+ (validate_files): USed N_MAGIC instead of reading a_magic.
+
+Wed Jan 11 12:51:00 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * remote.c: Upped PBUFSIZ.
+ (getpkt): Added zeroing of c inside loop in case of error retry.
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Removed
+ code to not put stuff with debugging symbols in the misc function
+ list. Had been ifdef'd out.
+
+ * gdb.texinfo: Added the fact that the return value for a function
+ is printed if you use return.
+
+ * infrun.c (wait_for_inferior): Removed test in "Have we hit
+ step_resume_breakpoint" for sp values in proper orientation. Was
+ in there for recursive calls in functions without frame pointers
+ and it was screwing up calls to alloca.
+
+ * dbxread.c: Added #ifdef COFF_ENCAPSULATE to include
+ a.out.encap.h.
+ (symbol_file_command): Do HEADER_SEEK_FD when defined.
+ * dbxread.c, core.c: Deleted #ifdef ROBOTUSSIN stuff.
+ * robotussin.h: Deleted local copy (was symlink).
+ * a.out.encap.h: Created symlink to
+ /gp/gnu/binutils/a.out.encap.h.
+ * Makefile: Removed robotussin.h and included a.out.encap.h in
+ list of files.
+
+ * valprint.c (val_print, print_scalar_formatted): Changed default
+ precision of printing float value; now 6 for a float and 16 for a
+ double.
+
+ * findvar.c (value_from_register): Added code to deal with the
+ case where a value is spread over several registers. Still don't
+ deal with the case when some registers are saved in memory and
+ some aren't.
+
+Tue Jan 10 17:04:04 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * xgdb.c (xgdb_create_window): Removed third arg (XtDepth) to
+ frameArgs.
+
+ * infrun.c (handle_command): Error if signal number is less or
+ equal to 0 or greater or equal to NSIG or a signal number is not
+ provided.
+
+ * command.c (lookup_cmd): Modified to not convert command section
+ of command line to lower case in place (in case it isn't a
+ subcommand, but an argument to a command).
+
+Fri Jan 6 17:57:34 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c: Changed "text area" to "data area" in comments on
+ N_SETV.
+
+Wed Jan 4 12:29:54 1989 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c: Added definitions of gnu symbol types after inclusion
+ of a.out.h and stab.h.
+
+Mon Jan 2 20:38:31 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * eval.c (evaluate_subexp): Binary logical operations needed to
+ know type to determine whether second value should be evaluated.
+ Modified to discover type before binup_user_defined_p branch.
+ Also commented "enum noside".
+
+ * Makefile: Changed invocations of munch to be "./munch".
+
+ * gdb.texinfo: Updated to refer to current version of gdb with
+ January 1989 last update.
+
+ * coffread.c (end_symtab): Zero context stack when finishing
+ lexical contexts.
+ (read_coff_symtab): error if context stack 0 in ".ef" else case.
+
+ * m-*.h (FRAME_SAVED_PC): Changed name of argument from "frame" to
+ "FRAME" to avoid problems with replacement of "->frame" part of
+ macro.
+
+ * i386-dep.c (i386_get_frame_setup): Added codestream_get() to
+ move codestream pointer up to the correct location in "subl $X,
+ %esp" case.
+
+Sun Jan 1 14:24:35 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * valprint.c (val_print): Rewrote routine to print string pointed
+ to by char pointer; was producing incorrect results when print_max
+ was 0.
+
+Fri Dec 30 12:13:35 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Put
+ everything on the misc function list.
+
+ * Checkpointed distribution.
+
+ * Makefile: Added expread.tab.c to the list of things slated for
+ distribution.
+
+Thu Dec 29 10:06:41 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * stack.c (set_backtrace_limit_command, backtrace_limit_info,
+ bactrace_command, _initialize_stack): Removed modifications for
+ limit on backtrace. Piping the backtrace through an interuptable
+ "more" emulation is a better way to do it.
+
+Wed Dec 28 11:43:09 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * stack.c
+ (set_backtrace_limit_command): Added command to set a limit to the
+ number of frames for a backtrace to print by default.
+ (backtrace_limit_info): To print the current limit.
+ (backtrace_command): To use the limit.
+ (_initialize_stack): To initialize the limit to its default value
+ (30), and add the set and info commands onto the appropriate
+ command lists.
+
+ * gdb.texinfo: Documented changes to "backtrace" and "commands"
+ commands.
+
+ * stack.c (backtrace_command): Altered so that a negative argument
+ would show the last few frames on the stack instead of the first
+ few.
+ (_initialize_stack): Modified help documentation.
+
+ * breakpoint.c (commands_command): Altered so that "commands" with
+ no argument would refer to the last breakpoint set.
+ (_initialize_breakpoint): Modified help documentation.
+
+ * infrun.c (wait_for_inferior): Removed ifdef on Sun4; now you can
+ single step through compiler generated sub calls and will die if
+ you next off of the end of a function.
+
+ * sparc-dep.c (single_step): Fixed typo; "break_insn" ==> "sizeof
+ break_insn".
+
+ * m-sparc.h (INIT_EXTRA_FRAME_INFO): Set the bottom of a stack
+ frame to be the bottom of the stack frame inner from this, if that
+ inner one is a leaf node.
+
+ * dbxread.c (read_dbx_symtab): Check to make sure we don't add a
+ psymtab to it's own dependency list.
+
+ * dbxread.c (read_dbx_symtab): Modified check for duplicate
+ dependencies to catch them correctly.
+
+Tue Dec 27 17:02:09 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-*.h (FRAME_SAVED_PC): Modified macro to take frame info
+ pointer as argument.
+ * stack.c (frame_info), blockframe.c (get_prev_frame_info),
+ gld-pinsn.c (findframe), m-*.h (SAVED_PC_AFTER_CALL,
+ FRAME_CHAIN_VALID, FRAME_NUM_ARGS): Changed usage of macros to
+ conform to above.
+ * m-sparc.h (FRAME_SAVED_PC), sparc-dep.c (frame_saved_pc):
+ Changed frame_saved_pc to have a frame info pointer as an
+ argument.
+
+ * m-vax.h, m-umax.h, m-npl.h, infrun.c (wait_for_inferior),
+ blockframe.c (get_prev_frame_info): Modified SAVED_PC_AFTER_CALL
+ to take a frame info pointer as an argument.
+
+ * blockframe.c (get_prev_frame_info): Altered the use of the
+ macros FRAME_CHAIN, FRAME_CHAIN_VALID, and FRAME_CHAIN_COMBINE to
+ use frame info pointers as arguments instead of frame addresses.
+ * m-vax.h, m-umax.h, m-sun3.h, m-sun3.h, m-sparc.h, m-pn.h,
+ m-npl.h, m-news.h, m-merlin.h, m-isi.h, m-hp9k320.h, m-i386.h:
+ Modified definitions of the above macros to suit.
+ * m-pn.h, m-npl.h, gould-dep.c (findframe): Modified findframe to
+ use a frame info argument; also fixed internals (wouldn't work
+ before).
+
+ * m-sparc.h: Cosmetic changes; reordered some macros and made sure
+ that nothing went over 80 lines.
+
+Thu Dec 22 11:49:15 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * Version 3.0 released.
+
+ * README: Deleted note about changing -lobstack to obstack.o.
+
+Wed Dec 21 11:12:47 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-vax.h (SKIP_PROLOGUE): Now recognizes gcc prologue also.
+
+ * blockframe.c (get_prev_frame_info): Added FUNCTION_START_OFFSET
+ to result of get_pc_function_start.
+ * infrun.c (wait_for_inferior): Same.
+
+ * gdb.texinfo: Documented new "step" and "next" behavior in
+ functions without line number information.
+
+Tue Dec 20 18:00:45 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * infcmd.c (step_1): Changed behavior of "step" or "next" in a
+ function witout line number information. It now sets the step
+ range around the function (to single step out of it) using the
+ misc function vector, warns the user, and continues.
+
+ * symtab.c (find_pc_line): Zero "end" subsection of returned
+ symtab_and_line if no symtab found.
+
+Mon Dec 19 17:44:35 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * i386-pinsn.c (OP_REG): Added code from pace to streamline
+ disassembly and corrected types.
+ * i386-dep.c
+ (i386_follow_jump): Code added to follow byte and word offset
+ branches.
+ (i386_get_frame_setup): Expanded to deal with more wide ranging
+ function prologue.
+ (i386_frame_find_saved_regs, i386_skip_prologue): Changed to use
+ i386_get_frame_setup.
+
+
+Sun Dec 18 11:15:03 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h: Deleted definition of SUN4_COMPILER_BUG; was designed
+ to avoid something that I consider a bug in our code, not theirs,
+ and which I fixed earlier. Also deleted definition of
+ CANNOT_USE_ARBITRARY_FRAME; no longer used anywhere.
+ FRAME_SPECIFICATION_DYADIC used instead.
+
+ * infrun.c (wait_for_inferior): On the sun 4, if a function
+ doesn't have a prologue, a next over it single steps into it.
+ This gets around the problem of a "call .stret4" at the end of
+ functions returning structures.
+ * m-sparc.h: Defined SUN4_COMPILER_FEATURE.
+
+ * main.c (copying_info): Seperated the last printf into two
+ printfs. The 386 compiler will now handle it.
+
+ * i386-pinsn.c, i386-dep.c: Moved print_387_control_word,
+ print_387_status_word, print_387_status, and i386_float_info to
+ dep.c Also included reg.h in dep.c.
+
+Sat Dec 17 15:31:38 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * main.c (source_command): Don't close instream if it's null
+ (indicating execution of a user-defined command).
+ (execute_command): Set instream to null before executing
+ commands and setup clean stuff to put it back on error.
+
+ * inflow.c (terminal_inferior): Went back to not checking the
+ ioctl returns; there are some systems when this will simply fail.
+ It seems that, on most of these systems, nothing bad will happen
+ by that failure.
+
+ * values.c (value_static_field): Fixed dereferencing of null
+ pointer.
+
+ * i386-dep.c (i386_follow_jump): Modified to deal with
+ unconditional byte offsets also.
+
+ * dbxread.c (read_type): Fixed typo in function type case of switch.
+
+ * infcmd.c (run_command): Does not prompt to restart if command is
+ not from a tty.
+
+Fri Dec 16 15:21:58 1988 Randy Smith (randy at calvin)
+
+ * gdb.texinfo: Added a third option under the "Cannot Insert
+ Breakpoints" workarounds.
+
+ * printcmd.c (display_command): Don't do the display unless there
+ is an active inferior; only set it.
+
+ * findvar.c (value_of_register): Added an error check for calling
+ this when the inferior isn't active and a core file isn't being
+ read.
+
+ * config.gdb: Added reminder about modifying REGEX in the
+ makefile for the 386.
+
+ * i386-pinsn.c, i386-dep.c: Moved m-i386.h helper functions over
+ to i386-dep.c.b
+
+Thu Dec 15 14:04:25 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * README: Added a couple of notes about compiling gdb with itself.
+
+ * breakpoint.c (set_momentary_breakpoint): Only takes FRAME_FP of
+ frame if frame is non-zero.
+
+ * printcmd.c (print_scalar_formatted): Implemented /g size for
+ hexadecimal format on machines without an 8 byte integer type. It
+ seems to be non-trivial to implement /g for other formats.
+ (decode_format): Allowed hexadecimal format to make it through /g
+ fileter.
+
+Wed Dec 14 13:27:04 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * expread.y: Converted all calls to write_exp_elt from the parser
+ to calls to one of write_exp_elt_{opcode, sym, longcst, dblcst,
+ char, type, intern}. Created all of these routines. This gets
+ around possible problems in passing one of these things in one ear
+ and getting something different out the other. Eliminated
+ SUN4_COMPILER_BUG ifdef's; they are now superfluous.
+
+ * symmisc.c (free_all_psymtabs): Reinited partial_symtab_list to 0.
+ (_initialize_symmisc): Initialized both symtab_list and
+ partial_symtab_list.
+
+ * dbxread.c (start_psymtab): Didn't allocate anything on
+ dependency list.
+ (end_psymtab): Allocate dependency list on psymbol obstack from
+ local list.
+ (add_psymtab_dependency): Deleted.
+ (read_dbx_symtab): Put dependency on local list if it isn't on it
+ already.
+
+ * symtab.c: Added definition of psymbol_obstack.
+ * symtab.h: Added declaration of psymbol_obstack.
+ * symmisc.c (free_all_psymtabs): Added freeing and
+ reinitionaliztion of psymbol_obstack.
+ * dbxread.c (free_all_psymbols): Deleted.
+ (start_psymtab, end_psymtab,
+ process_symbol_for_psymtab): Changed most allocation
+ of partial symbol stuff to be off of psymbol_obstack.
+
+ * symmisc.c (free_psymtab, free_all_psymtabs): Deleted
+ free_psymtab subroutine.
+
+ * symtab.h: Removed num_includes and includes from partial_symtab
+ structure; no longer needed now that all include files have their
+ own psymtab.
+ * dbxread.c (start_psymtab): Eliminated initialization of above.
+ (end_psymtab): Eliminated finalization of above; get
+ includes from seperate list.
+ (read_dbx_symtab): Moved includes from psymtab list to
+ their own list; included in call to end_psymtab.
+ * symmisc.c (free_psymtab): Don't free includes.
+
+Tue Dec 13 14:48:14 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * i386-pinsn.c: Reformatted entire file to correspond to gnu
+ software indentation conventions.
+
+ * sparc-dep.c (skip_prologue): Added capability of recognizign
+ stores of input register parameters into stack slots.
+
+ * sparc-dep.c: Added an include of sparc-opcode.h.
+ * sparc-pinsn.c, sparc-opcode.h: Moved insn_fmt structures and
+ unions from pinsn.c to opcode.h.
+ * sparc-pinsn.c, sparc-dep.c (isabranch, skip_prologue): Moved
+ this function from pinsn.c to dep.c.
+
+ * Makefile: Put in warnings about compiling with gcc (non-ansi
+ include files) and compiling with shared libs on Sunos 4.0 (can't
+ debug something that's been compiled that way).
+
+ * sparc-pinsn.c: Put in a completely new file (provided by
+ Tiemann) to handle floating point disassembly, load and store
+ instructions, and etc. better. Made the modifications this file
+ (ChangeLog) list for sparc-pinsn.c again.
+
+ * symtab.c (output_source_filename): Included "more" emulation hack.
+
+ * symtab.c (output_source_filename): Initialized COLUMN to 0.
+ (sources_info): Modified to not print out a line for
+ all of the include files within a partial symtab (since
+ they have pst's of their own now). Also modified to
+ make a distinction between those pst's read in and
+ those not.
+
+ * infrun.c: Included void declaration of single_step() if it's
+ going to be used.
+ * sparc-dep.c (single_step): Moved function previous to use of it.
+
+ * Makefile: Took removal of expread.tab.c out of make clean entry
+ and put it into a new "squeakyclean" entry.
+
+Mon Dec 12 13:21:02 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * sparc-pinsn.c (skip_prologue): Changed a struct insn_fmt to a
+ union insn_fmt.
+
+ * inflow.c (terminal_inferior): Checked *all* return codes from
+ ioctl's and fcntl's in routine.
+
+ * inflow.c (terminal_inferior): Added check for sucess of
+ TIOCSPGRP ioctl call. Just notifies if bad.
+
+ * dbxread.c (symbol_file_command): Close was getting called twice;
+ once directly and once through cleanup. Killed the direct call.
+
+Sun Dec 11 19:40:40 1988 & Smith (randy at hobbes.ai.mit.edu)
+
+ * valprint.c (val_print): Deleted spurious printing of "=" from
+ TYPE_CODE_REF case.
+
+Sat Dec 10 16:41:07 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c: Changed allocation of psymbols from using malloc and
+ realloc to using obstacks. This means they aren't realloc'd out
+ from under the pointers to them.
+
+Fri Dec 9 10:33:24 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * sparc-dep.c inflow.c core.c expread.y command.c infrun.c
+ infcmd.c dbxread.c symmisc.c symtab.c printcmd.c valprint.c
+ values.c source.c stack.c findvar.c breakpoint.c blockframe.c
+ main.c: Various cleanups inspired by "gcc -Wall" (without checking
+ for implicit declarations).
+
+ * Makefile: Cleaned up some more.
+
+ * valops.c, m-*.h (FIX_CALL_DUMMY): Modified to take 5 arguments
+ as per what sparc needs (programming for a superset of needed
+ args).
+
+ * dbxread.c (process_symbol_for_psymtab): Modified to be slightly
+ more picky about what it puts on the list of things *not* to be
+ put on the misc function list. When/if I shift everything over to
+ being placed on the misc_function_list, this will go away.
+
+ * inferior.h, infrun.c: Added fields to save in inferior_status
+ structure.
+
+ * maketarfile: Deleted; functionality is in Makefile now.
+
+ * infrun.c (wait_for_inferior): Modified algorithm for determining
+ whether or not a single-step was through a subroutine call. See
+ comments at top of file.
+
+ * dbxread.c (read_dbx_symtab): Made sure that the IGNORE_SYMBOL
+ macro would be checked during initial readin.
+
+ * dbxread.c (read_ofile_symtab): Added macro GCC_COMPILED_FLAG_SYMBOL
+ into dbxread.c to indicate what string in a local text symbol will
+ indicate a file compiled with gcc. Defaults to "gcc_compiled.".
+
+Thu Dec 8 11:46:22 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h (FRAME_FIND_SAVED_REGS): Cleaned up a little to take
+ advantage of the new frame cache system.
+
+ * inferior.h, infrun.c, valops.c, valops.c, infcmd.c: Changed
+ mechanism to save inferior status over calls to inferior (eg.
+ call_function); implemented save_inferior_info and
+ restore_inferior_info.
+
+ * blockframe.c (get_prev_frame): Simplified this by a direct call
+ to get_prev_frame_info.
+
+ * frame.h, stack.c, printcmd.c, m-sparc.h, sparc-dep.c: Removed
+ all uses of frame_id_from_addr. There are short routines like it
+ still in frame_saved_pc (m-sparc.h) and parse_frame_spec
+ (stack.c). Eventually the one in frame_saved_pc will go away.
+
+ * infcmd.c, sparc-dep.c: Implemented a new mechanism for
+ re-selecting the selected frame on return from a call.
+
+ * blockframe.c, stack.c, findvar.c, printcmd.c, m-*.h: Changed
+ all routines and macros that took a "struct frame_info" as an
+ argument to take a "struct frame_info *". Routines: findarg,
+ framechain, print_frame_args, FRAME_ARGS_ADDRESS,
+ FRAME_STRUCT_ARGS_ADDRESS, FRAME_LOCALS_ADDRESS, FRAME_NUM_ARGS,
+ FRAME_FIND_SAVED_REGS.
+
+ * frame.h, stack.c, printcmd.c, infcmd.c, findvar.c, breakpoint.c,
+ blockframe.c, xgdb.c, i386-pinsn.c, gld-pinsn.c, m-umax.h,
+ m-sun2.h, m-sun3.h, m-sparc.h, m-pn.h, m-npl.h, m-news.h,
+ m-merlin.h, m-isi.h, m-i386.h, m-hp9k320.h: Changed routines to
+ use "struct frame_info *" internally.
+
+Wed Dec 7 12:07:54 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * frame.h, blockframe.c, m-sparc.h, sparc-dep.c: Changed all calls
+ to get_[prev_]frame_cache_item to get_[prev_]frame_info.
+
+ * blockframe.c: Elminated get_frame_cache_item and
+ get_prev_frame_cache_item; functionality now taken care of by
+ get_frame_info and get_prev_frame_info.
+
+ * blockframe.c: Put allocation on an obstack and eliminated fancy
+ reallocation routines, several variables, and various nasty
+ things.
+
+ * frame.h, stack.c, infrun.c, blockframe.c, sparc-dep.c: Changed
+ type FRAME to be a typedef to "struct frame_info *". Had to also
+ change routines that returned frame id's to return the pointer
+ instead of the cache index.
+
+ * infcmd.c (finish_command): Used proper method of getting from
+ function symbol to start of function. Was treating a symbol as a
+ value.
+
+ * blockframe.c, breakpoint.c, findvar.c, infcmd.c, stack.c,
+ xgdb.c, i386-pinsn.c, frame.h, m-hp9k320.h, m-i386.h, m-isi.h,
+ m-merlin.h, m-news.h, m-npl.h, m-pn.h, m-sparc.h, m-sun2.h,
+ m-sun3.h, m-umax.h: Changed get_frame_info and get_prev_frame_info
+ to return pointers instead of structures.
+
+ * blockframe.c (get_pc_function_start): Modified to go to misc
+ function table instead of bombing if pc was in a block without a
+ containing function.
+
+ * coffread.c: Dup'd descriptor passed to read_coff_symtab and
+ fdopen'd it so that there wouldn't be multiple closes on the same
+ fd. Also put (fclose, stream) on the cleanup list.
+
+ * printcmd.c, stack.c: Changed print_frame_args to take a
+ frame_info struct as argument instead of the address of the args
+ to the frame.
+
+ * m-i386.h (STORE_STRUCT_RETURN): Decremented sp by sizeof object
+ to store (an address) rather than 1.
+
+ * dbxread.c (read_dbx_symtab): Set first_object_file_end in
+ read_dbx_symtab (oops).
+
+ * coffread.c (fill_in_vptr_fieldno): Rewrote TYPE_BASECLASS as
+ necessary.
+
+Tue Dec 6 13:03:43 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * coffread.c: Added fake support for partial_symtabs to allow
+ compilation and execution without there use.
+ * inflow.c: Added a couple of minor USG mods.
+ * munch: Put in appropriate conditionals so that it would work on
+ USG systems.
+ * Makefile: Made regex.* handled same as obstack.*; made sure tar
+ file included everything I wanted it to include (including
+ malloc.c).
+
+ * dbxread.c (end_psymtab): Create an entry in the
+ partial_symtab_list for each subfile of the .o file just read in.
+ This allows a "list expread.y:10" to work when we haven't read in
+ expread.o's symbol stuff yet.
+
+ * symtab.h, dbxread.c (psymtab_to_symtab): Recognize pst->ldsymlen
+ == 0 as indicating a dummy psymtab, only in existence to cause the
+ dependency list to be read in.
+
+ * dbxread.c (sort_symtab_syms): Elminated reversal of symbols to
+ make sure that register debug symbol decls always come before
+ parameter symbols. After mod below, this is not needed.
+
+ * symtab.c (lookup_block_symbol): Take parameter type symbols
+ (LOC_ARG or LOC_REGPARM) after any other symbols which match.
+
+ * dbxread.c (read_type): When defining a type in terms of some
+ other type and the other type is supposed to have a pointer back
+ to this specific kind of type (pointer, reference, or function),
+ check to see if *that* type has been created yet. If it has, use
+ it and fill in the appropriate slot with a pointer to it.
+
+Mon Dec 5 11:25:04 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * symmisc.c: Eliminated existence of free_inclink_symtabs and
+ init_free_inclink_symtabs; they aren't called from anywhere, and
+ if they were they could disrupt gdb's data structure badly
+ (elimination of struct type's which values that stick around past
+ elimination of inclink symtabs).
+
+ * dbxread.c (symbol_file_command): Fixed a return pathway out of
+ the routine to do_cleanups before it left.
+
+ * infcmd.c (set_environment_command), gdb.texinfo: Added
+ capability to set environmental variable values to null.
+
+ * gdb.texinfo: Modified doc on "break" without args slightly.
+
+Sun Dec 4 17:03:16 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c (symbol_file_command): Added check; if there weren't
+ any debugging symbols in the file just read, the user is warned.
+
+ * infcmd.c: Commented set_environment_command (a little).
+
+ * createtags: Cleaned up and commented.
+
+ * Makefile: Updated depen_memory and write_inferior_memory in that errno is
+ checked after each ptrace and returned to the caller. Used in
+ value_at to detect references to addresses which are out of
+ bounds. Also core.c (xfer_core_file): return 1 if invalid
+ address, 0 otherwise.
+
+ * inflow.c, <machine>-infdep.c: removed all calls to ptrace from
+ inflo, m-sun3.h: Cleaned up dealings with
+ functions returning structu0 19:19:36 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * symmisc.c: (read_symsegs) Accept only format number 2. Since
+ the size of the type structure changed when C++ support was added,
+ format 1 can no longer be used.
+
+ * core.c, m-sunos4.h: (core_file_command) support for SunOS 4.0.
+ Slight change in the core structure. #ifdef SUNOS4. New file
+ m-sunos4.h. May want to change config.gdb also.
+
+Fri Jul 8 19:59:49 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * breakpoint.c: (break_command_1) Allow `break if condition'
+ rather than parsing `if' as a function name and returning an
+ error.
+
+Thu Jul 7 22:22:47 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: valops.c, valprint.c, value.h, values.c: merged code to deal
+ with C++ expressions.
+
+Wed Jul 6 03:28:18 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: dbxread.c: (read_dbx_symtab, condense_misc_bunches,
+ add_file_command) Merged code to read symbol information from
+ an incrementally linked file. symmisc.c:
+ (init_free_inclink_symtabs, free_inclink_symtabs) Cleanup
+ routines.
+
+Tue Jul 5 02:50:41 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: symtab.c, breakpoint.c, source.c: Merged code to deal with
+ ambiguous line specifications. In C++ one can have overloaded
+ function names, so that `list classname::overloadedfuncname'
+ refers to several different lines, possibly sure currently configured machine
+ dependent files come first in e at corn-chex.ai.mit.edu)
+
+ * C++: symtab.c: replaced lookup_symtab_1 and lookup_symtab_2 with
+ a modified lookup_symbol which checks for fields of the current
+ implied argument `this'. printcmd.c, source.c, symtab.c,
+ valops.c: Need to change callers once callers are
+ installed.
+
+Wed Jun 29 01:26:56 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu)
+
+ * C++: eval.c, expprint.c, expread.y, expression.h, valarith.c,
+ Merged code to deal with evaluation of user-defined operators,
+ member functions, and virtual functions.
+ binop_must_be_user_defined tests for user-defined binops,
+ value_x_binop calls the appropriate operator function.
+
+Tue Jun 28 02:56:42 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu)
+
+ * C++: Makefile: changed the echo: expect 101 shift/reduce conflicts
+ and 1 reduce/reduce conflict.
+
+
+Local Variables:
+mode: indented-text
+eval: (auto-fill-mode 1)
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
+
+ constructors, and flags being defined via public and via
+ virtual paths. Added fields NEXT_VARIANT, N_BASECLASSES,
+ and BASECLASSES to this type (tr: Changed types from
+ having to be derived from a single baseclass to a multiple
+ base class).
+ * symtab.h: Added macros to access new fields defined in symseg.h.
+ Added decl for lookup_basetype_type.
+ * dbxread.c
+ (condense_addl_misc_bunches): Function added to condense the misc
+ function bunches added by reading in a new .o file.
+ (read_addl_syms): Function added to read in symbols
+ from a new .o file (incremental linking).
+ (add_file_command): Command interface function to indicate
+ incrmental linking of a new .o file; this now calls
+ read_addl_syms and condense_addl_misc_bunches.
+ (define_symbol): Modified code to handle types defined from base
+ types which were not known when the derived class was
+ output.
+ (read_struct_type): Modified to better handle description of
+ struct types as derived types. Possibly derived from
+ several different base classes. Also added new code to
+ mark definitions via virtual paths or via public paths.
+ Killed seperate code to handle classes with destructors
+ but without constructors and improved marking of classes
+ as having destructors and constructors.
+ * infcmd.c: Modified call to val_print (one more argument).
+ * symtab.c (lookup_member_type): Modified to deal with new
+ structure in symseg.h.
+ (lookup_basetype_type): Function added to find or construct a type
+ ?derived? from the given type.
+ (decode_line_1): Modified to deal with new type data structures.
+ Modified to deal with new number of args for
+ decode_line_2.
+ (decode_line_2): Changed number of args (?why?).
+ (init_type): Added inits for new C++ fields from
+ symseg.h.
+ *valarith.c
+ (value_x_binop, value_binop): Added cases for BINOP_MIN &
+ BINOP_MAX.
+ * valops.c
+ (value_struct_elt, check_field, value_struct_elt_for_address):
+ Changed to deal with multiple possible baseclasses.
+ (value_of_this): Made SELECTED_FRAME an extern variable.
+ * valprint.c
+ (val_print): Added an argument DEREF_REF to dereference references
+ automatically, instead of printing them like pointers.
+ Changed number of arguments in recursive calls to itself.
+ Changed to deal with varibale numbers of base classes.
+ (value_print): Changed number of arguments to val_print. Print
+ type of value also if value is a reference.
+ (type_print_derivation_info): Added function to print out
+ derivation info a a type.
+ (type_print_base): Modified to use type_print_derivation_info and
+ to handle multiple baseclasses.
+
+Mon Nov 21 10:32:07 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * inflow.c (term_status_command): Add trailing newline to output.
+
+ * sparc-dep.c (do_save_insn, do_restore_insn): Saved
+ "stop_registers" over the call for the sake of normal_stop and
+ run_stack_dummy.
+
+ * m-sparc.h (EXTRACT_RETURN_VALUE): Put in parenthesis to force
+ addition of 8 to the int pointer, not the char pointer.
+
+ * sparc-pinsn.c (print_addr1): Believe that I have gotten the
+ syntax right for loads and stores as adb does it.
+
+ * symtab.c (list_symbols): Turned search for match on rexegp into
+ a single loop.
+
+ * dbxread.c (psymtab_to_symtab): Don't read it in if it's already
+ been read in.
+
+ * dbxread.c (psymtab_to_symtab): Changed error to fatal in
+ psymtab_to_symtab.
+
+ * expread.y (parse_number): Fixed bug which treated 'l' at end of
+ number as '0'.
+
+Fri Nov 18 13:57:33 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Was
+ being foolish and using pointers into an array I could realloc.
+ Converted these pointers into integers.
+
+Wed Nov 16 11:43:10 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h (POP_FRAME): Made the new frame be PC_ADJUST of the
+ old frame.
+
+ * i386-pinsn.c, m-hp9k320.h, m-isi.h, m-merlin.h, m-news.h,
+ m-npl.h, m-pn.h, m-sparc.h, m-sun2.h, m-sun3.h, m-umax.h, m-vax.h:
+ Modified POP_FRAME to use the current frame instead of
+ read_register (FP_REGNUM) and to flush_cached_frames before
+ setting the current frame. Also added a call to set the current
+ frame in those POP_FRAMEs that didn't have it.
+
+ * infrun.c (wait_for_inferior): Moved call to set_current_frame up
+ to guarrantee that the current frame will always be set when a
+ POP_FRAME is done.
+
+ * infrun.c (normal_stop): Added something to reset the pc of the
+ current frame (was incorrect because of DECR_PC_AFTER_BREAK).
+
+ * valprint.c (val_print): Changed to check to see if a string was
+ out of bounds when being printed and to indicate this if so.
+
+ * convex-dep.c (read_inferior_memory): Changed to return the value
+ of errno if the call failed (which will be 0 if the call
+ suceeded).
+
+Tue Nov 15 10:17:15 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * infrun.c (wait_for_inferior): Two changes: 1) Added code to
+ not trigger the step breakpoint on recursive calls to functions
+ without frame info, and 2) Added calls to distinguish recursive
+ calls within a function without a frame (which next/nexti might
+ wish to step over) from jumps to the beginning of a function
+ (which it generally doesn't).
+
+ * m-sparc.h (INIT_EXTRA_FRAME_INFO): Bottom set correctly for leaf
+ parents.
+
+ * blockframe.c (get_prev_frame_cache_item): Put in mod to check
+ for a leaf node (by presence or lack of function prologue). If
+ there is a leaf node, it is assumed that SAVED_PC_AFTER_CALL is
+ valid. Otherwise, FRAME_SAVED_PC or read_pc is used.
+
+ * blockframe.c, frame.h: Did final deletion of unused routines and
+ commented problems with getting a pointer into the frame cache in
+ the frame_info structure comment.
+
+ * blockframe.c, frame.h, stack.c: Killed use of
+ frame_id_from_frame_info; used frame_id_from_addr instead.
+
+ * blockframe.c, frame.h, stack.c, others (oops): Combined stack
+ cache and frame info structures.
+
+ * blockframe.c, sparc-dep.c, stack.c: Created the function
+ create_new_frame and used it in place of bad calls to
+ frame_id_from_addr.
+
+ * blockframe.c, inflow.c, infrun.c, i386-pinsn.c, m-hp9k320.h,
+ m-npl.h, m-pn.h, m-sparc.h, m-sun3.h, m-vax.h, default-dep.c,
+ convex-dep.c, gould-dep.c, hp9k320-dep.c, news-dep.c, sparc-dep.c,
+ sun3-dep.c, umax-dep.c: Killed use of
+ set_current_Frame_by_address. Used set_current_frame
+ (create_new_frame...) instead.
+
+ * frame.h: Killed use of FRAME_FP_ID.
+
+ * infrun.c, blockframe.c: Killed select_frame_by_address. Used
+ select_frame (get_current_frame (), 0) (which was correct in all
+ cases that we need to worry about.
+
+Mon Nov 14 14:19:32 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * frame.h, blockframe.c, stack.c, m-sparc.h, sparc-dep.c: Added
+ mechanisms to deal with possible specification of frames
+ dyadically.
+
+Sun Nov 13 16:03:32 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ns32k-opcode.h: Add insns acbw, acbd.
+
+Sun Nov 13 15:09:58 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * breakpoint.c: Changed breakpoint structure to use the address of
+ a given frame (constant across inferior runs) as the criteria for
+ stopping instead of the frame ident (which varies across inferior
+ calls).
+
+Fri Nov 11 13:00:22 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * gld-pinsn.c (findframe): Modified to work with the new frame
+ id's. Actually, it looks as if this routine should be called with
+ an address anyway.
+
+ * findvar.c (find_saved_register): Altered bactrace loop to work
+ off of frames and not frame infos.
+
+ * frame.h, blockframe.c, stack.c, sparc-dep.c, m-sparc.h: Changed
+ FRAME from being the address of the frame to being a simple ident
+ which is an index into the frame_cache_item list.
+ * convex-dep.c, default-dep.c, gould-dep.c, hp9k320-dep.c,
+ i386-pinsn.c, inflow.c, infrun.c, news-dep.c, sparc-dep.c,
+ sun3-dep.c, umax-dep.c, m-hp9k320.h, m-npl.h, m-pn.h, m-sparc.h,
+ m-sun3.h, m-vax.h: Changed calls of the form set_current_frame
+ (read_register (FP_REGNUM)) to set_current_frame_by_address (...).
+
+Thu Nov 10 16:57:57 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * frame.h, blockframe.c, gld-pinsn.c, sparc-dep.c, stack.c,
+ infrun.c, findvar.c, m-sparc.h: Changed the FRAME type to be
+ purely an identifier, using FRAME_FP and FRAME_FP_ID to convert
+ back and forth between the two. The identifier is *currently*
+ still the frame pointer value for that frame.
+
+Wed Nov 9 17:28:14 1988 Chris Hanson (cph at kleph)
+
+ * m-hp9k320.h (FP_REGISTER_ADDR): Redefine this to return
+ difference between address of given FP register, and beginning of
+ `struct user' that it occurs in.
+
+ * hp9k320-dep.c (core_file_command): Fix sign error in size
+ argument to myread. Change buffer argument to pointer; was
+ copying entire structure.
+ (fetch_inferior_registers, store_inferior_registers): Replace
+ occurrences of `FP_REGISTER_ADDR_DIFF' with `FP_REGISTER_ADDR'.
+ Flush former definition.
+
+Wed Nov 9 12:11:37 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * xgdb.c: Killed include of initialize.h.
+
+ * Pulled in xgdb.c from the net.
+
+ * Checkpointed distribution (to provide to 3b2 guy).
+
+ * coffread.c, dbxread.c, symmisc.c, symtab.c, symseg.h: Changed
+ format of table of line number--pc mapping information. Can
+ handle negative pc's now.
+
+ * command.c: Deleted local copy of savestring; code in utils.c is
+ identical.
+
+Tue Nov 8 11:12:16 1988 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * gdb.texinfo: Added documentation for shell escape.
+
+Mon Nov 7 12:27:16 1988 Randall Smith (randy at sugar-bombs.ai.mit.edu)
+
+ * command.c: Added commands for shell escape.
+
+ * core.c, dbxread.c: Added ROBOTUSSIN mods.
+
+ * Checkpointed distribution.
+
+ * printcmd.c (x_command): Yanked error if there is no memory to
+ examine (could be looking at executable straight).
+
+ * sparc-pinsn.c (print_insn): Amount to leftshift sethi imm by is
+ now 10 (matches adb in output).
+
+ * printcmd.c (x_command): Don't attempt to set $_ & $__ if there
+ is no last_examine_value (can happen if you did an x/0).
+
+Fri Nov 4 13:44:49 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * printcmd.c (x_command): Error if there is no memory to examine.
+
+ * gdb.texinfo: Added "cont" to the command index.
+
+ * sparc-dep.c (do_save_insn): Fixed typo in shift amount.
+
+ * m68k-opcode.h: Fixed opcodes for 68881.
+
+ * breakpoint.c, infcmd.c, source.c: Changed defaults in several
+ places for decode_line_1 to work off of the default_breakpoint_*
+ values instead of current_source_* values (the current_source_*
+ values are off by 5 or so because of listing defaults).
+
+ * stack.c (frame_info): ifdef'd out FRAME_SPECIFCATION_DYADIC in
+ the stack.c module. If I can't do this right, I don't want to do
+ it at all. Read the comment there for more info.
+
+Mon Oct 31 16:23:06 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * gdb.texinfo: Added documentation on the "until" command.
+
+Sat Oct 29 17:47:10 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * breakpoint.c, infcmd.c: Added UNTIL_COMMAND and subroutines of
+ it.
+
+ * breakpoint.c, infcmd.c, infrun.c: Added new field to breakpoint
+ structure (silent, indicating a silent breakpoint), and modified
+ breakpoint_stop_status and things that read it's return value to
+ understand it.
+
+Fri Oct 28 17:45:33 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c, symmisc.c: Assorted speedups for readin, including
+ special casing most common symbols, and doing buffering instead of
+ calling malloc.
+
+Thu Oct 27 11:11:15 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * stack.c, sparc-dep.c, m-sparc.h: Modified to allow "info frame"
+ to take two arguments on the sparc and do the right thing with
+ them.
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Put
+ stuff to put only symbols that didn't have debugging info on the
+ misc functions list back in.
+
+Wed Oct 26 10:10:32 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * valprint.c (type_print_varspec_suffix): Added check for
+ TYPE_LENGTH(TYPE_TARGET_TYPE(type)) > 0 to prevent divide by 0.
+
+ * printcmd.c (print_formatted): Added check for VALUE_REPEATED;
+ value_print needs to be called for that.
+
+ * infrun.c (wait_for_inferior): Added break when you decide to
+ stop on a null function prologue rather than continue stepping.
+
+ * m-sun3.h: Added explanatory comment to REGISTER_RAW_SIZE.
+
+ * expread.y (parse_c_1): Initialized paren_depth for each parse.
+
+Tue Oct 25 14:19:38 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * valprint.c, coffread.c, dbxread.c: Enum constant values in enum
+ type now accessed through TYPE_FIELD_BITPOS.
+
+ * dbxread.c (process_symbol_for_psymtab): Added code to deal with
+ possible lack of a ":" in a debugging symbol (do nothing).
+
+ * symtab.c (decode_line_1): Added check in case of all numbers for
+ complete lack of symbols.
+
+ * source.c (select_source_symtab): Made sure that this wouldn't
+ bomb on complete lack of symbols.
+
+Mon Oct 24 12:28:29 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h, findvar.c: Ditched REGISTER_SAVED_UNIQUELY and based
+ code on REGISTER_IN_WINDOW_P and HAVE_REGISTER_WINDOWS. This will
+ break when we find a register window machine which saves the
+ window registers within the context of an inferior frame.
+
+ * sparc-dep.c (frame_saved_pc): Put PC_ADJUST return back in for
+ frame_saved_pc. Seems correct.
+
+ * findvar.c, m-sparc.h: Created the macro REGISTER_SAVED_UNIQUELY
+ to handle register window issues (ie. that find_saved_register
+ wasn't checking the selected frame itself for shit).
+
+ * sparc-dep.c (core_file_command): Offset target of o & g register
+ bcopy by 1 to hit correct registers.
+
+ * m-sparc.h: Changed STACK_END_ADDR.
+
+Sun Oct 23 19:41:51 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * sparc-dep.c (core_file_command): Added in code to get the i & l
+ registers from the stack in the corefile, and blew away some wrong
+ code to get i & l from inferior.
+
+Fri Oct 21 15:09:19 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h (PUSH_DUMMY_FRAME): Saved the value of the RP register
+ in the location reserved for i7 (in the created frame); this way
+ the rp value won't get lost. The pc (what we put into the rp in
+ this routine) gets saved seperately, so we loose no information.
+
+ * sparc-dep.c (do_save_insn & do_restore_insn): Added a wrapper to
+ preserve the proceed status state variables around each call to
+ proceed (the current frame was getting munged because this wasn't
+ being done).
+
+ * m-sparc.h (FRAME_FIND_SAVED_REGS): Fix bug: saved registers
+ addresses were being computed using absolute registers number,
+ rather than numbers relative to each group of regs.
+
+ * m-sparc.h (POP_FRAME): Fixed a bug (I hope) in the context
+ within which saved reg numbers were being interpetted. The
+ values to be restored were being gotten in the inferior frame, and
+ the restoring was done in the superior frame. This means that i
+ registers must be restored into o registers.
+
+ * sparc-dep.c (do_restore_insn): Modified to take a pc as an
+ argument, instead of a raw_buffer. This matches (at least it
+ appears to match) usage from POP_FRAME, which is the only place
+ from which do_restore_insn is called.
+
+ * sparc-dep.c (do_save_insn and do_restore_insn): Added comments.
+
+ * m-sparc.h (FRAME_FIND_SAVED_REGS): Modified my code to find the
+ save addresses of out registers to use the in regs off the stack
+ pointer when the current frame is 1 from the innermost.
+
+Thu Oct 20 13:56:15 1988 & Smith (randy at hobbes.ai.mit.edu)
+
+ * blockframe.c, m-sparc.h: Removed code associated with
+ GET_PREV_FRAME_FROM_CACHE_ITEM. This code was not needed for the
+ sparc; you can always find the previous frames fp from the fp of
+ the current frame (which is the sp of the previous). It's getting
+ the information associated with a given frame (ie. saved
+ registers) that's a bitch, because that stuff is saved relative to
+ the stack pointer rather than the frame pointer.
+
+ * m-sparc.h (GET_PREV_FRAME_FROM_CACHE_ITEM): Modified to return
+ the frame pointer of the previous frame instead of the stack
+ pointer of same.
+
+ * blockframe.c (flush_cached_frames): Modified call to
+ obstack_free to free back to frame_cache instead of back to zero.
+ This leaves the obstack control structure in finite state (and
+ still frees the entry allocated at frame_cache).
+
+Sat Oct 15 16:30:47 1988 & Smith (randy at tartarus.uchicago.edu)
+
+ * valops.c (call_function): Suicide material here. Fixed a typo;
+ CALL_DUMMY_STACK_ADJUST was spelled CAll_DUMMY_STACK_ADJUST on
+ line 530 of the file. This cost me three days. I'm giving up
+ typing for lent.
+
+Fri Oct 14 15:10:43 1988 & Smith (randy at tartarus.uchicago.edu)
+
+ * m-sparc.h: Corrected a minor mistake in the dummy frame code
+ that was getting the 5th argument and the first argument from the
+ same place.
+
+Tue Oct 11 11:49:33 1988 & Smith (randy at tartarus.uchicago.edu)
+
+ * infrun.c: Made stop_after_trap and stop_after_attach extern
+ instead of static so that code which used proceed from machine
+ dependent files could fiddle with them.
+
+ * blockframe.c, frame.h, sparc-dep.c, m-sparc.h: Changed sense of
+ ->prev and ->next in struct frame_cache_item to fit usage in rest
+ of gdb (oops).
+
+Mon Oct 10 15:32:42 1988 Randy Smith (randy at gargoyle.uchicago.edu)
+
+ * m-sparc.h, sparc-dep.c, blockframe.c, frame.h: Wrote
+ get_frame_cache_item. Modified FRAME_SAVED_PC and frame_saved_pc
+ to take only one argument and do the correct thing with it. Added
+ the two macros I recently defined in blockframe.c to m-sparc.h.
+ Have yet to compile this thing on a sparc, but I've now merged in
+ everything that I received from tiemann, either exactly, or simply
+ effectively.
+
+ * source.c: Added code to allocated space to sals.sals in the case
+ where no line was specified.
+
+ * blockframe.c, infrun.c: Modified to cache stack frames requested
+ to minimize accesses to subprocess.
+
+Tue Oct 4 15:10:39 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * config.gdb: Added sparc.
+
+Mon Oct 3 23:01:22 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * Makefile, blockframe.c, command.c, core.c, dbxread.c, defs.h,
+ expread.y, findvar.c, infcmd.c, inflow.c, infrun.c, sparc-pinsn.c,
+ m-sparc.h, sparc-def.c, printcmd.c, stack.c, symmisc.c, symseg.h,
+ valops.c, values.c: Did initial merge of sparc port. This will
+ not compile; have to do stack frame caching and finish port.
+
+ * inflow.c, gdb.texinfo: `tty' now resets the controling terminal.
+
+Fri Sep 30 11:31:16 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * inferior.h, infcmd.c, infrun.c: Changed the variable
+ stop_random_signal to stopped_by_random signal to fit in better
+ with name conventions (variable is not a direction to the
+ proceed/resume set; it is information from it).
+
+Thu Sep 29 13:30:46 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * infcmd.c (finish_command): Value type of return value is now
+ whatever the function returns, not the type of the function (fixed
+ a bug in printing said value).
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab):
+ Put *all* global symbols into misc_functions. This is what was
+ happening anyway, and we need it for find_pc_misc_function.
+
+ ** This was eventually taken out, but I didn't mark it in the
+ ChangeLog. Oops.
+
+ * dbxread.c (process_symbol_for_psymtab): Put every debugger
+ symbol which survives the top case except for constants on the
+ symchain. This means that all of these *won't* show up in misc
+ functions (this will be fixed once I make sure it's broken the way
+ it's supposed to be).
+
+ * dbxread.c: Modified placement of debugger globals onto the hash
+ list; now we exclude the stuff after the colon and don't skip the
+ first character (debugger symbols don't have underscores).
+
+ * dbxread.c: Killed debuginfo stuff with ifdef's.
+
+Wed Sep 28 14:31:51 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * symtab.h, dbxread.c: Modified to deal with BINCL, EINCL, and
+ EXCL symbols produced by the sun loader by adding a list of
+ pre-requisite partial_symtabs that each partial symtab needs.
+
+ * symtab.h, dbxread.c, symtab.c, symmisc.c: Modified to avoid
+ doing a qsort on the local (static) psymbols for each file to
+ speed startup. This feature is not completely debugged, but it's
+ inclusion has forced the inclusion of another feature (dealing
+ with EINCL's, BINCL's and EXCL's) and so I'm going to go in and
+ deal with them.
+
+ * dbxread.c (process_symbol_for_psymtab): Made sure that the class
+ of the symbol made it into the partial_symbol entry.
+
+Tue Sep 27 15:10:26 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c: Fixed bug; init_psymbol_list was not being called
+ with the right number of arguments (1).
+
+ * dbxread.c: Put ifdef's around N_MAIN, N_M2C, and N_SCOPE to
+ allow compilation on a microvax.
+
+ * config.gdb: Modified so that "config.gdb vax" would work.
+
+ * dbxread.c, symtab.h, symmisc.h, symtab.c, source.c: Put in many
+ and varied hacks to speed up gdb startup including: A complete
+ rewrite of read_dbx_symtab, a modification of the partial_symtab
+ data type, deletion of select_source_symtab from
+ symbol_file_command, and optimiztion of the call to strcmp in
+ compare_psymbols.
+
+Thu Sep 22 11:08:54 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c (psymtab_to_symtab): Removed call to
+ init_misc_functions.
+
+ * dbxread.c: Fixed enumeration type clash (used enum instead of
+ integer constant).
+
+ * breakpoint.c: Fixed typo; lack of \ at end of line in middle of
+ string constant.
+
+ * symseg.h: Fixed typo; lack of semicolon after structure
+ definition.
+
+ * command.c, breakpoint.c, printcmd.c: Added cmdlist editing
+ functions to add commands with the abbrev flag set. Changed
+ help_cmd_list to recognize this flag and modified unset,
+ undisplay, and enable, disable, and delete breakpoints to have
+ this flag set.
+
+Wed Sep 21 13:34:19 1988 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * breakpoint.c, infcmd.c, gdb.texinfo: Created "unset" as an alias
+ for delete, and changed "unset-environment" to be the
+ "environment" subcommand of "delete".
+
+ * gdb.texinfo, valprint.c: Added documentation in the manual for
+ breaking the set-* commands into subcommands of set. Changed "set
+ maximum" to "set array-max".
+
+ * main.c, printcmd.c, breakpoint.c: Moved the declaration of
+ command lists into main and setup a function in main initializing
+ them to guarrantee that they would be initialized before calling
+ any of the individual files initialize routines.
+
+ * command.c (lookup_cmd): A null string subcommand is treated as
+ an unknown subcommand rather than an ambiguous one (eg. "set $x =
+ 1" will now work).
+
+ * infrun.c (wait_for_inferior): Put in ifdef for Sony News in
+ check for trap by INNER_THAN macro.
+
+ * eval.c (evaluate_subexp): Put in catch to keep the user from
+ attempting to call a non function as a function.
+
+Tue Sep 20 10:35:53 1988 Randall Smith (randy at oatmeal.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Installed code to keep track of
+ which global symbols did not have debugger symbols refering to
+ them, and recording these via record_misc_function.
+
+ * dbxread.c: Killed code to check for extra global symbols in the
+ debugger symbol table.
+
+ * printcmd.c, breakpoint.c: Modified help entries for several
+ commands to make sure that abbreviations were clearly marked and
+ that the right commands showed up in the help listings.
+
+ * main.c, command.c, breakpoint.c, infcmd.c, printcmd.c,
+ valprint.c, defs.h: Modified help system to allow help on a class
+ name to show subcommands as well as commands and help on a command
+ to show *all* subcommands of that command.
+
+Fri Sep 16 16:51:19 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * breakpoint.c (_initialize_breakpoint): Made "breakpoints"
+ subcommands of enable, disable, and delete use class 0 (ie. they
+ show up when you do a help xxx now).
+
+ * infcmd.c,printcmd,c,main.c,valprint.c: Changed the set-*
+ commands into subcommands of set. Created "set variable" for use
+ with variables whose names might conflict with other subcommands.
+
+ * blockframe.c, dbxread.c, coffread.c, expread.y, source.c:
+ Fixed mostly minor (and one major one in block_for_pc) bugs
+ involving checking the partial_symtab_list when a scan through the
+ symtab_list fails.
+
+Wed Sep 14 12:02:05 1988 Randall Smith (randy at sugar-smacks.ai.mit.edu)
+
+ * breakpoint.c, gdb.texinfo: Added enable breakpoints, disable
+ breakpoints and delete breakpoints as synonyms for enable,
+ disable, and delete. This seemed reasonable because of the
+ immeninent arrival of watchpoints & etc.
+
+ * gdb.texinfo: Added enable display, disable display, and delete
+ display to manual.
+
+Tue Sep 13 16:53:56 1988 Randall Smith (randy at sugar-smacks.ai.mit.edu)
+
+ * inferior.h, infrun.c, infcmd.c: Added variable
+ stop_random_signal to indicate when a proceed had been stopped by
+ an unexpected signal. Used this to determine (in normal_stop)
+ whether the current display point should be deleted.
+
+ * valops.c: Fix to value_ind to check for reference before doing a
+ COERCE_ARRAY.
+
+Sun Jul 31 11:42:36 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * breakpoint.c (_initialize_breakpoint): Clean up doc for commands
+ that can now apply also to auto-displays.
+
+ * coffread.c (record_line): Corrected a spazz in editing.
+ Also removed the two lines that assume line-numbers appear
+ only in increasing order.
+
+Tue Jul 26 22:19:06 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * expression.h, eval.c, expprint.c, printcmd.c, valarith.c,
+ valops.c, valprint.c, values.c, m-*.h: Changes for evaluating and
+ displaying 64-bit `long long' integers. Each machine must define
+ a LONGEST type, and a BUILTIN_TYPE_LONGEST.
+
+ * symmisc.c: (print_symtab) check the status of the fopen and call
+ perror_with_name if needed.
+
+Thu Jul 21 00:56:11 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * Convex: core.c: changes required by Convex's SOFF format were
+ isolated in convex-dep.c.
+
+Wed Jul 20 21:26:10 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * coffread.c, core.c, expread.y, i386-pinsn.c, infcmd.c, inflow.c,
+ infrun.c, m-i386.h, main.c, remote.c, source.c, valops.c:
+ Improvements for the handling of the i386 and other machines
+ running USG. (Several of these files just needed extra header files
+ such as types.h.) utils.c: added bcopy, bcmp, bzero, getwd, list
+ of signals, and queue routines for USG systems. Added vfork macro
+ to i386
+
+ * printcmd.c, breakpoint.c: New commands to enable/disable
+ auto-displays. Also `delete display displaynumber' works like
+ `undisplay displaynumber'.
+
+Tue Jul 19 02:17:18 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * coffread.c: (coff_lookup_type) Wrong portion of type_vector was
+ being bzero'd after type_vector was reallocated.
+
+ * printcmd.c: (delete_display) Check for a display chain before
+ attempting to delete a display.
+
+ * core.c, *-dep.c (*-infdep moved to *-dep): machine-dependent
+ parts of core.c (core_file_command, exec_file_command) moved to
+ *-dep.c.
+
+Mon Jul 18 19:45:51 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * dbxread.c: typo in read_struct_type (missing '=') was causing a
+ C struct to be parsed as a C++ struct, resulting in a `invalid
+ character' message.
+
+Sun Jul 17 22:27:32 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * printcmd.c, symtab.c, valops.c, expread.y: When an expression is
+ read, the innermost block required to evaluate the expression is
+ saved in the global variable `innermost_block'. This information
+ is saved in the `block' field of an auto-display so that
+ expressions with inactive variables can be skipped. `info display'
+ tells the user which displays are active and which are not. New
+ fn `contained_in' returns nonzero if one block is contained within
+ another.
+
+Fri Jul 15 01:53:14 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * infrun.c, m-i386.h: Use macro TRAPS_EXPECTED to set number of
+ traps to skip when sh execs the program. Default is 2, m-i386.h
+ overrides this and sets to 4.
+
+ * coffread.c, infrun.c: minor changes for the i386. May be able
+ to eliminate them with more general code.
+
+ * default-infdep.c: #ifdef SYSTEMV, include header file types.h.
+ Also switched the order of signal.h and user.h, since System 5
+ requires signal.h to come first.
+
+ * core.c main.c, remote,c, source.c, inflow.c: #ifdef SYSTEMV,
+ include various header files. Usually types.h and fcntl.h.
+
+ * utils.c: added queue routines needed by the i386 (and other sys
+ 5 machines).
+
+ * sys5.c, regex.c, regex.h: new files for sys 5 systems. (The
+ regex files are simply links to /gp/gnu/lib.)
+
+Thu Jul 14 01:47:14 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * config.gdb, README: Provide a list of known machines when user
+ enters an invalid machine. New second arg is operating system,
+ currently only used with `sunos4' or `os4'. Entry for i386 added.
+
+ * news-infdep.c: new file.
+
+ * m-news.h: new version which deals with new bugs in news800's OS.
+
+Tue Jul 12 19:52:16 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * Makefile, *.c, munch, config.gdb, README: New initialization
+ scheme uses nm to find functions whose names begin with
+ `_initialize_'. Files `initialize.h', `firstfile.c',
+ `lastfile.c', `m-*init.h' no longer needed.
+
+ * eval.c, symtab.c, valarith.c, valops.c, value.h, values.c: Bug
+ fixes from gdb+ 2.5.4. evaluate_subexp takes a new arg, type
+ expected. New fn value_virtual_fn_field.
+
+Mon Jul 11 00:48:49 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * core.c (read_memory): xfer_core_file was being called with an
+ extra argument (0) by read_memory.
+
+ * core.c (read_memory), *-infdep.c (read_inferior_memory),
+ valops.c (value_at): read_memory and read_inferior_memory now work
+ like write_memory and write_inferior_memory in that errno is
+ checked after each ptrace and returned to the caller. Used in
+ value_at to detect references to addresses which are out of
+ bounds. Also core.c (xfer_core_file): return 1 if invalid
+ address, 0 otherwise.
+
+ * inflow.c, <machine>-infdep.c: removed all calls to ptrace from
+ inflow.c and put them in machine-dependent files *-infdep.c.
+
+Sun Jul 10 19:19:36 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * symmisc.c: (read_symsegs) Accept only format number 2. Since
+ the size of the type structure changed when C++ support was added,
+ format 1 can no longer be used.
+
+ * core.c, m-sunos4.h: (core_file_command) support for SunOS 4.0.
+ Slight change in the core structure. #ifdef SUNOS4. New file
+ m-sunos4.h. May want to change config.gdb also.
+
+Fri Jul 8 19:59:49 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * breakpoint.c: (break_command_1) Allow `break if condition'
+ rather than parsing `if' as a function name and returning an
+ error.
+
+Thu Jul 7 22:22:47 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: valops.c, valprint.c, value.h, values.c: merged code to deal
+ with C++ expressions.
+
+Wed Jul 6 03:28:18 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: dbxread.c: (read_dbx_symtab, condense_misc_bunches,
+ add_file_command) Merged code to read symbol information from
+ an incrementally linked file. symmisc.c:
+ (init_free_inclink_symtabs, free_inclink_symtabs) Cleanup
+ routines.
+
+Tue Jul 5 02:50:41 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: symtab.c, breakpoint.c, source.c: Merged code to deal with
+ ambiguous line specifications. In C++ one can have overloaded
+ function names, so that `list classname::overloadedfuncname'
+ refers to several different lines, possibly in different files.
+
+Fri Jul 1 02:44:20 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: symtab.c: replaced lookup_symtab_1 and lookup_symtab_2 with
+ a modified lookup_symbol which checks for fields of the current
+ implied argument `this'. printcmd.c, source.c, symtab.c,
+ valops.c: Need to change callers once callers are
+ installed.
+
+Wed Jun 29 01:26:56 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu)
+
+ * C++: eval.c, expprint.c, expread.y, expression.h, valarith.c,
+ Merged code to deal with evaluation of user-defined operators,
+ member functions, and virtual functions.
+ binop_must_be_user_defined tests for user-defined binops,
+ value_x_binop calls the appropriate operator function.
+
+Tue Jun 28 02:56:42 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu)
+
+ * C++: Makefile: changed the echo: expect 101 shift/reduce conflicts
+ and 1 reduce/reduce conflict.
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gnu/usr.bin/kgdb/Gdbinit b/gnu/usr.bin/kgdb/Gdbinit
new file mode 100644
index 000000000000..bcacd5dc7e84
--- /dev/null
+++ b/gnu/usr.bin/kgdb/Gdbinit
@@ -0,0 +1,15 @@
+echo Setting up the environment for debugging gdb.\n
+
+b fatal
+
+b info_command
+commands
+ silent
+ return
+end
+
+define rr
+ run
+end
+
+set prompt (top-gdb)
diff --git a/gnu/usr.bin/kgdb/Makefile b/gnu/usr.bin/kgdb/Makefile
new file mode 100644
index 000000000000..0c2380e5accc
--- /dev/null
+++ b/gnu/usr.bin/kgdb/Makefile
@@ -0,0 +1,34 @@
+# @(#)Makefile 6.4 (Berkley) 5/6/91
+
+PROG= kgdb
+GDBSRCS= blockframe.c breakpoint.c command.c copying.c core.c \
+ cplus-dem.c dbxread.c environ.c eval.c expprint.c \
+ expread.y findvar.c infcmd.c inflow.c infrun.c \
+ main.c obstack.c printcmd.c regex.c remote.c \
+ remote-sl.c source.c stack.c symmisc.c symtab.c \
+ utils.c valarith.c valops.c valprint.c values.c \
+ version.c
+SRCS= $(CONFIGSRCS) $(GDBSRCS) init.c
+CFLAGS+= -I. -I$(.CURDIR) -I$(.CURDIR)/config \
+ -DHAVE_VPRINTF -DKERNELDEBUG -DNEWVM
+DPADD+= ${LIBREADLINE} ${LIBTERMCAP}
+LDADD+= -lreadline -ltermcap
+YFLAGS=
+.PATH: $(.CURDIR)/config
+
+.include "config/Makefile.$(MACHINE)"
+.include <bsd.prog.mk>
+
+$(OBJS): param.h
+
+#
+# Generate the constructor
+#
+init.c: $(CONFIGSRCS) $(GDBSRCS) $(READLINESRCS) param.h
+ -((cd $(.CURDIR)/config; \
+ egrep -h '^_initialize_[^ ]* *\(\)' $(CONFIGSRCS)); \
+ (cd $(.CURDIR); egrep -h '^_initialize_[^ ]* *\(\)' $(GDBSRCS))) | \
+ (echo 'void initialize_all_files () {'; sed -e 's/$$/;/'; echo '}') \
+ > init.c
+
+CLEANFILES+= init.c param.h
diff --git a/gnu/usr.bin/kgdb/Makefile.dist b/gnu/usr.bin/kgdb/Makefile.dist
new file mode 100644
index 000000000000..3cbc91f9786f
--- /dev/null
+++ b/gnu/usr.bin/kgdb/Makefile.dist
@@ -0,0 +1,371 @@
+/* This file should be run through the C preprocessor by config.gdb
+ to produce the Makefile. */
+
+/* Define this to xgdb if you want to compile xgdb as well as gdb. */
+XGDB=
+/* Place to install binaries. */
+bindir=/usr/local/bin
+/* Place to install X binaries. */
+xbindir=$(bindir)
+
+/* System V: If you compile gdb with a compiler which uses the coff
+ encapsulation feature (this is a function of the compiler used, NOT
+ of the m-?.h file selected by config.gdb), you must make sure that
+ the GNU nm is the one that is used by munch. */
+
+/* If you are compiling with GCC, make sure that either 1) You use the
+ -traditional flag, or 2) You have the fixed include files where GCC
+ can reach them. Otherwise the ioctl calls in inflow.c and readline.c
+ will be incorrectly compiled. The "fixincludes" script in the gcc
+ distribution will fix your include files up. */
+/* CC=gcc -traditional */
+CC=cc
+
+/* It is also possible that you will need to add -I/usr/include/sys to the
+ CFLAGS section if your system doesn't have fcntl.h in /usr/include (which
+ is where it should be according to Posix). */
+
+YACC=bison -y -v
+/* YACC=yacc */
+SHELL=/bin/sh
+MAKE=make
+
+/* Set this up with gcc if you have gnu ld and the loader will print out
+ line numbers for undefinded refs. */
+/* CC-LD=gcc -static */
+CC-LD=${CC}
+
+/* If you are using the GNU C library, uncomment the following line. */
+/* HAVE_VPRINTF_DEFINE = -DHAVE_VPRINTF */
+
+/* -I. for "#include <obstack.h>". Possibly regex.h also. */
+
+/* M_CFLAGS, if defined, has system-dependent CFLAGS. */
+#if !defined(M_CFLAGS)
+#define M_CFLAGS
+#endif
+
+/* CFLAGS for both GDB and readline. */
+GLOBAL_CFLAGS = -g M_CFLAGS
+CFLAGS = -I. ${HAVE_VPRINTF_DEFINE} ${GLOBAL_CFLAGS}
+/* None of the things in CFLAGS will do any harm, and on some systems
+ (e.g. SunOS4) it is important to use the M_CFLAGS. */
+LDFLAGS = $(CFLAGS)
+
+/*
+ define this to be "obstack.o" if you don't have the obstack library installed
+ you must at the same time define OBSTACK1 as "obstack.o"
+ so that the dependencies work right. Similarly with REGEX and "regex.o".
+ You must define REGEX and REGEX1 on USG machines.
+ If your sysyem is missing alloca(), or, more likely, it's there but
+ it doesn't work, define ALLOCA & ALLOCA1 */
+OBSTACK = obstack.o
+OBSTACK1 = obstack.o
+
+#ifdef M_REGEX
+REGEX = M_REGEX
+REGEX1 = M_REGEX
+#else
+REGEX =
+REGEX1 =
+#endif
+
+#ifdef M_ALLOCA
+ALLOCA = M_ALLOCA
+ALLOCA1 = M_ALLOCA
+#else
+ALLOCA =
+ALLOCA1 =
+#endif
+
+/*
+ define this to be "malloc.o" if you want to use the gnu malloc routine
+ (useful for debugging memory allocation problems in gdb). Otherwise, leave
+ it blank. */
+/* GNU_MALLOC = */
+GNU_MALLOC = malloc.o
+
+/* Flags to be used in compiling malloc.o
+ Specify range checking for storage allocation. */
+/* MALLOC_FLAGS = ${CFLAGS} */
+MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal_dump_core -DMSTATS
+
+/* Define SYSV if compiling on a system V or HP machine. */
+#ifdef M_SYSV
+SYSV_DEFINE = -DSYSV
+#else
+SYSV_DEFINE =
+#endif
+
+/* MUNCH_DEFINE should be -DSYSV if have System V-style nm,
+ or null if have BSD-style nm. */
+#ifdef M_BSD_NM
+MUNCH_DEFINE =
+#else
+MUNCH_DEFINE = ${SYSV_DEFINE}
+#endif
+
+/* Flags that describe where you can find the termcap library.
+ You may need to make other arrangements for USG. */
+TERMCAP = -ltermcap
+
+/* M_CLIBS, if defined, has system-dependent libs
+ For example, -lPW for System V to get alloca(). */
+#ifndef M_CLIBS
+#define M_CLIBS
+#endif
+CLIBS = ${ADD_FILES} ${TERMCAP} M_CLIBS
+
+ADD_FILES = ${OBSTACK} ${REGEX} ${ALLOCA} ${GNU_MALLOC}
+ADD_DEPS = ${OBSTACK1} ${REGEX1} ${ALLOCA1} ${GNU_MALLOC}
+
+SFILES = blockframe.c breakpoint.c dbxread.c coffread.c command.c core.c \
+ environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
+ kdb-start.c main.c printcmd.c \
+ remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
+ utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
+ xgdb.c
+
+DEPFILES = umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
+ sparc-dep.c hp9k320-dep.c hp300bsd-dep.c news-dep.c i386-dep.c \
+ symmetry-dep.c convex-dep.c altos-dep.c isi-dep.c pyr-dep.c
+
+PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \
+ ns32k-pinsn.c convex-pinsn.c pyr-pinsn.c
+
+HFILES = command.h defs.h environ.h expression.h frame.h getpagesize.h \
+ inferior.h symseg.h symtab.h value.h wait.h \
+ a.out.encap.h a.out.gnu.h stab.gnu.h
+
+OPCODES = m68k-opcode.h pn-opcode.h sparc-opcode.h npl-opcode.h vax-opcode.h \
+ ns32k-opcode.h convex-opcode.h pyr-opcode.h
+
+MFILES = m-hp9k320.h m-hp300bsd.h m-i386.h m-i386gas.h \
+ m-i386-sv32.h m-i386g-sv32.h m-isi.h m-merlin.h \
+ m-altos.h m-news.h m-newsos3.h m-npl.h m-pn.h \
+ m-sparc.h m-sun2.h m-sun3.h m-sun2os4.h \
+ m-sun3os4.h m-sun4os4.h m-umax.h m-vax.h m-symmetry.h m-convex.h \
+ m-pyr.h
+
+/* This list of files really shouldn't be in this makefile, but I can't think
+ of any good way to get the readline makefile to tell us what files
+ to put in our tarfile. */
+READLINE = readline.c history.c funmap.c \
+ emacs_keymap.c vi_keymap.c vi_mode.c keymaps.c \
+ readline.h history.h keymaps.h chardefs.h \
+ inc-readline.texinfo inc-history.texinfo \
+ readline.texinfo history.texinfo \
+ Makefile ChangeLog
+
+REMOTE_EXAMPLES = remote-sa.m68k.shar remote-multi.shar
+
+POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c alloca.c
+
+TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
+
+OTHERS = Makefile.dist createtags munch config.gdb ChangeLog README TAGS \
+ gdb.texinfo .gdbinit COPYING expread.tab.c stab.def \
+ XGDB-README copying.c Projects Convex.notes copying.awk hp-include
+
+TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \
+ ${POSSLIBS}
+TARFILES = ${TAGFILES} ${OTHERS} ${REMOTE_EXAMPLES}
+
+OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
+ values.o eval.o valops.o valarith.o valprint.o printcmd.o \
+ symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \
+ command.o utils.o expread.o expprint.o pinsn.o environ.o version.o \
+ copying.o ${READLINEOBS}
+
+TSOBS = core.o inflow.o dep.o
+
+NTSOBS = standalone.o
+
+TSSTART = /lib/crt0.o
+
+NTSSTART = kdb-start.o
+
+RL_LIB = readline/libreadline.a
+
+/* Do some fancy trickery to produce a line like
+ -DM_MAKEDEFINE="-DM_SYSV -DM_BSD_NM".
+*/
+MD=M_MAKEDEFINE
+
+/* Avoid funny things that Sun's make throws in for us. */
+/* TARGET_ARCH is supposed to get around it putting in the machine type.
+ If the "things" up there really is plural, we'll need to do something
+ else as well. */
+/*.c.o:
+ ${CC} -c ${CFLAGS} $< */
+TARGET_ARCH=
+
+all: gdb $(XGDB)
+
+install: gdb $(XGDB)
+ cp gdb $(bindir)/gdb.new
+ mv $(bindir)/gdb.new $(bindir)/gdb
+ -if [ "$(XGDB)" = xgdb ]; then \
+ cp xgdb $(xbindir)/xgdb.new; \
+ mv $(xbindir)/xgdb.new $(xbindir)xgdb; \
+ fi
+
+gdb : $(OBS) $(TSOBS) ${ADD_DEPS} ${RL_LIB}
+ rm -f init.c
+ ./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) > init.c
+ ${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) ${RL_LIB} $(CLIBS)
+
+/* This is useful when debugging GDB, because Unix doesn't let you run GDB
+ on itself without copying the executable. So "make gdb1" will make
+ gdb and put a copy in gdb1, and you can run it with "gdb gdb1". */
+gdb1 : gdb
+ cp gdb gdb1
+
+Makefile : Makefile.dist
+ cp Makefile.dist tmp.c
+ $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=$(MD)"
+ -rm tmp.c
+/* This did not work-- -Usparc became "-Usparc" became "-Usparc.
+ Or something like that. */
+/* $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=\"$(MD)\"" */
+
+xgdb : $(OBS) $(TSOBS) xgdb.o ${ADD_DEPS} ${RL_LIB}
+ rm -f init.c
+ ./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) xgdb.o > init.c
+ $(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
+ -lXaw -lXmu -lXt -lX11 ${RL_LIB} $(CLIBS)
+
+/* Old (pre R3) xgdb comp.
+ $(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
+ -lXaw -lXt -lX11 $(CLIBS) */
+
+kdb : $(NTSSTART) $(OBS) $(NTSOBS) ${ADD_DEPS} ${RL_LIB}
+ rm -f init.c
+ ./munch ${MUNCH_DEFINE} $(OBS) $(NTSOBS) > init.c
+ $(CC) $(LDFLAGS) -c init.c $(CLIBS)
+ ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o ${RL_LIB} -lc $(CLIBS)
+
+/* If it can figure out the appropriate order, createtags will make sure
+ that the proper m-*, *-dep, *-pinsn, and *-opcode files come first
+ in the tags list. It will attempt to do the same for dbxread.c and
+ coffread.c. This makes using M-. on machine dependent routines much
+ easier. */
+
+TAGS: ${TAGFILES}
+ createtags ${TAGFILES}
+tags: TAGS
+
+gdb.tar: ${TARFILES}
+ rm -f gdb.tar
+ mkdir dist-gdb
+ cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
+ mkdir dist-gdb/readline
+ cd dist-gdb/readline ; for i in ${READLINE} ; do ln -s ../../readline/$$i . ; done
+ tar chf gdb.tar dist-gdb
+ rm -rf dist-gdb
+
+/* Remove gdb.tar.Z so stupid compress doesn't ask whether we want to
+ overwrite it. compress -f is not what we want, because we do want
+ to know if compress would not make it smaller. */
+gdb.tar.Z: gdb.tar
+ if [ -f gdb.tar.Z ]; then rm -f gdb.tar.Z; else true; fi
+ compress gdb.tar
+
+clean:
+ rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} ${GNU_MALLOC}
+ rm -f init.c init.o
+ rm -f xgdb.o xgdb
+ rm -f gdb core gdb.tar gdb.tar.Z make.log
+ rm -f gdb[0-9]
+ cd readline ; make clean
+
+distclean: clean expread.tab.c TAGS
+ rm -f dep.c opcode.h param.h pinsn.c config.status
+ rm -f y.output yacc.acts yacc.tmp
+ rm -f ${TESTS} Makefile
+
+realclean: clean
+ rm -f expread.tab.c TAGS
+ rm -f dep.c opcode.h param.h pinsn.c config.status
+ rm -f Makefile
+
+xgdb.o : defs.h param.h symtab.h frame.h
+
+/* Make copying.c from COPYING */
+copying.c : COPYING copying.awk
+ awk -f copying.awk < COPYING > copying.c
+
+expread.tab.c : expread.y
+ @echo 'Expect 4 shift/reduce conflict.'
+ ${YACC} expread.y
+ mv y.tab.c expread.tab.c
+
+expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
+ $(CC) -c ${CFLAGS} expread.tab.c
+ mv expread.tab.o expread.o
+
+readline/libreadline.a : force_update
+ cd readline ; ${MAKE} "SYSV=${SYSV_DEFINE}" \
+ "DEBUG_FLAGS=${GLOBAL_CFLAGS}" "CC=${CC}" libreadline.a
+
+force_update :
+
+/* Only useful if you are using the gnu malloc routines. */
+malloc.o : malloc.c
+ ${CC} -c ${MALLOC_FLAGS} malloc.c
+
+/* dep.o depends on config.status in case someone reconfigures gdb out
+ from under an already compiled gdb. */
+dep.o : dep.c config.status defs.h param.h frame.h inferior.h obstack.h \
+ a.out.encap.h
+
+/* pinsn.o depends on config.status in case someone reconfigures gdb out
+ from under an already compiled gdb. */
+pinsn.o : pinsn.c config.status defs.h param.h symtab.h obstack.h symseg.h \
+ frame.h opcode.h
+
+/* The rest of this is a standard dependencies list (hand edited output of
+ cpp -M). It does not include dependencies of .o files on .c files. */
+/* All files which depend on config.status also depend on param.h in case
+ someone reconfigures gdb out from under an already compiled gdb. */
+blockframe.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
+breakpoint.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
+coffread.o : defs.h param.h config.status
+command.o : command.h defs.h
+core.o : defs.h param.h config.status a.out.encap.h
+dbxread.o : param.h config.status defs.h symtab.h obstack.h symseg.h a.out.encap.h \
+ stab.gnu.h
+environ.o : environ.h
+eval.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
+expprint.o : defs.h symtab.h obstack.h symseg.h param.h config.status expression.h
+findvar.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h value.h
+infcmd.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
+ environ.h value.h
+inflow.o : defs.h param.h config.status frame.h inferior.h
+infrun.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
+ wait.h
+kdb-start.o : defs.h param.h config.status
+main.o : defs.h command.h param.h config.status
+malloc.o : getpagesize.h
+obstack.o : obstack.h
+printcmd.o : defs.h param.h config.status frame.h symtab.h obstack.h symseg.h value.h \
+ expression.h
+regex.o : regex.h
+remote.o : defs.h param.h config.status frame.h inferior.h wait.h
+source.o : defs.h symtab.h obstack.h symseg.h param.h config.status
+stack.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
+standalone.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h \
+ inferior.h wait.h
+symmisc.o : defs.h symtab.h obstack.h symseg.h obstack.h
+symtab.o : defs.h symtab.h obstack.h symseg.h param.h config.status obstack.h
+utils.o : defs.h param.h config.status
+valarith.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
+valops.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h frame.h \
+ inferior.h
+valprint.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
+values.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
+
+robotussin.h : getpagesize.h
+symtab.h : obstack.h symseg.h
+a.out.encap.h : a.out.gnu.h
+
diff --git a/gnu/usr.bin/kgdb/Projects b/gnu/usr.bin/kgdb/Projects
new file mode 100644
index 000000000000..f38f6c74e959
--- /dev/null
+++ b/gnu/usr.bin/kgdb/Projects
@@ -0,0 +1,114 @@
+
+ Suggested projects for aspiring or current GDB hackers
+ ======================================================
+
+ (You should probably chat with kingdon@ai.mit.edu to make sure that
+ no one else is doing the project you chose).
+
+Add watchpoints (break if a memory location changes). This would
+usually have to involve constant single stepping, but occasionally
+there is operating system support which gdb should be able to cleanly
+use (e.g. on the 80386, there are 4 debug registers. By ptracing an
+address into them, you can get a trap on writes or on reads and
+writes).
+
+Rewrite proceed, wait_for_inferior, and normal_stop to clean them up.
+Suggestions:
+
+ 1) Make each test in wait_for_inferior a seperate subroutine
+ call.
+ 2) Combine wait_for_inferior and normal_stop to clean up
+ communication via global variables.
+ 3) See if you can find some way to clean up the global
+ variables that are used; possibly group them by data flow
+ and information content?
+
+Work out some kind of way to allow running the inferior to be done as
+a sub-execution of, eg. breakpoint command lists. Currently running
+the inferior interupts any command list execution. This would require
+some rewriting of wait_for_inferior & friends, and hence should
+probably be done in concert with the above.
+
+Add function arguments to gdb user defined functions.
+
+Add convenience variables that refer to exec file, symbol file,
+selected frame source file, selected frame function, selected frame
+line number, etc.
+
+Add a "suspend" subcommand of the "continue" command to suspend gdb
+while continuing execution of the subprocess. Useful when you are
+debugging servers and you want to dodge out and initiate a connection
+to a server running under gdb.
+
+Make "handle" understand symbolic signal names.
+
+Work out and implement a reasonably general mechanism for multi-threaded
+processies. There are parts of one implemented in convex-dep.c, if
+you want an example.
+
+A standalone version of gdb on the i386 exists. Anyone who wants to
+do some serious working cleaning it up and making it a general
+standalone gdb should contact pace@wheaties.ai.mit.edu.
+
+Add stab information to allow reasonable debugging of inline functions
+(possibly they should show up on a stack backtrace? With a note
+indicating that they weren't "real"?).
+
+Implement support for specifying arbitrary locations of stack frames
+(in practice, this usually requires specification of both the top and
+bottom of the stack frame (fp and sp), since you *must* retrieve the
+pc that was saved in the innermost frame).
+
+Modify the naked "until" command to step until past the current source
+line, rather than past the current pc value. This is tricky simply
+because the low level routines have no way of specifying a multi-line
+step range, and there is no way of saying "don't print stuff when we
+stop" from above (otherwise could just call step many times).
+
+Modify the handling of symbols grouped through BINCL/EINCL stabs to
+allocate a partial symtab for each BINCL/EINCL grouping. This will
+seriously decrease the size of inter-psymtab dependencies and hence
+lessen the amount that needs to be read in when a new source file is
+accessed.
+
+Work out some method of saving breakpoints across the reloading of an
+executable. Probably this should be by saving the commands by which
+the breakpoints were set and re-executing them (as text locations may
+change).
+
+Do an "x/i $pc" after each stepi or nexti.
+
+Modify all of the disassemblers to use printf_filtered to get correct
+more filtering.
+
+Modify gdb to work correctly with Pascal.
+
+Rewrite macros that handle frame chaining and frameless functions.
+They should be able to tell the difference between start, main, and a
+frameless function called from main.
+
+Work out what information would need to be included in an executable
+by the compiler to allow gdb to debug functions which do not have a
+frame pointer. Modify gdb and gcc to do this.
+
+When `attached' to a program (via either OS support or remote
+debugging), gdb should arrange to catch signals which the terminal
+might send, as it is unlikely that the program will be able to notice
+them. SIGINT and SIGTSTP are obvious examples.
+
+Enhance the gdb manual with extra examples where needed.
+
+Arrange for list_command not to use decode_line_1 and thus not require
+symbols to be read in simply to read a source file.
+
+Problem in xgdb; the readline library needs the terminal in CBREAK
+mode for command line editing, but this makes it difficult to dispatch
+on button presses. Possible solution: use a define to replace getc in
+readline.c with a routine that does button dispatches. You should
+probably see XGDB-README before you fiddle with XGDB. Also, someone
+is implementing a new xgdb; it may not be worth while fiddling with
+the old one.
+
+# Local Variables:
+# mode: text
+# End:
diff --git a/gnu/usr.bin/kgdb/README.gnu b/gnu/usr.bin/kgdb/README.gnu
new file mode 100644
index 000000000000..fa54dec236fd
--- /dev/null
+++ b/gnu/usr.bin/kgdb/README.gnu
@@ -0,0 +1,142 @@
+This is GDB, the GNU source-level debugger, presently running under un*x.
+
+Before compiling GDB, you must tell GDB what kind of machine you are
+running on. To do this, type `config.gdb machine', where machine is
+something like `vax' or `sun2'. For a list of valid machine types,
+type `config.gdb'.
+
+Normally config.gdb edits the makefile as necessary. If you have to
+edit the makefile on a standard machine listed in config.gdb this
+should be considered a bug and reported as such.
+
+Once these files are set up, just `make' will do everything,
+producing an executable `gdb' in this directory.
+
+If you want a new (current to this release) version of the manual, you
+will have to use the gdb.texinfo file provided with this distribution.
+The gdb.texinfo file requires the texinfo-format-buffer command from
+emacs 18.55 or later.
+
+About languages other than C...
+
+C++ support has been integrated into gdb. GDB should work with
+FORTRAN programs (if you have problem, please send a bug report), but
+I am not aware of anyone who is working on getting it to use the
+syntax of any language other than C or C++. Pascal programs which use
+sets, subranges, file variables, or nested functions will not
+currently work.
+
+About -gg format...
+
+Currently GDB version 3.x does *not* support GCC's -gg format. This
+is because it (in theory) has fast enough startup on dbx debugging
+format object files that -gg format is unnecessary (and hence
+undesirable, since it wastes space and processing power in gcc). I
+would like to hear people's opinions on the amount of time currently
+spent in startup; is it fast enough?
+
+About remote debugging...
+
+The two files remote-multi.shar and remote-sa.m68k.shar contain two
+examples of a remote stub to be used with remote.c. The the -multi
+file is a general stub that can probably be running on various
+different flavors of unix to allow debugging over a serial line from
+one machine to another. The remote-sa.m68k.shar is designed to run
+standalone on a 68k type cpu and communicate properley with the
+remote.c stub over a serial line.
+
+About reporting bugs...
+
+The correct address for reporting bugs found with gdb is
+"bug-gdb@prep.ai.mit.edu". Please send all bugs to that address.
+
+About xgdb...
+
+xgdb.c was provided to us by the user community; it is not an integral
+part of the gdb distribution. The problem of providing visual
+debugging support on top of gdb is peripheral to the GNU project and
+(at least right now) we can't afford to put time into it. So while we
+will be happy to incorporate user fixes to xgdb.c, we do not guarantee
+that it will work and we will not fix bugs reported in it. Someone is
+working on writing a new XGDB, so improving (e.g. by fixing it so that
+it will work, if it doesn't currently) the current one is not worth it.
+
+For those intersted in auto display of source and the availability of
+an editor while debugging I suggest trying gdb-mode in gnu-emacs.
+Comments on this mode are welcome.
+
+About the machine-dependent files...
+
+m-<machine>.h (param.h is a link to this file).
+This file contains macro definitions that express information
+about the machine's registers, stack frame format and instructions.
+
+<machine>-opcode.h (opcode.h is a link to this file).
+<machine>-pinsn.c (pinsn.c is a link to this file).
+These files contain the information necessary to print instructions
+for your cpu type.
+
+<machine>-dep.c (dep.c is a link to this file).
+Those routines which provide a low level interface to ptrace and which
+tend to be machine-dependent. (The machine-independent routines are in
+`infrun.c' and `inflow.c')
+
+About writing code for GDB...
+
+We appreciate having users contribute code that is of general use, but
+for it to be included in future GDB releases it must be cleanly
+written. We do not want to include changes that will needlessly make future
+maintainance difficult. It is not much harder to do things right, and
+in the long term it is worth it to the GNU project, and probably to
+you individually as well.
+
+Please code according to the GNU coding standards. If you do not have
+a copy, you can request one by sending mail to gnu@prep.ai.mit.edu.
+
+Please try to avoid making machine-specific changes to
+machine-independent files (i.e. all files except "param.h" and
+"dep.c". "pinsn.c" and "opcode.h" are processor-specific but not
+operating system-dependent). If this is unavoidable, put a hook in
+the machine-independent file which calls a (possibly)
+machine-dependent macro (for example, the IGNORE_SYMBOL macro can be
+used for any symbols which need to be ignored on a specific machine.
+Calling IGNORE_SYMBOL in dbxread.c is a lot cleaner than a maze of #if
+defined's). The machine-independent code should do whatever "most"
+machines want if the macro is not defined in param.h. Using #if
+defined can sometimes be OK (e.g. SET_STACK_LIMIT_HUGE) but should be
+conditionalized on a specific feature of an operating system (set in
+param.h) rather than something like #if defined(vax) or #if
+defined(SYSV).
+
+It is better to replace entire routines which may be system-specific,
+rather than put in a whole bunch of hooks which are probably not going
+to be helpful for any purpose other than your changes. For example,
+if you want to modify dbxread.c to deal with DBX debugging symbols
+which are in COFF files rather than BSD a.out files, do something
+along the lines of a macro GET_NEXT_SYMBOL, which could have
+different definitions for COFF and a.out, rather than trying to put
+the necessary changes throughout all the code in dbxread.c that
+currently assumes BSD format.
+
+Please avoid duplicating code. For example, if something needs to be
+changed in read_inferior_memory, it is very painful because there is a
+copy in every dep.c file. The correct way to do this is to put (in
+this case) the standard ptrace interfaces in a separate file ptrace.c,
+which is used by all systems which have ptrace. ptrace.c would deal
+with variations between systems the same way any system-independent
+file would (hooks, #if defined, etc.).
+
+About debugging gdb with itself...
+
+You probably want to do a "make TAGS" after you configure your
+distribution; this will put the machine dependent routines for your
+local machine where they will be accessed first by a M-period .
+
+Also, make sure that you've compiled gdb with your local cc or taken
+appropriate precautions regarding ansification of include files. See
+the Makefile for more information.
+
+The "info" command, when executed without a subcommand in a gdb being
+debugged by gdb, will pop you back up to the top level gdb. See
+.gdbinit for more details.
+
diff --git a/gnu/usr.bin/kgdb/XGdbinit.samp b/gnu/usr.bin/kgdb/XGdbinit.samp
new file mode 100644
index 000000000000..a99f10695606
--- /dev/null
+++ b/gnu/usr.bin/kgdb/XGdbinit.samp
@@ -0,0 +1,15 @@
+button "show" push-to-file %S
+button "back" pop-file
+button "break in" break %S
+button "break at" break %l
+button delete delete %b%e
+button backtrace
+button up
+button down
+button print print %E
+button print* print *(%E)
+button next
+button step
+button "do upto" until %l%e
+button finish
+button continue cont%e
diff --git a/gnu/usr.bin/kgdb/Xgdb.ad b/gnu/usr.bin/kgdb/Xgdb.ad
new file mode 100644
index 000000000000..5f9fe9920b49
--- /dev/null
+++ b/gnu/usr.bin/kgdb/Xgdb.ad
@@ -0,0 +1,8 @@
+Xgdb*geometry: 580x874-0+28
+Xgdb*src*scrollVertical: whenneeded
+Xgdb*src*scrollHorizontal: whenneeded
+Xgdb*src*wrap: never
+Xgdb*src*editType: read
+Xgdb*frame.buttons.allowResize: true
+Xgdb*frame.buttons.skipAdjust: true
+Xgdb*frame*showGrip: false
diff --git a/gnu/usr.bin/kgdb/blockframe.c b/gnu/usr.bin/kgdb/blockframe.c
new file mode 100644
index 000000000000..236d1cdccfec
--- /dev/null
+++ b/gnu/usr.bin/kgdb/blockframe.c
@@ -0,0 +1,622 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)blockframe.c 6.4 (Berkeley) 5/11/91";
+#endif /* not lint */
+
+/* Get info from stack frames;
+ convert between frames, blocks, functions and pc values.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+#include <obstack.h>
+
+#if defined(NEWVM) && defined(KERNELDEBUG)
+#include <sys/param.h> /* XXX for FRAME_CHAIN_VALID */
+#endif
+
+/* Start and end of object file containing the entry point.
+ STARTUP_FILE_END is the first address of the next file.
+ This file is assumed to be a startup file
+ and frames with pc's inside it
+ are treated as nonexistent.
+
+ Setting these variables is necessary so that backtraces do not fly off
+ the bottom of the stack. */
+CORE_ADDR startup_file_start;
+CORE_ADDR startup_file_end;
+
+/* Is ADDR outside the startup file? */
+int
+outside_startup_file (addr)
+ CORE_ADDR addr;
+{
+ return !(addr >= startup_file_start && addr < startup_file_end);
+}
+
+/* Address of innermost stack frame (contents of FP register) */
+
+static FRAME current_frame;
+
+struct block *block_for_pc ();
+CORE_ADDR get_pc_function_start ();
+
+/*
+ * Cache for frame addresses already read by gdb. Valid only while
+ * inferior is stopped. Control variables for the frame cache should
+ * be local to this module.
+ */
+struct obstack frame_cache_obstack;
+
+/* Return the innermost (currently executing) stack frame. */
+
+FRAME
+get_current_frame ()
+{
+ /* We assume its address is kept in a general register;
+ param.h says which register. */
+
+ return current_frame;
+}
+
+void
+set_current_frame (frame)
+ FRAME frame;
+{
+ current_frame = frame;
+}
+
+FRAME
+create_new_frame (addr, pc)
+ FRAME_ADDR addr;
+ CORE_ADDR pc;
+{
+ struct frame_info *fci; /* Same type as FRAME */
+
+ fci = (struct frame_info *)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_info));
+
+ /* Arbitrary frame */
+ fci->next = (struct frame_info *) 0;
+ fci->prev = (struct frame_info *) 0;
+ fci->frame = addr;
+ fci->next_frame = 0; /* Since arbitrary */
+ fci->pc = pc;
+
+#ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO (fci);
+#endif
+
+ return fci;
+}
+
+/* Return the frame that called FRAME.
+ If FRAME is the original frame (it has no caller), return 0. */
+
+FRAME
+get_prev_frame (frame)
+ FRAME frame;
+{
+ /* We're allowed to know that FRAME and "struct frame_info *" are
+ the same */
+ return get_prev_frame_info (frame);
+}
+
+/* Return the frame that FRAME calls (0 if FRAME is the innermost
+ frame). */
+
+FRAME
+get_next_frame (frame)
+ FRAME frame;
+{
+ /* We're allowed to know that FRAME and "struct frame_info *" are
+ the same */
+ return frame->next;
+}
+
+/*
+ * Flush the entire frame cache.
+ */
+void
+flush_cached_frames ()
+{
+ /* Since we can't really be sure what the first object allocated was */
+ obstack_free (&frame_cache_obstack, 0);
+ obstack_init (&frame_cache_obstack);
+
+ current_frame = (struct frame_info *) 0; /* Invalidate cache */
+}
+
+/* Return a structure containing various interesting information
+ about a specified stack frame. */
+/* How do I justify including this function? Well, the FRAME
+ identifier format has gone through several changes recently, and
+ it's not completely inconceivable that it could happen again. If
+ it does, have this routine around will help */
+
+struct frame_info *
+get_frame_info (frame)
+ FRAME frame;
+{
+ return frame;
+}
+
+/* If a machine allows frameless functions, it should define a macro
+ FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) in param.h. FI is the struct
+ frame_info for the frame, and FRAMELESS should be set to nonzero
+ if it represents a frameless function invocation. */
+
+/* Many machines which allow frameless functions can detect them using
+ this macro. Such machines should define FRAMELESS_FUNCTION_INVOCATION
+ to just call this macro. */
+#define FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS) \
+{ \
+ CORE_ADDR func_start, after_prologue; \
+ func_start = (get_pc_function_start ((FI)->pc) + \
+ FUNCTION_START_OFFSET); \
+ if (func_start) \
+ { \
+ after_prologue = func_start; \
+ SKIP_PROLOGUE (after_prologue); \
+ (FRAMELESS) = (after_prologue == func_start); \
+ } \
+ else \
+ /* If we can't find the start of the function, we don't really */ \
+ /* know whether the function is frameless, but we should be */ \
+ /* able to get a reasonable (i.e. best we can do under the */ \
+ /* circumstances) backtrace by saying that it isn't. */ \
+ (FRAMELESS) = 0; \
+}
+
+/* Return a structure containing various interesting information
+ about the frame that called NEXT_FRAME. Returns NULL
+ if there is no such frame. */
+
+struct frame_info *
+get_prev_frame_info (next_frame)
+ FRAME next_frame;
+{
+ FRAME_ADDR address;
+ struct frame_info *prev;
+ int fromleaf = 0;
+
+ /* If the requested entry is in the cache, return it.
+ Otherwise, figure out what the address should be for the entry
+ we're about to add to the cache. */
+
+ if (!next_frame)
+ {
+ if (!current_frame)
+ {
+ if (!have_inferior_p () && !have_core_file_p ())
+ fatal ("get_prev_frame_info: Called before cache primed. \"Shouldn't happen.\"");
+ else
+ error ("No inferior or core file.");
+ }
+
+ return current_frame;
+ }
+
+ /* If we have the prev one, return it */
+ if (next_frame->prev)
+ return next_frame->prev;
+
+ /* On some machines it is possible to call a function without
+ setting up a stack frame for it. On these machines, we
+ define this macro to take two args; a frameinfo pointer
+ identifying a frame and a variable to set or clear if it is
+ or isn't leafless. */
+#ifdef FRAMELESS_FUNCTION_INVOCATION
+ /* Still don't want to worry about this except on the innermost
+ frame. This macro will set FROMLEAF if NEXT_FRAME is a
+ frameless function invocation. */
+ if (!(next_frame->next))
+ {
+ FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf);
+ if (fromleaf)
+ address = next_frame->frame;
+ }
+#endif
+
+ if (!fromleaf)
+ {
+ /* Two macros defined in param.h specify the machine-dependent
+ actions to be performed here.
+ First, get the frame's chain-pointer.
+ If that is zero, the frame is the outermost frame or a leaf
+ called by the outermost frame. This means that if start
+ calls main without a frame, we'll return 0 (which is fine
+ anyway).
+
+ Nope; there's a problem. This also returns when the current
+ routine is a leaf of main. This is unacceptable. We move
+ this to after the ffi test; I'd rather have backtraces from
+ start go curfluy than have an abort called from main not show
+ main. */
+ address = FRAME_CHAIN (next_frame);
+ if (!FRAME_CHAIN_VALID (address, next_frame))
+ return 0;
+ /* If this frame is a leaf, this will be superceeded by the
+ code below. */
+ address = FRAME_CHAIN_COMBINE (address, next_frame);
+ }
+ if (address == 0)
+ return 0;
+
+ prev = (struct frame_info *)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_info));
+
+ if (next_frame)
+ next_frame->prev = prev;
+ prev->next = next_frame;
+ prev->prev = (struct frame_info *) 0;
+ prev->frame = address;
+ prev->next_frame = prev->next ? prev->next->frame : 0;
+
+#ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO(prev);
+#endif
+
+ /* This entry is in the frame queue now, which is good since
+ FRAME_SAVED_PC may use that queue to figure out it's value
+ (see m-sparc.h). We want the pc saved in the inferior frame. */
+ prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) :
+ next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ());
+
+ return prev;
+}
+
+CORE_ADDR
+get_frame_pc (frame)
+ FRAME frame;
+{
+ struct frame_info *fi;
+ fi = get_frame_info (frame);
+ return fi->pc;
+}
+
+/* Find the addresses in which registers are saved in FRAME. */
+
+void
+get_frame_saved_regs (frame_info_addr, saved_regs_addr)
+ struct frame_info *frame_info_addr;
+ struct frame_saved_regs *saved_regs_addr;
+{
+ FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr);
+}
+
+/* Return the innermost lexical block in execution
+ in a specified stack frame. The frame address is assumed valid. */
+
+struct block *
+get_frame_block (frame)
+ FRAME frame;
+{
+ struct frame_info *fi;
+ CORE_ADDR pc;
+
+ fi = get_frame_info (frame);
+
+ pc = fi->pc;
+ if (fi->next_frame != 0)
+ /* We are not in the innermost frame. We need to subtract one to
+ get the correct block, in case the call instruction was the
+ last instruction of the block. If there are any machines on
+ which the saved pc does not point to after the call insn, we
+ probably want to make fi->pc point after the call insn anyway. */
+ --pc;
+ return block_for_pc (pc);
+}
+
+struct block *
+get_current_block ()
+{
+ return block_for_pc (read_pc ());
+}
+
+CORE_ADDR
+get_pc_function_start (pc)
+ CORE_ADDR pc;
+{
+ register struct block *bl = block_for_pc (pc);
+ register struct symbol *symbol;
+ if (bl == 0 || (symbol = block_function (bl)) == 0)
+ {
+ register int misc_index = find_pc_misc_function (pc);
+ if (misc_index >= 0)
+ return misc_function_vector[misc_index].address;
+ return 0;
+ }
+ bl = SYMBOL_BLOCK_VALUE (symbol);
+ return BLOCK_START (bl);
+}
+
+/* Return the symbol for the function executing in frame FRAME. */
+
+struct symbol *
+get_frame_function (frame)
+ FRAME frame;
+{
+ register struct block *bl = get_frame_block (frame);
+ if (bl == 0)
+ return 0;
+ return block_function (bl);
+}
+
+/* Return the innermost lexical block containing the specified pc value,
+ or 0 if there is none. */
+
+extern struct symtab *psymtab_to_symtab ();
+
+struct block *
+block_for_pc (pc)
+ register CORE_ADDR pc;
+{
+ register struct block *b;
+ register int bot, top, half;
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ struct blockvector *bl;
+
+ /* First search all symtabs for one whose file contains our pc */
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ bl = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bl, 0);
+ if (BLOCK_START (b) <= pc
+ && BLOCK_END (b) > pc)
+ break;
+ }
+
+ if (s == 0)
+ for (ps = partial_symtab_list; ps; ps = ps->next)
+ {
+ if (ps->textlow <= pc
+ && ps->texthigh > pc)
+ {
+ if (ps->readin)
+ fatal ("Internal error: pc found in readin psymtab and not in any symtab.");
+ s = psymtab_to_symtab (ps);
+ bl = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bl, 0);
+ break;
+ }
+ }
+
+ if (s == 0)
+ return 0;
+
+ /* Then search that symtab for the smallest block that wins. */
+ /* Use binary search to find the last block that starts before PC. */
+
+ bot = 0;
+ top = BLOCKVECTOR_NBLOCKS (bl);
+
+ while (top - bot > 1)
+ {
+ half = (top - bot + 1) >> 1;
+ b = BLOCKVECTOR_BLOCK (bl, bot + half);
+ if (BLOCK_START (b) <= pc)
+ bot += half;
+ else
+ top = bot + half;
+ }
+
+ /* Now search backward for a block that ends after PC. */
+
+ while (bot >= 0)
+ {
+ b = BLOCKVECTOR_BLOCK (bl, bot);
+ if (BLOCK_END (b) > pc)
+ return b;
+ bot--;
+ }
+
+ return 0;
+}
+
+/* Return the function containing pc value PC.
+ Returns 0 if function is not known. */
+
+struct symbol *
+find_pc_function (pc)
+ CORE_ADDR pc;
+{
+ register struct block *b = block_for_pc (pc);
+ if (b == 0)
+ return 0;
+ return block_function (b);
+}
+
+/* Finds the "function" (text symbol) that is smaller than PC
+ but greatest of all of the potential text symbols. Sets
+ *NAME and/or *ADDRESS conditionally if that pointer is non-zero.
+ Returns 0 if it couldn't find anything, 1 if it did. On a zero
+ return, *NAME and *ADDRESS are always set to zero. On a 1 return,
+ *NAME and *ADDRESS contain real information. */
+
+int
+find_pc_partial_function (pc, name, address)
+ CORE_ADDR pc;
+ char **name;
+ CORE_ADDR *address;
+{
+ struct partial_symtab *pst = find_pc_psymtab (pc);
+ struct symbol *f;
+ int miscfunc;
+ struct partial_symbol *psb;
+
+ if (pst)
+ {
+ if (pst->readin)
+ {
+ /* The information we want has already been read in.
+ We can go to the already readin symbols and we'll get
+ the best possible answer. */
+ f = find_pc_function (pc);
+ if (!f)
+ {
+ return_error:
+ /* No availible symbol. */
+ if (name != 0)
+ *name = 0;
+ if (address != 0)
+ *address = 0;
+ return 0;
+ }
+
+ if (name)
+ *name = SYMBOL_NAME (f);
+ if (address)
+ *address = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
+ return 1;
+ }
+
+ /* Get the information from a combination of the pst
+ (static symbols), and the misc function vector (extern
+ symbols). */
+ miscfunc = find_pc_misc_function (pc);
+ psb = find_pc_psymbol (pst, pc);
+
+ if (!psb && miscfunc == -1)
+ {
+ goto return_error;
+ }
+ if (!psb
+ || (miscfunc != -1
+ && (SYMBOL_VALUE(psb)
+ < misc_function_vector[miscfunc].address)))
+ {
+ if (address)
+ *address = misc_function_vector[miscfunc].address;
+ if (name)
+ *name = misc_function_vector[miscfunc].name;
+ return 1;
+ }
+ else
+ {
+ if (address)
+ *address = SYMBOL_VALUE (psb);
+ if (name)
+ *name = SYMBOL_NAME (psb);
+ return 1;
+ }
+ }
+ else
+ /* Must be in the misc function stuff. */
+ {
+ miscfunc = find_pc_misc_function (pc);
+ if (miscfunc == -1)
+ goto return_error;
+ if (address)
+ *address = misc_function_vector[miscfunc].address;
+ if (name)
+ *name = misc_function_vector[miscfunc].name;
+ return 1;
+ }
+}
+
+/* Find the misc function whose address is the largest
+ while being less than PC. Return its index in misc_function_vector.
+ Returns -1 if PC is not in suitable range. */
+
+int
+find_pc_misc_function (pc)
+ register CORE_ADDR pc;
+{
+ register int lo = 0;
+ register int hi = misc_function_count-1;
+ register int new;
+ register int distance;
+
+ /* Note that the last thing in the vector is always _etext. */
+ /* Actually, "end", now that non-functions
+ go on the misc_function_vector. */
+
+ /* Above statement is not *always* true - fix for case where there are */
+ /* no misc functions at all (ie no symbol table has been read). */
+ if (hi < 0) return -1; /* no misc functions recorded */
+
+ /* trivial reject range test */
+ if (pc < misc_function_vector[0].address ||
+ pc > misc_function_vector[hi].address)
+ return -1;
+
+ /* Note that the following search will not return hi if
+ pc == misc_function_vector[hi].address. If "end" points to the
+ first unused location, this is correct and the above test
+ simply needs to be changed to
+ "pc >= misc_function_vector[hi].address". */
+ do {
+ new = (lo + hi) >> 1;
+ distance = misc_function_vector[new].address - pc;
+ if (distance == 0)
+ return new; /* an exact match */
+ else if (distance > 0)
+ hi = new;
+ else
+ lo = new;
+ } while (hi-lo != 1);
+
+ /* if here, we had no exact match, so return the lower choice */
+ return lo;
+}
+
+/* Return the innermost stack frame executing inside of the specified block,
+ or zero if there is no such frame. */
+
+FRAME
+block_innermost_frame (block)
+ struct block *block;
+{
+ struct frame_info *fi;
+ register FRAME frame;
+ register CORE_ADDR start = BLOCK_START (block);
+ register CORE_ADDR end = BLOCK_END (block);
+
+ frame = 0;
+ while (1)
+ {
+ frame = get_prev_frame (frame);
+ if (frame == 0)
+ return 0;
+ fi = get_frame_info (frame);
+ if (fi->pc >= start && fi->pc < end)
+ return frame;
+ }
+}
+
+void
+_initialize_blockframe ()
+{
+ obstack_init (&frame_cache_obstack);
+}
diff --git a/gnu/usr.bin/kgdb/breakpoint.c b/gnu/usr.bin/kgdb/breakpoint.c
new file mode 100644
index 000000000000..b515ed3f874f
--- /dev/null
+++ b/gnu/usr.bin/kgdb/breakpoint.c
@@ -0,0 +1,1383 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)breakpoint.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Everything about breakpoints, for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+/* This is the sequence of bytes we insert for a breakpoint. */
+
+static char break_insn[] = BREAKPOINT;
+
+/* States of enablement of breakpoint.
+ `temporary' means disable when hit.
+ `delete' means delete when hit. */
+
+enum enable { disabled, enabled, temporary, delete};
+
+/* Not that the ->silent field is not currently used by any commands
+ (though the code is in there if it was to be and set_raw_breakpoint
+ does set it to 0). I implemented it because I thought it would be
+ useful for a hack I had to put in; I'm going to leave it in because
+ I can see how there might be times when it would indeed be useful */
+
+struct breakpoint
+{
+ struct breakpoint *next;
+ /* Number assigned to distinguish breakpoints. */
+ int number;
+ /* Address to break at. */
+ CORE_ADDR address;
+ /* Line number of this address. Redundant. */
+ int line_number;
+ /* Symtab of file of this address. Redundant. */
+ struct symtab *symtab;
+ /* Zero means disabled; remember the info but don't break here. */
+ enum enable enable;
+ /* Non-zero means a silent breakpoint (don't print frame info
+ if we stop here). */
+ unsigned char silent;
+ /* Number of stops at this breakpoint that should
+ be continued automatically before really stopping. */
+ int ignore_count;
+ /* "Real" contents of byte where breakpoint has been inserted.
+ Valid only when breakpoints are in the program. */
+ char shadow_contents[sizeof break_insn];
+ /* Nonzero if this breakpoint is now inserted. */
+ char inserted;
+ /* Nonzero if this is not the first breakpoint in the list
+ for the given address. */
+ char duplicate;
+ /* Chain of command lines to execute when this breakpoint is hit. */
+ struct command_line *commands;
+ /* Stack depth (address of frame). If nonzero, break only if fp
+ equals this. */
+ FRAME_ADDR frame;
+ /* Conditional. Break only if this expression's value is nonzero. */
+ struct expression *cond;
+};
+
+#define ALL_BREAKPOINTS(b) for (b = breakpoint_chain; b; b = b->next)
+
+/* Chain of all breakpoints defined. */
+
+struct breakpoint *breakpoint_chain;
+
+/* Number of last breakpoint made. */
+
+static int breakpoint_count;
+
+/* Default address, symtab and line to put a breakpoint at
+ for "break" command with no arg.
+ if default_breakpoint_valid is zero, the other three are
+ not valid, and "break" with no arg is an error.
+
+ This set by print_stack_frame, which calls set_default_breakpoint. */
+
+int default_breakpoint_valid;
+CORE_ADDR default_breakpoint_address;
+struct symtab *default_breakpoint_symtab;
+int default_breakpoint_line;
+
+/* Remaining commands (not yet executed)
+ of last breakpoint hit. */
+
+struct command_line *breakpoint_commands;
+
+static void delete_breakpoint ();
+void clear_momentary_breakpoints ();
+void breakpoint_auto_delete ();
+
+/* Flag indicating extra verbosity for xgdb. */
+extern int xgdb_verbose;
+
+/* condition N EXP -- set break condition of breakpoint N to EXP. */
+
+static void
+condition_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b;
+ register char *p;
+ register int bnum;
+ register struct expression *expr;
+
+ if (arg == 0)
+ error_no_arg ("breakpoint number");
+
+ p = arg;
+ while (*p >= '0' && *p <= '9') p++;
+ if (p == arg)
+ /* There is no number here. (e.g. "cond a == b"). */
+ error_no_arg ("breakpoint number");
+ bnum = atoi (arg);
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bnum)
+ {
+ if (b->cond)
+ {
+ free (b->cond);
+ b->cond = 0; /* parse_c_1 can leave this unchanged. */
+ }
+ if (*p == 0)
+ {
+ b->cond = 0;
+ if (from_tty)
+ printf ("Breakpoint %d now unconditional.\n", bnum);
+ }
+ else
+ {
+ if (*p != ' ' && *p != '\t')
+ error ("Arguments must be an integer (breakpoint number) and an expression.");
+
+ /* Find start of expression */
+ while (*p == ' ' || *p == '\t') p++;
+
+ arg = p;
+ b->cond = (struct expression *) parse_c_1 (&arg, block_for_pc (b->address), 0);
+ if (*arg)
+ error ("Junk at end of expression");
+ }
+ return;
+ }
+
+ error ("No breakpoint number %d.", bnum);
+}
+
+static void
+commands_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b;
+ register char *p, *p1;
+ register int bnum;
+ struct command_line *l;
+
+ /* If we allowed this, we would have problems with when to
+ free the storage, if we change the commands currently
+ being read from. */
+
+ if (breakpoint_commands)
+ error ("Can't use the \"commands\" command among a breakpoint's commands.");
+
+ /* Allow commands by itself to refer to the last breakpoint. */
+ if (arg == 0)
+ bnum = breakpoint_count;
+ else
+ {
+ p = arg;
+ if (! (*p >= '0' && *p <= '9'))
+ error ("Argument must be integer (a breakpoint number).");
+
+ while (*p >= '0' && *p <= '9') p++;
+ if (*p)
+ error ("Unexpected extra arguments following breakpoint number.");
+
+ bnum = atoi (arg);
+ }
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bnum)
+ {
+ if (from_tty && input_from_terminal_p ())
+ {
+ printf ("Type commands for when breakpoint %d is hit, one per line.\n\
+End with a line saying just \"end\".\n", bnum);
+ fflush (stdout);
+ }
+ l = read_command_lines (from_tty);
+ free_command_lines (b->commands);
+ b->commands = l;
+ return;
+ }
+ error ("No breakpoint number %d.", bnum);
+}
+
+/* Called from command loop to execute the commands
+ associated with the breakpoint we just stopped at. */
+
+void
+do_breakpoint_commands ()
+{
+ struct command_line *cmd;
+
+ while (cmd = breakpoint_commands)
+ {
+ breakpoint_commands = 0;
+ execute_command_lines(cmd);
+ /* If command was "cont", breakpoint_commands is now 0,
+ of if we stopped at yet another breakpoint which has commands,
+ it is now the commands for the new breakpoint. */
+ }
+ clear_momentary_breakpoints ();
+}
+
+/* Used when the program is proceeded, to eliminate any remaining
+ commands attached to the previous breakpoint we stopped at. */
+
+void
+clear_breakpoint_commands ()
+{
+ breakpoint_commands = 0;
+ breakpoint_auto_delete (0);
+}
+
+/* Functions to get and set the current list of pending
+ breakpoint commands. These are used by run_stack_dummy
+ to preserve the commands around a function call. */
+
+struct command_line *
+get_breakpoint_commands ()
+{
+ return breakpoint_commands;
+}
+
+void
+set_breakpoint_commands (cmds)
+ struct command_line *cmds;
+{
+ breakpoint_commands = cmds;
+}
+
+/* insert_breakpoints is used when starting or continuing the program.
+ remove_breakpoints is used when the program stops.
+ Both return zero if successful,
+ or an `errno' value if could not write the inferior. */
+
+int
+insert_breakpoints ()
+{
+ register struct breakpoint *b;
+ int val;
+
+#ifdef BREAKPOINT_DEBUG
+ printf ("Inserting breakpoints.\n");
+#endif /* BREAKPOINT_DEBUG */
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled && ! b->inserted && ! b->duplicate)
+ {
+ read_memory (b->address, b->shadow_contents, sizeof break_insn);
+ val = write_memory (b->address, break_insn, sizeof break_insn);
+ if (val)
+ return val;
+#ifdef BREAKPOINT_DEBUG
+ printf ("Inserted breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
+ b->address, b->shadow_contents[0], b->shadow_contents[1]);
+#endif /* BREAKPOINT_DEBUG */
+ b->inserted = 1;
+ }
+ return 0;
+}
+
+int
+remove_breakpoints ()
+{
+ register struct breakpoint *b;
+ int val;
+
+#ifdef BREAKPOINT_DEBUG
+ printf ("Removing breakpoints.\n");
+#endif /* BREAKPOINT_DEBUG */
+
+ ALL_BREAKPOINTS (b)
+ if (b->inserted)
+ {
+ val = write_memory (b->address, b->shadow_contents, sizeof break_insn);
+ if (val)
+ return val;
+ b->inserted = 0;
+#ifdef BREAKPOINT_DEBUG
+ printf ("Removed breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
+ b->address, b->shadow_contents[0], b->shadow_contents[1]);
+#endif /* BREAKPOINT_DEBUG */
+ }
+
+ return 0;
+}
+
+/* Clear the "inserted" flag in all breakpoints.
+ This is done when the inferior is loaded. */
+
+void
+mark_breakpoints_out ()
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ b->inserted = 0;
+}
+
+/* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at PC.
+ When continuing from a location with a breakpoint,
+ we actually single step once before calling insert_breakpoints. */
+
+int
+breakpoint_here_p (pc)
+ CORE_ADDR pc;
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled && b->address == pc)
+ return 1;
+
+ return 0;
+}
+
+/* Evaluate the expression EXP and return 1 if value is zero.
+ This is used inside a catch_errors to evaluate the breakpoint condition. */
+
+int
+breakpoint_cond_eval (exp)
+ struct expression *exp;
+{
+ return value_zerop (evaluate_expression (exp));
+}
+
+/* Return 0 if PC is not the address just after a breakpoint,
+ or -1 if breakpoint says do not stop now,
+ or -2 if breakpoint says it has deleted itself and don't stop,
+ or -3 if hit a breakpoint number -3 (delete when program stops),
+ or else the number of the breakpoint,
+ with 0x1000000 added (or subtracted, for a negative return value) for
+ a silent breakpoint. */
+
+int
+breakpoint_stop_status (pc, frame_address)
+ CORE_ADDR pc;
+ FRAME_ADDR frame_address;
+{
+ register struct breakpoint *b;
+ register int cont = 0;
+
+ /* Get the address where the breakpoint would have been. */
+ pc -= DECR_PC_AFTER_BREAK;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled && b->address == pc)
+ {
+ if (b->frame && b->frame != frame_address)
+ cont = -1;
+ else
+ {
+ int value_zero;
+ if (b->cond)
+ {
+ /* Need to select the frame, with all that implies
+ so that the conditions will have the right context. */
+ select_frame (get_current_frame (), 0);
+ value_zero
+ = catch_errors (breakpoint_cond_eval, b->cond,
+ "Error occurred in testing breakpoint condition.");
+ free_all_values ();
+ }
+ if (b->cond && value_zero)
+ {
+ cont = -1;
+ }
+ else if (b->ignore_count > 0)
+ {
+ b->ignore_count--;
+ cont = -1;
+ }
+ else
+ {
+ if (b->enable == temporary)
+ b->enable = disabled;
+ breakpoint_commands = b->commands;
+ if (b->silent
+ || (breakpoint_commands
+ && !strcmp ("silent", breakpoint_commands->line)))
+ {
+ if (breakpoint_commands)
+ breakpoint_commands = breakpoint_commands->next;
+ return (b->number > 0 ?
+ 0x1000000 + b->number :
+ b->number - 0x1000000);
+ }
+ return b->number;
+ }
+ }
+ }
+
+ return cont;
+}
+
+static void
+breakpoint_1 (bnum)
+ int bnum;
+{
+ register struct breakpoint *b;
+ register struct command_line *l;
+ register struct symbol *sym;
+ CORE_ADDR last_addr = (CORE_ADDR)-1;
+
+ ALL_BREAKPOINTS (b)
+ if (bnum == -1 || bnum == b->number)
+ {
+ printf_filtered ("#%-3d %c 0x%08x", b->number,
+ "nyod"[(int) b->enable],
+ b->address);
+ last_addr = b->address;
+ if (b->symtab)
+ {
+ sym = find_pc_function (b->address);
+ if (sym)
+ {
+ fputs_filtered (" in ", stdout);
+ fputs_demangled (SYMBOL_NAME (sym), stdout, 1);
+ fputs_filtered (" (", stdout);
+ }
+ fputs_filtered (b->symtab->filename, stdout);
+ printf_filtered (" line %d", b->line_number);
+ if (sym) fputs_filtered(")", stdout);
+ }
+ else
+ print_address_symbolic (b->address, stdout);
+
+ printf_filtered ("\n");
+
+ if (b->ignore_count)
+ printf_filtered ("\tignore next %d hits\n", b->ignore_count);
+ if (b->frame)
+ printf_filtered ("\tstop only in stack frame at 0x%x\n", b->frame);
+ if (b->cond)
+ {
+ printf_filtered ("\tbreak only if ");
+ print_expression (b->cond, stdout);
+ printf_filtered ("\n");
+ }
+ if (l = b->commands)
+ while (l)
+ {
+ printf_filtered ("\t%s\n", l->line);
+ l = l->next;
+ }
+ }
+
+ /* Compare against (CORE_ADDR)-1 in case some compiler decides
+ that a comparison of an unsigned with -1 is always false. */
+ if (last_addr != (CORE_ADDR)-1)
+ set_next_address (last_addr);
+}
+
+static void
+breakpoints_info (bnum_exp)
+ char *bnum_exp;
+{
+ int bnum = -1;
+
+ if (bnum_exp)
+ bnum = parse_and_eval_address (bnum_exp);
+ else if (breakpoint_chain == 0)
+ printf_filtered ("No breakpoints.\n");
+ else
+ printf_filtered ("Breakpoints:\n\
+Num Enb Address Where\n");
+
+ breakpoint_1 (bnum);
+}
+
+/* Print a message describing any breakpoints set at PC. */
+
+static void
+describe_other_breakpoints (pc)
+ register CORE_ADDR pc;
+{
+ register int others = 0;
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->address == pc)
+ others++;
+ if (others > 0)
+ {
+ printf ("Note: breakpoint%s ", (others > 1) ? "s" : "");
+ ALL_BREAKPOINTS (b)
+ if (b->address == pc)
+ {
+ others--;
+ printf ("%d%s%s ",
+ b->number,
+ (b->enable == disabled) ? " (disabled)" : "",
+ (others > 1) ? "," : ((others == 1) ? " and" : ""));
+ }
+ printf ("also set at pc 0x%x.\n", pc);
+ }
+}
+
+/* Set the default place to put a breakpoint
+ for the `break' command with no arguments. */
+
+void
+set_default_breakpoint (valid, addr, symtab, line)
+ int valid;
+ CORE_ADDR addr;
+ struct symtab *symtab;
+ int line;
+{
+ default_breakpoint_valid = valid;
+ default_breakpoint_address = addr;
+ default_breakpoint_symtab = symtab;
+ default_breakpoint_line = line;
+}
+
+/* Rescan breakpoints at address ADDRESS,
+ marking the first one as "first" and any others as "duplicates".
+ This is so that the bpt instruction is only inserted once. */
+
+static void
+check_duplicates (address)
+ CORE_ADDR address;
+{
+ register struct breakpoint *b;
+ register int count = 0;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled && b->address == address)
+ {
+ count++;
+ b->duplicate = count > 1;
+ }
+}
+
+/* Low level routine to set a breakpoint.
+ Takes as args the three things that every breakpoint must have.
+ Returns the breakpoint object so caller can set other things.
+ Does not set the breakpoint number!
+ Does not print anything. */
+
+static struct breakpoint *
+set_raw_breakpoint (sal)
+ struct symtab_and_line sal;
+{
+ register struct breakpoint *b, *b1;
+
+ b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
+ bzero (b, sizeof *b);
+ b->address = sal.pc;
+ b->symtab = sal.symtab;
+ b->line_number = sal.line;
+ b->enable = enabled;
+ b->next = 0;
+ b->silent = 0;
+
+ /* Add this breakpoint to the end of the chain
+ so that a list of breakpoints will come out in order
+ of increasing numbers. */
+
+ b1 = breakpoint_chain;
+ if (b1 == 0)
+ breakpoint_chain = b;
+ else
+ {
+ while (b1->next)
+ b1 = b1->next;
+ b1->next = b;
+ }
+
+ check_duplicates (sal.pc);
+
+ return b;
+}
+
+/* Set a breakpoint that will evaporate an end of command
+ at address specified by SAL.
+ Restrict it to frame FRAME if FRAME is nonzero. */
+
+void
+set_momentary_breakpoint (sal, frame)
+ struct symtab_and_line sal;
+ FRAME frame;
+{
+ register struct breakpoint *b;
+ b = set_raw_breakpoint (sal);
+ b->number = -3;
+ b->enable = delete;
+ b->frame = (frame ? FRAME_FP (frame) : 0);
+}
+
+void
+clear_momentary_breakpoints ()
+{
+ register struct breakpoint *b;
+ ALL_BREAKPOINTS (b)
+ if (b->number == -3)
+ {
+ delete_breakpoint (b);
+ break;
+ }
+}
+
+/* Set a breakpoint from a symtab and line.
+ If TEMPFLAG is nonzero, it is a temporary breakpoint.
+ Print the same confirmation messages that the breakpoint command prints. */
+
+void
+set_breakpoint (s, line, tempflag)
+ struct symtab *s;
+ int line;
+ int tempflag;
+{
+ register struct breakpoint *b;
+ struct symtab_and_line sal;
+
+ sal.symtab = s;
+ sal.line = line;
+ sal.pc = find_line_pc (sal.symtab, sal.line);
+ if (sal.pc == 0)
+ error ("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename);
+ else
+ {
+ describe_other_breakpoints (sal.pc);
+
+ b = set_raw_breakpoint (sal);
+ b->number = ++breakpoint_count;
+ b->cond = 0;
+ if (tempflag)
+ b->enable = temporary;
+
+ printf ("Breakpoint %d at 0x%x", b->number, b->address);
+ if (b->symtab)
+ printf (": file %s, line %d.", b->symtab->filename, b->line_number);
+ printf ("\n");
+ }
+}
+
+/* Set a breakpoint according to ARG (function, linenum or *address)
+ and make it temporary if TEMPFLAG is nonzero. */
+
+static void
+break_command_1 (arg, tempflag, from_tty)
+ char *arg;
+ int tempflag, from_tty;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ register struct expression *cond = 0;
+ register struct breakpoint *b;
+ char *save_arg;
+ int i;
+ CORE_ADDR pc;
+
+ sals.sals = NULL;
+ sals.nelts = 0;
+
+ sal.line = sal.pc = sal.end = 0;
+ sal.symtab = 0;
+
+ /* If no arg given, or if first arg is 'if ', use the default breakpoint. */
+
+ if (!arg || (arg[0] == 'i' && arg[1] == 'f'
+ && (arg[2] == ' ' || arg[2] == '\t')))
+ {
+ if (default_breakpoint_valid)
+ {
+ sals.sals = (struct symtab_and_line *)
+ malloc (sizeof (struct symtab_and_line));
+ sal.pc = default_breakpoint_address;
+ sal.line = default_breakpoint_line;
+ sal.symtab = default_breakpoint_symtab;
+ sals.sals[0] = sal;
+ sals.nelts = 1;
+ }
+ else
+ error ("No default breakpoint address now.");
+ }
+ else
+ /* Force almost all breakpoints to be in terms of the
+ current_source_symtab (which is decode_line_1's default). This
+ should produce the results we want almost all of the time while
+ leaving default_breakpoint_* alone. */
+ if (default_breakpoint_valid
+ && (!current_source_symtab
+ || (arg && (*arg == '+' || *arg == '-'))))
+ sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
+ default_breakpoint_line);
+ else
+ sals = decode_line_1 (&arg, 1, 0, 0);
+
+ if (! sals.nelts)
+ return;
+
+ save_arg = arg;
+ for (i = 0; i < sals.nelts; i++)
+ {
+ sal = sals.sals[i];
+ if (sal.pc == 0 && sal.symtab != 0)
+ {
+ pc = find_line_pc (sal.symtab, sal.line);
+ if (pc == 0)
+ error ("No line %d in file \"%s\".",
+ sal.line, sal.symtab->filename);
+ }
+ else
+ pc = sal.pc;
+
+ while (arg && *arg)
+ {
+ if (arg[0] == 'i' && arg[1] == 'f'
+ && (arg[2] == ' ' || arg[2] == '\t'))
+ cond = (struct expression *) parse_c_1 ((arg += 2, &arg),
+ block_for_pc (pc), 0);
+ else
+ error ("Junk at end of arguments.");
+ }
+ arg = save_arg;
+ sals.sals[i].pc = pc;
+ }
+
+ for (i = 0; i < sals.nelts; i++)
+ {
+ sal = sals.sals[i];
+
+ if (from_tty)
+ describe_other_breakpoints (sal.pc);
+
+ b = set_raw_breakpoint (sal);
+ b->number = ++breakpoint_count;
+ b->cond = cond;
+ if (tempflag)
+ b->enable = temporary;
+
+ printf ("Breakpoint %d at 0x%x", b->number, b->address);
+ if (b->symtab)
+ printf (": file %s, line %d.", b->symtab->filename, b->line_number);
+ printf ("\n");
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf ("Multiple breakpoints were set.\n");
+ printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ }
+ free (sals.sals);
+}
+
+static void
+break_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_command_1 (arg, 0, from_tty);
+}
+
+static void
+tbreak_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_command_1 (arg, 1, from_tty);
+}
+
+/*
+ * Helper routine for the until_command routine in infcmd.c. Here
+ * because it uses the mechanisms of breakpoints.
+ */
+void
+until_break_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ FRAME prev_frame = get_prev_frame (selected_frame);
+
+ clear_proceed_status ();
+
+ /* Set a breakpoint where the user wants it and at return from
+ this function */
+
+ if (default_breakpoint_valid)
+ sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
+ default_breakpoint_line);
+ else
+ sals = decode_line_1 (&arg, 1, 0, 0);
+
+ if (sals.nelts != 1)
+ error ("Couldn't get information on specified line.");
+
+ sal = sals.sals[0];
+ free (sals.sals); /* malloc'd, so freed */
+
+ if (*arg)
+ error ("Junk at end of arguments.");
+
+ if (sal.pc == 0 && sal.symtab != 0)
+ sal.pc = find_line_pc (sal.symtab, sal.line);
+
+ if (sal.pc == 0)
+ error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
+
+ set_momentary_breakpoint (sal, selected_frame);
+
+ /* Keep within the current frame */
+
+ if (prev_frame)
+ {
+ struct frame_info *fi;
+
+ fi = get_frame_info (prev_frame);
+ sal = find_pc_line (fi->pc, 0);
+ sal.pc = fi->pc;
+ set_momentary_breakpoint (sal, prev_frame);
+ }
+
+ proceed (-1, -1, 0);
+}
+
+static void
+clear_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b, *b1;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ register struct breakpoint *found;
+ int i;
+
+ if (arg)
+ {
+ sals = decode_line_spec (arg, 1);
+ }
+ else
+ {
+ sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line));
+ sal.line = default_breakpoint_line;
+ sal.symtab = default_breakpoint_symtab;
+ sal.pc = 0;
+ if (sal.symtab == 0)
+ error ("No source file specified.");
+
+ sals.sals[0] = sal;
+ sals.nelts = 1;
+ }
+
+ for (i = 0; i < sals.nelts; i++)
+ {
+ /* If exact pc given, clear bpts at that pc.
+ But if sal.pc is zero, clear all bpts on specified line. */
+ sal = sals.sals[i];
+ found = (struct breakpoint *) 0;
+ while (breakpoint_chain
+ && (sal.pc ? breakpoint_chain->address == sal.pc
+ : (breakpoint_chain->symtab == sal.symtab
+ && breakpoint_chain->line_number == sal.line)))
+ {
+ b1 = breakpoint_chain;
+ breakpoint_chain = b1->next;
+ b1->next = found;
+ found = b1;
+ }
+
+ ALL_BREAKPOINTS (b)
+ while (b->next
+ && (sal.pc ? b->next->address == sal.pc
+ : (b->next->symtab == sal.symtab
+ && b->next->line_number == sal.line)))
+ {
+ b1 = b->next;
+ b->next = b1->next;
+ b1->next = found;
+ found = b1;
+ }
+
+ if (found == 0)
+ error ("No breakpoint at %s.", arg);
+
+ if (found->next) from_tty = 1; /* Always report if deleted more than one */
+ if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : "");
+ while (found)
+ {
+ if (from_tty) printf ("%d ", found->number);
+ b1 = found->next;
+ delete_breakpoint (found);
+ found = b1;
+ }
+ if (from_tty) putchar ('\n');
+ }
+ free (sals.sals);
+}
+
+/* Delete breakpoint number BNUM if it is a `delete' breakpoint.
+ This is called after breakpoint BNUM has been hit.
+ Also delete any breakpoint numbered -3 unless there are breakpoint
+ commands to be executed. */
+
+void
+breakpoint_auto_delete (bnum)
+ int bnum;
+{
+ register struct breakpoint *b;
+ if (bnum != 0)
+ ALL_BREAKPOINTS (b)
+ if (b->number == bnum)
+ {
+ if (b->enable == delete)
+ delete_breakpoint (b);
+ break;
+ }
+ if (breakpoint_commands == 0)
+ clear_momentary_breakpoints ();
+}
+
+static void
+delete_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ register struct breakpoint *b;
+
+ if (bpt->inserted)
+ write_memory (bpt->address, bpt->shadow_contents, sizeof break_insn);
+
+ if (breakpoint_chain == bpt)
+ breakpoint_chain = bpt->next;
+
+ ALL_BREAKPOINTS (b)
+ if (b->next == bpt)
+ {
+ b->next = bpt->next;
+ break;
+ }
+
+ check_duplicates (bpt->address);
+
+ free_command_lines (bpt->commands);
+ if (bpt->cond)
+ free (bpt->cond);
+
+ if (xgdb_verbose && bpt->number >=0)
+ printf ("breakpoint #%d deleted\n", bpt->number);
+
+ free (bpt);
+}
+
+static void map_breakpoint_numbers ();
+
+static void
+delete_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b, *b1;
+
+ if (arg == 0)
+ {
+ /* Ask user only if there are some breakpoints to delete. */
+ if (!from_tty
+ || breakpoint_chain && query ("Delete all breakpoints? "))
+ {
+ /* No arg; clear all breakpoints. */
+ while (breakpoint_chain)
+ delete_breakpoint (breakpoint_chain);
+ }
+ }
+ else
+ map_breakpoint_numbers (arg, delete_breakpoint);
+}
+
+/* Delete all breakpoints.
+ Done when new symtabs are loaded, since the break condition expressions
+ may become invalid, and the breakpoints are probably wrong anyway. */
+
+void
+clear_breakpoints ()
+{
+ delete_command (0, 0);
+}
+
+/* Set ignore-count of breakpoint number BPTNUM to COUNT.
+ If from_tty is nonzero, it prints a message to that effect,
+ which ends with a period (no newline). */
+
+void
+set_ignore_count (bptnum, count, from_tty)
+ int bptnum, count, from_tty;
+{
+ register struct breakpoint *b;
+
+ if (count < 0)
+ count = 0;
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bptnum)
+ {
+ b->ignore_count = count;
+ if (!from_tty)
+ return;
+ else if (count == 0)
+ printf ("Will stop next time breakpoint %d is reached.", bptnum);
+ else if (count == 1)
+ printf ("Will ignore next crossing of breakpoint %d.", bptnum);
+ else
+ printf ("Will ignore next %d crossings of breakpoint %d.",
+ count, bptnum);
+ return;
+ }
+
+ error ("No breakpoint number %d.", bptnum);
+}
+
+/* Clear the ignore counts of all breakpoints. */
+void
+breakpoint_clear_ignore_counts ()
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ b->ignore_count = 0;
+}
+
+/* Command to set ignore-count of breakpoint N to COUNT. */
+
+static void
+ignore_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ register int num;
+
+ if (p == 0)
+ error_no_arg ("a breakpoint number");
+
+ while (*p >= '0' && *p <= '9') p++;
+ if (*p && *p != ' ' && *p != '\t')
+ error ("First argument must be a breakpoint number.");
+
+ num = atoi (args);
+
+ if (*p == 0)
+ error ("Second argument (specified ignore-count) is missing.");
+
+ set_ignore_count (num, parse_and_eval_address (p), from_tty);
+ printf ("\n");
+}
+
+/* Call FUNCTION on each of the breakpoints
+ whose numbers are given in ARGS. */
+
+static void
+map_breakpoint_numbers (args, function)
+ char *args;
+ void (*function) ();
+{
+ register char *p = args;
+ register char *p1;
+ register int num;
+ register struct breakpoint *b;
+
+ if (p == 0)
+ error_no_arg ("one or more breakpoint numbers");
+
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9') p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be breakpoint numbers.");
+
+ num = atoi (p);
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == num)
+ {
+ function (b);
+ goto win;
+ }
+ printf ("No breakpoint number %d.\n", num);
+ win:
+ p = p1;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+}
+
+static void
+enable_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ bpt->enable = enabled;
+
+ if (xgdb_verbose && bpt->number >= 0)
+ printf ("breakpoint #%d enabled\n", bpt->number);
+
+ check_duplicates (bpt->address);
+}
+
+static void
+enable_command (args)
+ char *args;
+{
+ struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ enable_breakpoint (bpt);
+ else
+ map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+static void
+disable_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ bpt->enable = disabled;
+
+ if (xgdb_verbose && bpt->number >= 0)
+ printf ("breakpoint #%d disabled\n", bpt->number);
+
+ check_duplicates (bpt->address);
+}
+
+static void
+disable_command (args)
+ char *args;
+{
+ register struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ disable_breakpoint (bpt);
+ else
+ map_breakpoint_numbers (args, disable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ bpt->enable = temporary;
+
+ check_duplicates (bpt->address);
+}
+
+static void
+enable_once_command (args)
+ char *args;
+{
+ map_breakpoint_numbers (args, enable_once_breakpoint);
+}
+
+static void
+enable_delete_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ bpt->enable = delete;
+
+ check_duplicates (bpt->address);
+}
+
+static void
+enable_delete_command (args)
+ char *args;
+{
+ map_breakpoint_numbers (args, enable_delete_breakpoint);
+}
+
+/*
+ * Use default_breakpoint_'s, or nothing if they aren't valid.
+ */
+struct symtabs_and_lines
+decode_line_spec_1 (string, funfirstline)
+ char *string;
+ int funfirstline;
+{
+ struct symtabs_and_lines sals;
+ if (string == 0)
+ error ("Empty line specification.");
+ if (default_breakpoint_valid)
+ sals = decode_line_1 (&string, funfirstline,
+ default_breakpoint_symtab, default_breakpoint_line);
+ else
+ sals = decode_line_1 (&string, funfirstline, 0, 0);
+ if (*string)
+ error ("Junk at end of line specification: %s", string);
+ return sals;
+}
+
+
+/* Chain containing all defined enable commands. */
+
+extern struct cmd_list_element
+ *enablelist, *disablelist,
+ *deletelist, *enablebreaklist;
+
+extern struct cmd_list_element *cmdlist;
+
+void
+_initialize_breakpoint ()
+{
+ breakpoint_chain = 0;
+ breakpoint_count = 0;
+
+ add_com ("ignore", class_breakpoint, ignore_command,
+ "Set ignore-count of breakpoint number N to COUNT.");
+
+ add_com ("commands", class_breakpoint, commands_command,
+ "Set commands to be executed when a breakpoint is hit.\n\
+Give breakpoint number as argument after \"commands\".\n\
+With no argument, the targeted breakpoint is the last one set.\n\
+The commands themselves follow starting on the next line.\n\
+Type a line containing \"end\" to indicate the end of them.\n\
+Give \"silent\" as the first line to make the breakpoint silent;\n\
+then no output is printed when it is hit, except what the commands print.");
+
+ add_com ("condition", class_breakpoint, condition_command,
+ "Specify breakpoint number N to break only if COND is true.\n\
+N is an integer; COND is a C expression to be evaluated whenever\n\
+breakpoint N is reached. Actually break only when COND is nonzero.");
+
+ add_com ("tbreak", class_breakpoint, tbreak_command,
+ "Set a temporary breakpoint. Args like \"break\" command.\n\
+Like \"break\" except the breakpoint is only enabled temporarily,\n\
+so it will be disabled when hit. Equivalent to \"break\" followed\n\
+by using \"enable once\" on the breakpoint number.");
+
+ add_prefix_cmd ("enable", class_breakpoint, enable_command,
+ "Enable some breakpoints or auto-display expressions.\n\
+Give breakpoint numbers (separated by spaces) as arguments.\n\
+With no subcommand, breakpoints are enabled until you command otherwise.\n\
+This is used to cancel the effect of the \"disable\" command.\n\
+With a subcommand you can enable temporarily.\n\
+\n\
+The \"display\" subcommand applies to auto-displays instead of breakpoints.",
+ &enablelist, "enable ", 1, &cmdlist);
+
+ add_abbrev_prefix_cmd ("breakpoints", class_breakpoint, enable_command,
+ "Enable some breakpoints or auto-display expressions.\n\
+Give breakpoint numbers (separated by spaces) as arguments.\n\
+With no subcommand, breakpoints are enabled until you command otherwise.\n\
+This is used to cancel the effect of the \"disable\" command.\n\
+May be abbreviates to simply \"enable\".\n\
+With a subcommand you can enable temporarily.",
+ &enablebreaklist, "enable breakpoints ", 1, &enablelist);
+
+ add_cmd ("once", no_class, enable_once_command,
+ "Enable breakpoints for one hit. Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\
+See the \"tbreak\" command which sets a breakpoint and enables it once.",
+ &enablebreaklist);
+
+ add_cmd ("delete", no_class, enable_delete_command,
+ "Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it is deleted.",
+ &enablebreaklist);
+
+ add_cmd ("delete", no_class, enable_delete_command,
+ "Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it is deleted.",
+ &enablelist);
+
+ add_cmd ("once", no_class, enable_once_command,
+ "Enable breakpoints for one hit. Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\
+See the \"tbreak\" command which sets a breakpoint and enables it once.",
+ &enablelist);
+
+ add_prefix_cmd ("disable", class_breakpoint, disable_command,
+ "Disable some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To disable all breakpoints, give no argument.\n\
+A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\
+\n\
+The \"display\" subcommand applies to auto-displays instead of breakpoints.",
+ &disablelist, "disable ", 1, &cmdlist);
+ add_com_alias ("dis", "disable", class_breakpoint, 1);
+ add_com_alias ("disa", "disable", class_breakpoint, 1);
+
+ add_abbrev_cmd ("breakpoints", class_breakpoint, disable_command,
+ "Disable some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To disable all breakpoints, give no argument.\n\
+A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\
+This command may be abbreviated \"disable\".",
+ &disablelist);
+
+ add_prefix_cmd ("delete", class_breakpoint, delete_command,
+ "Delete some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.\n\
+\n\
+Also a prefix command for deletion of other GDB objects.\n\
+The \"unset\" command is also an alias for \"delete\".",
+ &deletelist, "delete ", 1, &cmdlist);
+ add_com_alias ("d", "delete", class_breakpoint, 1);
+ add_com_alias ("unset", "delete", class_alias, 1);
+
+ add_cmd ("breakpoints", class_alias, delete_command,
+ "Delete some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.\n\
+This command may be abbreviated \"delete\".",
+ &deletelist);
+
+ add_com ("clear", class_breakpoint, clear_command,
+ "Clear breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, all breakpoints in that line are cleared.\n\
+If function is specified, breakpoints at beginning of function are cleared.\n\
+If an address is specified, breakpoints at that address are cleared.\n\n\
+With no argument, clears all breakpoints in the line that the selected frame\n\
+is executing in.\n\
+\n\
+See also the \"delete\" command which clears breakpoints by number.");
+
+ add_com ("break", class_breakpoint, break_command,
+ "Set breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, break at start of code for that line.\n\
+If function is specified, break at start of code for that function.\n\
+If an address is specified, break at that exact address.\n\
+With no arg, uses current execution address of selected stack frame.\n\
+This is useful for breaking on return to a stack frame.\n\
+\n\
+Multiple breakpoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.");
+ add_com_alias ("b", "break", class_run, 1);
+ add_com_alias ("br", "break", class_run, 1);
+ add_com_alias ("bre", "break", class_run, 1);
+ add_com_alias ("brea", "break", class_run, 1);
+
+ add_info ("breakpoints", breakpoints_info,
+ "Status of all breakpoints, or breakpoint number NUMBER.\n\
+Second column is \"y\" for enabled breakpoint, \"n\" for disabled,\n\
+\"o\" for enabled once (disable when hit), \"d\" for enable but delete when hit.\n\
+Then come the address and the file/line number.\n\n\
+Convenience variable \"$_\" and default examine address for \"x\"\n\
+are set to the address of the last breakpoint listed.");
+}
+
diff --git a/gnu/usr.bin/kgdb/command.c b/gnu/usr.bin/kgdb/command.c
new file mode 100644
index 000000000000..79daea490383
--- /dev/null
+++ b/gnu/usr.bin/kgdb/command.c
@@ -0,0 +1,856 @@
+/* Library for reading command lines and decoding commands.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "command.h"
+#include "defs.h"
+#include <stdio.h>
+#include <ctype.h>
+
+extern char *xmalloc ();
+
+/* Add element named NAME to command list *LIST.
+ FUN should be the function to execute the command;
+ it will get a character string as argument, with leading
+ and trailing blanks already eliminated.
+
+ DOC is a documentation string for the command.
+ Its first line should be a complete sentence.
+ It should start with ? for a command that is an abbreviation
+ or with * for a command that most users don't need to know about. */
+
+struct cmd_list_element *
+add_cmd (name, class, fun, doc, list)
+ char *name;
+ int class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+ delete_cmd (name, list);
+ c->next = *list;
+ c->name = savestring (name, strlen (name));
+ c->class = class;
+ c->function = fun;
+ c->doc = doc;
+ c->prefixlist = 0;
+ c->allow_unknown = 0;
+ c->abbrev_flag = 0;
+ c->aux = 0;
+ *list = c;
+ return c;
+}
+
+/* Same as above, except that the abbrev_flag is set. */
+
+struct cmd_list_element *
+add_abbrev_cmd (name, class, fun, doc, list)
+ char *name;
+ int class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+ delete_cmd (name, list);
+ c->next = *list;
+ c->name = savestring (name, strlen (name));
+ c->class = class;
+ c->function = fun;
+ c->doc = doc;
+ c->prefixlist = 0;
+ c->allow_unknown = 0;
+ c->abbrev_flag = 1;
+ c->aux = 0;
+ *list = c;
+ return c;
+}
+
+struct cmd_list_element *
+add_alias_cmd (name, oldname, class, abbrev_flag, list)
+ char *name;
+ char *oldname;
+ int class;
+ int abbrev_flag;
+ struct cmd_list_element **list;
+{
+ /* Must do this since lookup_cmd tries to side-effect its first arg */
+ char *copied_name;
+ register struct cmd_list_element *old;
+ register struct cmd_list_element *c;
+ copied_name = (char *) alloca (strlen (oldname) + 1);
+ strcpy (copied_name, oldname);
+ old = lookup_cmd (&copied_name, *list, 0, 1, 1);
+
+ if (old == 0)
+ {
+ delete_cmd (name, list);
+ return 0;
+ }
+
+ c = add_cmd (name, class, old->function, old->doc, list);
+ c->prefixlist = old->prefixlist;
+ c->prefixname = old->prefixname;
+ c->allow_unknown = old->allow_unknown;
+ c->abbrev_flag = abbrev_flag;
+ c->aux = old->aux;
+ return c;
+}
+
+/* Like add_cmd but adds an element for a command prefix:
+ a name that should be followed by a subcommand to be looked up
+ in another command list. PREFIXLIST should be the address
+ of the variable containing that list. */
+
+struct cmd_list_element *
+add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+ allow_unknown, list)
+ char *name;
+ int class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ return c;
+}
+
+/* Like add_prefix_cmd butsets the abbrev_flag on the new command. */
+
+struct cmd_list_element *
+add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+ allow_unknown, list)
+ char *name;
+ int class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ c->abbrev_flag = 1;
+ return c;
+}
+
+/* Remove the command named NAME from the command list. */
+
+void
+delete_cmd (name, list)
+ char *name;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c;
+
+ while (*list && !strcmp ((*list)->name, name))
+ {
+ *list = (*list)->next;
+ }
+
+ if (*list)
+ for (c = *list; c->next;)
+ {
+ if (!strcmp (c->next->name, name))
+ c->next = c->next->next;
+ else
+ c = c->next;
+ }
+}
+
+void help_cmd (), help_list (), help_cmd_list ();
+
+/* This command really has to deal with two things:
+ * 1) I want documentation on *this string* (usually called by
+ * "help commandname").
+ * 2) I want documentation on *this list* (usually called by
+ * giving a command that requires subcommands. Also called by saying
+ * just "help".)
+ *
+ * I am going to split this into two seperate comamnds, help_cmd and
+ * help_list.
+ */
+
+void
+help_cmd (command, stream)
+ char *command;
+ FILE *stream;
+{
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
+
+ if (!command)
+ {
+ help_list (cmdlist, "", -2, stream);
+ return;
+ }
+
+ c = lookup_cmd (&command, cmdlist, "", 0, 0);
+
+ if (c == 0)
+ return;
+
+ /* There are three cases here.
+ If c->prefixlist is nonzer, we have a prefix command.
+ Print its documentation, then list its subcommands.
+
+ If c->function is nonzero, we really have a command.
+ Print its documentation and return.
+
+ If c->function is zero, we have a class name.
+ Print its documentation (as if it were a command)
+ and then set class to he number of this class
+ so that the commands in the class will be listed. */
+
+ fputs_filtered (c->doc, stream);
+ fputs_filtered ("\n", stream);
+
+ if (c->prefixlist == 0 && c->function != 0)
+ return;
+ fprintf_filtered (stream, "\n");
+
+ /* If this is a prefix command, print it's subcommands */
+ if (c->prefixlist)
+ help_list (*c->prefixlist, c->prefixname, -1, stream);
+
+ /* If this is a class name, print all of the commands in the class */
+ if (c->function == 0)
+ help_list (cmdlist, "", c->class, stream);
+}
+
+/*
+ * Get a specific kind of help on a command list.
+ *
+ * LIST is the list.
+ * CMDTYPE is the prefix to use in the title string.
+ * CLASS is the class with which to list the nodes of this list (see
+ * documentation for help_cmd_list below), As usual, -1 for
+ * everything, -2 for just classes, and non-negative for only things
+ * in a specific class.
+ * and STREAM is the output stream on which to print things.
+ * If you call this routine with a class >= 0, it recurses.
+ */
+void
+help_list (list, cmdtype, class, stream)
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int class;
+ FILE *stream;
+{
+ int len;
+ char *cmdtype1, *cmdtype2;
+
+ /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */
+ len = strlen (cmdtype);
+ cmdtype1 = (char *) alloca (len + 1);
+ cmdtype1[0] = 0;
+ cmdtype2 = (char *) alloca (len + 4);
+ cmdtype2[0] = 0;
+ if (len)
+ {
+ cmdtype1[0] = ' ';
+ strncpy (cmdtype1 + 1, cmdtype, len - 1);
+ cmdtype1[len] = 0;
+ strncpy (cmdtype2, cmdtype, len - 1);
+ strcpy (cmdtype2 + len - 1, " sub");
+ }
+
+ if (class == -2)
+ fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
+ else
+ fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
+
+ help_cmd_list (list, class, cmdtype, (class >= 0), stream);
+
+ if (class == -2)
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by a class name for a list of commands in that class.",
+ cmdtype1);
+
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by %scommand name for full documentation.\n\
+Command name abbreviations are allowed if unambiguous.\n",
+ cmdtype1, cmdtype2);
+}
+
+
+/*
+ * Implement a help command on command list LIST.
+ * RECURSE should be non-zero if this should be done recursively on
+ * all sublists of LIST.
+ * PREFIX is the prefix to print before each command name.
+ * STREAM is the stream upon which the output should be written.
+ * CLASS should be:
+ * A non-negative class number to list only commands in that
+ * class.
+ * -1 to list all commands in list.
+ * -2 to list all classes in list.
+ *
+ * Note that RECURSE will be active on *all* sublists, not just the
+ * ones seclected by the criteria above (ie. the selection mechanism
+ * is at the low level, not the high-level).
+ */
+void
+help_cmd_list (list, class, prefix, recurse, stream)
+ struct cmd_list_element *list;
+ int class;
+ char *prefix;
+ int recurse;
+ FILE *stream;
+{
+ register struct cmd_list_element *c;
+ register char *p;
+ static char *line_buffer = 0;
+ static int line_size;
+
+ if (!line_buffer)
+ {
+ line_size = 80;
+ line_buffer = (char *) xmalloc (line_size);
+ }
+
+ for (c = list; c; c = c->next)
+ {
+ if (c->abbrev_flag == 0 &&
+ (class == -1
+ || (class == -2 && c->function == 0)
+ || (class == c->class && c->function != 0)))
+ {
+ fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+ /* Print just the first line */
+ p = c->doc;
+ while (*p && *p != '\n') p++;
+ if (p - c->doc > line_size - 1)
+ {
+ line_size = p - c->doc + 1;
+ free (line_buffer);
+ line_buffer = (char *) xmalloc (line_size);
+ }
+ strncpy (line_buffer, c->doc, p - c->doc);
+ line_buffer[p - c->doc] = '\0';
+ fputs_filtered (line_buffer, stream);
+ fputs_filtered ("\n", stream);
+ }
+ if (recurse
+ && c->prefixlist != 0
+ && c->abbrev_flag == 0)
+ help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
+ }
+}
+
+/* This routine takes a line of TEXT and a CLIST in which to
+ start the lookup. When it returns it will have incremented the text
+ pointer past the section of text it matched, set *RESULT_LIST to
+ the list in which the last word was matched, and will return the
+ cmd list element which the text matches. It will return 0 if no
+ match at all was possible. It will return -1 if ambigous matches are
+ possible; in this case *RESULT_LIST will be set to the list in which
+ there are ambiguous choices (and text will be set to the ambiguous
+ text string).
+
+ It does no error reporting whatsoever; control will always return
+ to the superior routine.
+
+ In the case of an ambiguous return (-1), *RESULT_LIST will be set to
+ point at the prefix_command (ie. the best match) *or* (special
+ case) will be 0 if no prefix command was ever found. For example,
+ in the case of "info a", "info" matches without ambiguity, but "a"
+ could be "args" or "address", so *RESULT_LIST is set to
+ the cmd_list_element for "info". So in this case
+ result list should not be interpeted as a pointer to the beginning
+ of a list; it simply points to a specific command.
+
+ This routine does *not* modify the text pointed to by TEXT.
+
+ If INGNORE_HELP_CLASSES is nonzero, ignore any command list
+ elements which are actually help classes rather than commands (i.e.
+ the function field of the struct cmd_list_element is 0). */
+
+struct cmd_list_element *
+lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
+ char **text;
+ struct cmd_list_element *clist, **result_list;
+ int ignore_help_classes;
+{
+ char *p, *command;
+ int len, tmp, nfound;
+ struct cmd_list_element *found, *c;
+
+ while (**text == ' ' || **text == '\t')
+ (*text)++;
+
+ /* Treating underscores as part of command words is important
+ so that "set args_foo()" doesn't get interpreted as
+ "set args _foo()". */
+ for (p = *text;
+ *p && (isalnum(*p) || *p == '-' || *p == '_');
+ p++)
+ ;
+
+ /* If nothing but whitespace, return 0. */
+ if (p == *text)
+ return 0;
+
+ len = p - *text;
+
+ /* *text and p now bracket the first command word to lookup (and
+ it's length is len). We copy this into a local temporary,
+ converting to lower case as we go. */
+
+ command = (char *) alloca (len + 1);
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = (*text)[tmp];
+ command[tmp] = (x >= 'A' && x <= 'Z') ? x - 'A' + 'a' : x;
+ }
+ command[len] = '\0';
+
+ /* Look it up. */
+ found = 0;
+ nfound = 0;
+ for (c = clist; c; c = c->next)
+ if (!strncmp (command, c->name, len)
+ && (!ignore_help_classes || c->function))
+ {
+ found = c;
+ nfound++;
+ if (c->name[len] == '\0')
+ {
+ nfound = 1;
+ break;
+ }
+ }
+
+ /* If nothing matches, we have a simple failure. */
+ if (nfound == 0)
+ return 0;
+
+ if (nfound > 1)
+ {
+ *result_list = 0; /* Will be modified in calling routine
+ if we know what the prefix command is.
+ */
+ return (struct cmd_list_element *) -1; /* Ambiguous. */
+ }
+
+ /* We've matched something on this list. Move text pointer forward. */
+
+ *text = p;
+ if (found->prefixlist)
+ {
+ c = lookup_cmd_1 (text, *found->prefixlist, result_list,
+ ignore_help_classes);
+ if (!c)
+ {
+ /* Didn't find anything; this is as far as we got. */
+ *result_list = clist;
+ return found;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* We've gotten this far properley, but the next step
+ is ambiguous. We need to set the result list to the best
+ we've found (if an inferior hasn't already set it). */
+ if (!*result_list)
+ /* This used to say *result_list = *found->prefixlist
+ If that was correct, need to modify the documentation
+ at the top of this function to clarify what is supposed
+ to be going on. */
+ *result_list = found;
+ return c;
+ }
+ else
+ {
+ /* We matched! */
+ return c;
+ }
+ }
+ else
+ {
+ *result_list = clist;
+ return found;
+ }
+}
+
+/* Look up the contents of *LINE as a command in the command list LIST.
+ LIST is a chain of struct cmd_list_element's.
+ If it is found, return the struct cmd_list_element for that command
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message.
+
+ If INGNORE_HELP_CLASSES is nonzero, ignore any command list
+ elements which are actually help classes rather than commands (i.e.
+ the function field of the struct cmd_list_element is 0). */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+ int ignore_help_classes;
+{
+ struct cmd_list_element *last_list = 0;
+ struct cmd_list_element *c =
+ lookup_cmd_1 (line, list, &last_list, ignore_help_classes);
+ char *ptr = (*line) + strlen (*line) - 1;
+
+ /* Clear off trailing whitespace. */
+ while (ptr >= *line && (*ptr == ' ' || *ptr == '\t'))
+ ptr--;
+ *(ptr + 1) = '\0';
+
+ if (!c)
+ {
+ if (!allow_unknown)
+ {
+ if (!*line)
+ error ("Lack of needed %scommand", cmdtype);
+ else
+ {
+ char *p = *line, *q;
+
+ while (isalnum(*p) || *p == '-')
+ p++;
+
+ q = (char *) alloca (p - *line + 1);
+ strncpy (q, *line, p - *line);
+ q[p-*line] = '\0';
+
+ error ("Undefined %scommand: \"%s\".", cmdtype, q);
+ }
+ }
+ else
+ return 0;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* Ambigous. Local values should be off prefixlist or called
+ values. */
+ int local_allow_unknown = (last_list ? last_list->allow_unknown :
+ allow_unknown);
+ char *local_cmdtype = last_list ? last_list->prefixname : cmdtype;
+ struct cmd_list_element *local_list =
+ (last_list ? *(last_list->prefixlist) : list);
+
+ if (local_allow_unknown < 0)
+ {
+ if (last_list)
+ return last_list; /* Found something. */
+ else
+ return 0; /* Found nothing. */
+ }
+ else
+ {
+ /* Report as error. */
+ int amb_len;
+ char ambbuf[100];
+
+ for (amb_len = 0;
+ ((*line)[amb_len] && (*line)[amb_len] != ' '
+ && (*line)[amb_len] != '\t');
+ amb_len++)
+ ;
+
+ ambbuf[0] = 0;
+ for (c = local_list; c; c = c->next)
+ if (!strncmp (*line, c->name, amb_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
+ *line, ambbuf);
+ }
+ }
+ else
+ {
+ /* We've got something. It may still not be what the caller
+ wants (if this command *needs* a subcommand). */
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ if (c->prefixlist && **line && !c->allow_unknown)
+ error ("Undefined %scommand: \"%s\".", c->prefixname, *line);
+
+ /* Seems to be what he wants. Return it. */
+ return c;
+ }
+}
+
+#if 0
+/* Look up the contents of *LINE as a command in the command list LIST.
+ LIST is a chain of struct cmd_list_element's.
+ If it is found, return the struct cmd_list_element for that command
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message. */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+{
+ register char *p;
+ register struct cmd_list_element *c, *found;
+ int nfound;
+ char ambbuf[100];
+ char *processed_cmd;
+ int i, cmd_len;
+
+ /* Skip leading whitespace. */
+
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ /* Clear out trailing whitespace. */
+
+ p = *line + strlen (*line);
+ while (p != *line && (p[-1] == ' ' || p[-1] == '\t'))
+ p--;
+ *p = 0;
+
+ /* Find end of command name. */
+
+ p = *line;
+ while (*p == '-'
+ || (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z')
+ || (*p >= '0' && *p <= '9'))
+ p++;
+
+ /* Look up the command name.
+ If exact match, keep that.
+ Otherwise, take command abbreviated, if unique. Note that (in my
+ opinion) a null string does *not* indicate ambiguity; simply the
+ end of the argument. */
+
+ if (p == *line)
+ {
+ if (!allow_unknown)
+ error ("Lack of needed %scommand", cmdtype);
+ return 0;
+ }
+
+ /* Copy over to a local buffer, converting to lowercase on the way.
+ This is in case the command being parsed is a subcommand which
+ doesn't match anything, and that's ok. We want the original
+ untouched for the routine of the original command. */
+
+ processed_cmd = (char *) alloca (p - *line + 1);
+ for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
+ {
+ char x = (*line)[cmd_len];
+ if (x >= 'A' && x <= 'Z')
+ processed_cmd[cmd_len] = x - 'A' + 'a';
+ else
+ processed_cmd[cmd_len] = x;
+ }
+ processed_cmd[cmd_len] = '\0';
+
+ /* Check all possibilities in the current command list. */
+ found = 0;
+ nfound = 0;
+ for (c = list; c; c = c->next)
+ {
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ found = c;
+ nfound++;
+ if (c->name[cmd_len] == 0)
+ {
+ nfound = 1;
+ break;
+ }
+ }
+ }
+
+ /* Report error for undefined command name. */
+
+ if (nfound != 1)
+ {
+ if (nfound > 1 && allow_unknown >= 0)
+ {
+ ambbuf[0] = 0;
+ for (c = list; c; c = c->next)
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
+ processed_cmd, ambbuf);
+ }
+ else if (!allow_unknown)
+ error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
+ return 0;
+ }
+
+ /* Skip whitespace before the argument. */
+
+ while (*p == ' ' || *p == '\t') p++;
+ *line = p;
+
+ if (found->prefixlist && *p)
+ {
+ c = lookup_cmd (line, *found->prefixlist, found->prefixname,
+ found->allow_unknown);
+ if (c)
+ return c;
+ }
+
+ return found;
+}
+#endif
+
+/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
+
+/* Return a vector of char pointers which point to the different
+ possible completions in LIST of TEXT. */
+
+char **
+complete_on_cmdlist (list, text)
+ struct cmd_list_element *list;
+ char *text;
+{
+ struct cmd_list_element *ptr;
+ char **matchlist;
+ int sizeof_matchlist;
+ int matches;
+ int textlen = strlen (text);
+
+ sizeof_matchlist = 10;
+ matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
+ matches = 0;
+
+ for (ptr = list; ptr; ptr = ptr->next)
+ if (!strncmp (ptr->name, text, textlen)
+ && !ptr->abbrev_flag
+ && (ptr->function
+ || ptr->prefixlist))
+ {
+ if (matches == sizeof_matchlist)
+ {
+ sizeof_matchlist *= 2;
+ matchlist = (char **) xrealloc (matchlist,
+ (sizeof_matchlist
+ * sizeof (char *)));
+ }
+
+ matchlist[matches] = (char *)
+ xmalloc (strlen (ptr->name) + 1);
+ strcpy (matchlist[matches++], ptr->name);
+ }
+
+ if (matches == 0)
+ {
+ free (matchlist);
+ matchlist = 0;
+ }
+ else
+ {
+ matchlist = (char **) xrealloc (matchlist, ((matches + 1)
+ * sizeof (char *)));
+ matchlist[matches] = (char *) 0;
+ }
+
+ return matchlist;
+}
+
+static void
+shell_escape (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int rc, status, pid;
+ char *p, *user_shell;
+ extern char *rindex ();
+
+ if ((user_shell = (char *) getenv ("SHELL")) == NULL)
+ user_shell = "/bin/sh";
+
+ /* Get the name of the shell for arg0 */
+ if ((p = rindex (user_shell, '/')) == NULL)
+ p = user_shell;
+ else
+ p++; /* Get past '/' */
+
+ if ((pid = fork()) == 0)
+ {
+ if (!arg)
+ execl (user_shell, p, 0);
+ else
+ execl (user_shell, p, "-c", arg, 0);
+
+ fprintf (stderr, "Exec of shell failed\n");
+ exit (0);
+ }
+
+ if (pid != -1)
+ while ((rc = wait (&status)) != pid && rc != -1)
+ ;
+ else
+ error ("Fork failed");
+}
+
+void
+_initialize_command ()
+{
+ add_com ("shell", class_support, shell_escape,
+ "Execute the rest of the line as a shell command. \n\
+With no arguments, run an inferior shell.");
+}
diff --git a/gnu/usr.bin/kgdb/command.h b/gnu/usr.bin/kgdb/command.h
new file mode 100644
index 000000000000..fe28aef817ae
--- /dev/null
+++ b/gnu/usr.bin/kgdb/command.h
@@ -0,0 +1,77 @@
+/* Header file for command-reading library command.c.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This structure records one command'd definition. */
+
+struct cmd_list_element
+ {
+ /* Points to next command in this list. */
+ struct cmd_list_element *next;
+
+ /* Name of this command. */
+ char *name;
+
+ /* Command class; class values are chosen by application program. */
+ int class;
+
+ /* Function definition of this command.
+ Zero for command class names and for help topics that
+ are not really commands. */
+ void (*function) ();
+
+ /* Documentation of this command (or help topic).
+ First line is brief documentation; remaining lines form, with it,
+ the full documentation. First line should end with a period.
+ Entire string should also end with a period, not a newline. */
+ char *doc;
+
+ /* Auxiliary information.
+ It is up to the calling program to decide what this means. */
+ char *aux;
+
+ /* Nonzero identifies a prefix command. For them, the address
+ of the variable containing the list of subcommands. */
+ struct cmd_list_element **prefixlist;
+
+ /* For prefix commands only:
+ String containing prefix commands to get here: this one
+ plus any others needed to get to it. Should end in a space.
+ It is used before the word "command" in describing the
+ commands reached through this prefix. */
+ char *prefixname;
+
+ /* For prefix commands only:
+ nonzero means do not get an error if subcommand is not
+ recognized; call the prefix's own function in that case. */
+ char allow_unknown;
+
+ /* Nonzero says this is an abbreviation, and should not
+ be mentioned in lists of commands.
+ This allows "br<tab>" to complete to "break", which it
+ otherwise wouldn't. */
+ char abbrev_flag;
+ };
+
+/* Forward-declarations of the entry-points of command.c. */
+
+extern struct cmd_list_element *add_cmd ();
+extern struct cmd_list_element *add_alias_cmd ();
+extern struct cmd_list_element *add_prefix_cmd ();
+extern struct cmd_list_element *lookup_cmd (), *lookup_cmd_1 ();
+extern char **complete_on_cmdlist ();
+extern void delete_cmd ();
+extern void help_cmd ();
diff --git a/gnu/usr.bin/kgdb/config/Makefile.i386 b/gnu/usr.bin/kgdb/config/Makefile.i386
new file mode 100644
index 000000000000..cc52aa3b13d4
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/Makefile.i386
@@ -0,0 +1,6 @@
+# @(#)Makefile.i386 6.2 (Berkeley) 3/21/91
+
+CONFIGSRCS= i386bsd-dep.c i386-pinsn.c
+
+param.h:
+ ln -s $(.CURDIR)/config/m-i386bsd.h param.h
diff --git a/gnu/usr.bin/kgdb/config/default-dep.c b/gnu/usr.bin/kgdb/config/default-dep.c
new file mode 100644
index 000000000000..13fe7b95a49e
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/default-dep.c
@@ -0,0 +1,585 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)default-dep.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h> Can we live without this? */
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#include <a.out.h>
+#endif
+#ifndef N_SET_MAGIC
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+extern int errno;
+
+/* This function simply calls ptrace with the given arguments.
+ It exists so that all calls to ptrace are isolated in this
+ machine-dependent file. */
+int
+call_ptrace (request, pid, arg3, arg4)
+ int request, pid, arg3, arg4;
+{
+ return ptrace (request, pid, arg3, arg4);
+}
+
+kill_inferior ()
+{
+ if (remote_debugging)
+ return;
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ inferior_died ();
+}
+
+/* This is used when GDB is exiting. It gives less chance of error.*/
+
+kill_inferior_fast ()
+{
+ if (remote_debugging)
+ return;
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+resume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ if (remote_debugging)
+ remote_resume (step, signal);
+ else
+ {
+ ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+ }
+}
+
+void
+fetch_inferior_registers ()
+{
+ register int regno;
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct user u;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct user u;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+ if (regno >= 0)
+ {
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR.
+ On failure (cannot read from inferior, usually because address is out
+ of bounds) returns the value of errno. */
+
+int
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+#if 0
+ /* This is now done by read_memory, because when this function did it,
+ reading a byte or short int hardware port read whole longs, causing
+ serious side effects
+ such as bus errors and unexpected hardware operation. This would
+ also be a problem with ptrace if the inferior process could read
+ or write hardware registers, but that's not usually the case. */
+ if (remote_debugging)
+ buffer[i] = remote_fetch_word (addr);
+ else
+#endif
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ if (errno)
+ return errno;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+ return 0;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (remote_debugging)
+ return (remote_write_inferior_memory(memaddr, myaddr, len));
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ buffer[count - 1] = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(hdr) 0
+#endif /* no N_TXTADDR */
+
+#ifndef N_DATADDR
+#define N_DATADDR(hdr) hdr.a_text
+#endif /* no N_DATADDR */
+
+/* Make COFF and non-COFF names for things a little more compatible
+ to reduce conditionals later. */
+
+#ifdef COFF_FORMAT
+#define a_magic magic
+#endif
+
+#ifndef COFF_FORMAT
+#ifndef AOUTHDR
+#define AOUTHDR struct exec
+#endif
+#endif
+
+extern char *sys_siglist[];
+
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+/* File names of core file and executable file. */
+
+extern char *corefile;
+extern char *execfile;
+
+/* Descriptors on which core file and executable file are open.
+ Note that the execchan is closed when an inferior is created
+ and reopened if the inferior dies or is killed. */
+
+extern int corechan;
+extern int execchan;
+
+/* Last modification time of executable file.
+ Also used in source.c to compare against mtime of a source file. */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file. */
+
+extern CORE_ADDR data_start;
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+ Note that the data area in the exec file is used only when there is no core file. */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data. */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data. */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data. */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data. */
+
+extern int stack_offset;
+
+#ifdef COFF_FORMAT
+/* various coff data structures */
+
+extern FILHDR file_hdr;
+extern SCNHDR text_hdr;
+extern SCNHDR data_hdr;
+
+#endif /* not COFF_FORMAT */
+
+/* a.out header saved in core file. */
+
+extern AOUTHDR core_aouthdr;
+
+/* a.out header of exec file. */
+
+extern AOUTHDR exec_aouthdr;
+
+extern void validate_files ();
+
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+
+ /* We are depending on exec_file_command having been called
+ previously to set exec_data_start. Since the executable
+ and the core file share the same text segment, the address
+ of the data segment will be the same in both. */
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (reg_names[regno])
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
+
+exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end -= exec_data_start;
+ text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+#ifdef COFF_FORMAT
+ {
+ int aout_hdrsize;
+ int num_sections;
+
+ if (read_file_hdr (execchan, &file_hdr) < 0)
+ error ("\"%s\": not in executable format.", execfile);
+
+ aout_hdrsize = file_hdr.f_opthdr;
+ num_sections = file_hdr.f_nscns;
+
+ if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
+ error ("\"%s\": can't read optional aouthdr", execfile);
+
+ if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
+ aout_hdrsize) < 0)
+ error ("\"%s\": can't read text section header", execfile);
+
+ if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
+ aout_hdrsize) < 0)
+ error ("\"%s\": can't read data section header", execfile);
+
+ text_start = exec_aouthdr.text_start;
+ text_end = text_start + exec_aouthdr.tsize;
+ text_offset = text_hdr.s_scnptr;
+ exec_data_start = exec_aouthdr.data_start;
+ exec_data_end = exec_data_start + exec_aouthdr.dsize;
+ exec_data_offset = data_hdr.s_scnptr;
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+ exec_mtime = file_hdr.f_timdat;
+ }
+#else /* not COFF_FORMAT */
+ {
+ struct stat st_exec;
+
+#ifdef HEADER_SEEK_FD
+ HEADER_SEEK_FD (execchan);
+#endif
+
+ val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
+
+ if (val < 0)
+ perror_with_name (filename);
+
+ text_start = N_TXTADDR (exec_aouthdr);
+ exec_data_start = N_DATADDR (exec_aouthdr);
+
+ text_offset = N_TXTOFF (exec_aouthdr);
+ exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+
+ text_end = text_start + exec_aouthdr.a_text;
+ exec_data_end = exec_data_start + exec_aouthdr.a_data;
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+
+ if (fstat (execchan, &st_exec) < 0)
+ perror_with_name (filename);
+ exec_mtime = st_exec.st_mtime;
+ }
+#endif /* not COFF_FORMAT */
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No exec file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
diff --git a/gnu/usr.bin/kgdb/config/i386-dep.c b/gnu/usr.bin/kgdb/config/i386-dep.c
new file mode 100644
index 000000000000..c4630d0c07ac
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/i386-dep.c
@@ -0,0 +1,1275 @@
+/* Low level interface to ptrace, for GDB when running on the Intel 386.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#include <a.out.h>
+#endif
+
+#ifndef N_SET_MAGIC
+#ifdef COFF_FORMAT
+#define N_SET_MAGIC(exec, val) ((exec).magic = (val))
+#else
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+#endif
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <sys/reg.h>
+
+extern int errno;
+
+/* This function simply calls ptrace with the given arguments.
+ It exists so that all calls to ptrace are isolated in this
+ machine-dependent file. */
+int
+call_ptrace (request, pid, arg3, arg4)
+ int request, pid, arg3, arg4;
+{
+ return ptrace (request, pid, arg3, arg4);
+}
+
+kill_inferior ()
+{
+ if (remote_debugging)
+ return;
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ inferior_died ();
+}
+
+/* This is used when GDB is exiting. It gives less chance of error.*/
+
+kill_inferior_fast ()
+{
+ if (remote_debugging)
+ return;
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+resume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ if (remote_debugging)
+ remote_resume (step, signal);
+ else
+ {
+ ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+ }
+}
+
+void
+fetch_inferior_registers ()
+{
+ register int regno;
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct user u;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct user u;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+ if (regno >= 0)
+ {
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR.
+ On failure (cannot read from inferior, usually because address is out
+ of bounds) returns the value of errno. */
+
+int
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ if (remote_debugging)
+ buffer[i] = remote_fetch_word (addr);
+ else
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ if (errno)
+ return errno;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+ return 0;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (remote_debugging)
+ buffer[0] = remote_fetch_word (addr);
+ else
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ if (remote_debugging)
+ buffer[count - 1]
+ = remote_fetch_word (addr + (count - 1) * sizeof (int));
+ else
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ if (remote_debugging)
+ remote_store_word (addr, buffer[i]);
+ else
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(hdr) 0
+#endif /* no N_TXTADDR */
+
+#ifndef N_DATADDR
+#define N_DATADDR(hdr) hdr.a_text
+#endif /* no N_DATADDR */
+
+/* Make COFF and non-COFF names for things a little more compatible
+ to reduce conditionals later. */
+
+#ifndef COFF_FORMAT
+#ifndef AOUTHDR
+#define AOUTHDR struct exec
+#endif
+#endif
+
+extern char *sys_siglist[];
+
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+/* File names of core file and executable file. */
+
+extern char *corefile;
+extern char *execfile;
+
+/* Descriptors on which core file and executable file are open.
+ Note that the execchan is closed when an inferior is created
+ and reopened if the inferior dies or is killed. */
+
+extern int corechan;
+extern int execchan;
+
+/* Last modification time of executable file.
+ Also used in source.c to compare against mtime of a source file. */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file. */
+
+extern CORE_ADDR data_start;
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+ Note that the data area in the exec file is used only when there is no core file. */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data. */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data. */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data. */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data. */
+
+extern int stack_offset;
+
+#ifdef COFF_FORMAT
+/* various coff data structures */
+
+extern FILHDR file_hdr;
+extern SCNHDR text_hdr;
+extern SCNHDR data_hdr;
+
+#endif /* not COFF_FORMAT */
+
+/* a.out header saved in core file. */
+
+extern AOUTHDR core_aouthdr;
+
+/* a.out header of exec file. */
+
+extern AOUTHDR exec_aouthdr;
+
+extern void validate_files ();
+
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name (filename);
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+ reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+/* N_SET_MAGIC (core_aouthdr, 0); */
+ bzero ((char *) &core_aouthdr, sizeof core_aouthdr);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0)
+ perror_with_name (filename);
+
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
+
+exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end -= exec_data_start;
+ text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+#ifdef COFF_FORMAT
+ {
+ int aout_hdrsize;
+ int num_sections;
+
+ if (read_file_hdr (execchan, &file_hdr) < 0)
+ error ("\"%s\": not in executable format.", execfile);
+
+ aout_hdrsize = file_hdr.f_opthdr;
+ num_sections = file_hdr.f_nscns;
+
+ if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
+ error ("\"%s\": can't read optional aouthdr", execfile);
+
+ if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
+ aout_hdrsize) < 0)
+ error ("\"%s\": can't read text section header", execfile);
+
+ if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
+ aout_hdrsize) < 0)
+ error ("\"%s\": can't read data section header", execfile);
+
+ text_start = exec_aouthdr.text_start;
+ text_end = text_start + exec_aouthdr.tsize;
+ text_offset = text_hdr.s_scnptr;
+ exec_data_start = exec_aouthdr.data_start;
+ exec_data_end = exec_data_start + exec_aouthdr.dsize;
+ exec_data_offset = data_hdr.s_scnptr;
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+ exec_mtime = file_hdr.f_timdat;
+ }
+#else /* not COFF_FORMAT */
+ {
+ struct stat st_exec;
+
+#ifdef HEADER_SEEK_FD
+ HEADER_SEEK_FD (execchan);
+#endif
+
+ val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
+
+ if (val < 0)
+ perror_with_name (filename);
+
+ text_start = N_TXTADDR (exec_aouthdr);
+ exec_data_start = N_DATADDR (exec_aouthdr);
+
+ text_offset = N_TXTOFF (exec_aouthdr);
+ exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+
+ text_end = text_start + exec_aouthdr.a_text;
+ exec_data_end = exec_data_start + exec_aouthdr.a_data;
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+
+ fstat (execchan, &st_exec);
+ exec_mtime = st_exec.st_mtime;
+ }
+#endif /* not COFF_FORMAT */
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No exec file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
+
+/* helper functions for m-i386.h */
+
+/* stdio style buffering to minimize calls to ptrace */
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[sizeof (int)];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() (codestream_addr + codestream_off)
+#define codestream_peek() (codestream_cnt == 0 ? \
+ codestream_fill(1): codestream_buf[codestream_off])
+#define codestream_get() (codestream_cnt-- == 0 ? \
+ codestream_fill(0) : codestream_buf[codestream_off++])
+
+static unsigned char
+codestream_fill (peek_flag)
+{
+ codestream_addr = codestream_next_addr;
+ codestream_next_addr += sizeof (int);
+ codestream_off = 0;
+ codestream_cnt = sizeof (int);
+ read_memory (codestream_addr,
+ (unsigned char *)codestream_buf,
+ sizeof (int));
+
+ if (peek_flag)
+ return (codestream_peek());
+ else
+ return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+{
+ codestream_next_addr = place & -sizeof (int);
+ codestream_cnt = 0;
+ codestream_fill (1);
+ while (codestream_tell() != place)
+ codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+ unsigned char *buf;
+{
+ unsigned char *p;
+ int i;
+ p = buf;
+ for (i = 0; i < count; i++)
+ *p++ = codestream_get ();
+}
+
+/* next instruction is a jump, move to target */
+static
+i386_follow_jump ()
+{
+ int long_delta;
+ short short_delta;
+ char byte_delta;
+ int data16;
+ int pos;
+
+ pos = codestream_tell ();
+
+ data16 = 0;
+ if (codestream_peek () == 0x66)
+ {
+ codestream_get ();
+ data16 = 1;
+ }
+
+ switch (codestream_get ())
+ {
+ case 0xe9:
+ /* relative jump: if data16 == 0, disp32, else disp16 */
+ if (data16)
+ {
+ codestream_read ((unsigned char *)&short_delta, 2);
+ pos += short_delta + 3; /* include size of jmp inst */
+ }
+ else
+ {
+ codestream_read ((unsigned char *)&long_delta, 4);
+ pos += long_delta + 5;
+ }
+ break;
+ case 0xeb:
+ /* relative jump, disp8 (ignore data16) */
+ codestream_read ((unsigned char *)&byte_delta, 1);
+ pos += byte_delta + 2;
+ break;
+ }
+ codestream_seek (pos + data16);
+}
+
+/*
+ * find & return amound a local space allocated, and advance codestream to
+ * first register push (if any)
+ *
+ * if entry sequence doesn't make sense, return -1, and leave
+ * codestream pointer random
+ */
+static long
+i386_get_frame_setup (pc)
+{
+ unsigned char op;
+
+ codestream_seek (pc);
+
+ i386_follow_jump ();
+
+ op = codestream_get ();
+
+ if (op == 0x58) /* popl %eax */
+ {
+ /*
+ * this function must start with
+ *
+ * popl %eax 0x58
+ * xchgl %eax, (%esp) 0x87 0x04 0x24
+ * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
+ *
+ * (the system 5 compiler puts out the second xchg
+ * inst, and the assembler doesn't try to optimize it,
+ * so the 'sib' form gets generated)
+ *
+ * this sequence is used to get the address of the return
+ * buffer for a function that returns a structure
+ */
+ int pos;
+ unsigned char buf[4];
+ static unsigned char proto1[3] = { 0x87,0x04,0x24 };
+ static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
+ pos = codestream_tell ();
+ codestream_read (buf, 4);
+ if (bcmp (buf, proto1, 3) == 0)
+ pos += 3;
+ else if (bcmp (buf, proto2, 4) == 0)
+ pos += 4;
+
+ codestream_seek (pos);
+ op = codestream_get (); /* update next opcode */
+ }
+
+ if (op == 0x55) /* pushl %esp */
+ {
+ /* check for movl %esp, %ebp - can be written two ways */
+ switch (codestream_get ())
+ {
+ case 0x8b:
+ if (codestream_get () != 0xec)
+ return (-1);
+ break;
+ case 0x89:
+ if (codestream_get () != 0xe5)
+ return (-1);
+ break;
+ default:
+ return (-1);
+ }
+ /* check for stack adjustment
+ *
+ * subl $XXX, %esp
+ *
+ * note: you can't subtract a 16 bit immediate
+ * from a 32 bit reg, so we don't have to worry
+ * about a data16 prefix
+ */
+ op = codestream_peek ();
+ if (op == 0x83)
+ {
+ /* subl with 8 bit immed */
+ codestream_get ();
+ if (codestream_get () != 0xec)
+ return (-1);
+ /* subl with signed byte immediate
+ * (though it wouldn't make sense to be negative)
+ */
+ return (codestream_get());
+ }
+ else if (op == 0x81)
+ {
+ /* subl with 32 bit immed */
+ int locals;
+ codestream_get();
+ if (codestream_get () != 0xec)
+ return (-1);
+ /* subl with 32 bit immediate */
+ codestream_read ((unsigned char *)&locals, 4);
+ return (locals);
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ else if (op == 0xc8)
+ {
+ /* enter instruction: arg is 16 bit unsigned immed */
+ unsigned short slocals;
+ codestream_read ((unsigned char *)&slocals, 2);
+ codestream_get (); /* flush final byte of enter instruction */
+ return (slocals);
+ }
+ return (-1);
+}
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+/* on the 386, the instruction following the call could be:
+ * popl %ecx - one arg
+ * addl $imm, %esp - imm/4 args; imm may be 8 or 32 bits
+ * anything else - zero args
+ */
+
+int
+i386_frame_num_args (fi)
+ struct frame_info fi;
+{
+ int retpc;
+ unsigned char op;
+ struct frame_info *pfi;
+
+ pfi = get_prev_frame_info ((fi));
+ if (pfi == 0)
+ {
+ /* Note: this can happen if we are looking at the frame for
+ main, because FRAME_CHAIN_VALID won't let us go into
+ start. If we have debugging symbols, that's not really
+ a big deal; it just means it will only show as many arguments
+ to main as are declared. */
+ return -1;
+ }
+ else
+ {
+ retpc = pfi->pc;
+ op = read_memory_integer (retpc, 1);
+ if (op == 0x59)
+ /* pop %ecx */
+ return 1;
+ else if (op == 0x83)
+ {
+ op = read_memory_integer (retpc+1, 1);
+ if (op == 0xc4)
+ /* addl $<signed imm 8 bits>, %esp */
+ return (read_memory_integer (retpc+2,1)&0xff)/4;
+ else
+ return 0;
+ }
+ else if (op == 0x81)
+ { /* add with 32 bit immediate */
+ op = read_memory_integer (retpc+1, 1);
+ if (op == 0xc4)
+ /* addl $<imm 32>, %esp */
+ return read_memory_integer (retpc+2, 4) / 4;
+ else
+ return 0;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+
+/*
+ * parse the first few instructions of the function to see
+ * what registers were stored.
+ *
+ * We handle these cases:
+ *
+ * The startup sequence can be at the start of the function,
+ * or the function can start with a branch to startup code at the end.
+ *
+ * %ebp can be set up with either the 'enter' instruction, or
+ * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful,
+ * but was once used in the sys5 compiler)
+ *
+ * Local space is allocated just below the saved %ebp by either the
+ * 'enter' instruction, or by 'subl $<size>, %esp'. 'enter' has
+ * a 16 bit unsigned argument for space to allocate, and the
+ * 'addl' instruction could have either a signed byte, or
+ * 32 bit immediate.
+ *
+ * Next, the registers used by this function are pushed. In
+ * the sys5 compiler they will always be in the order: %edi, %esi, %ebx
+ * (and sometimes a harmless bug causes it to also save but not restore %eax);
+ * however, the code below is willing to see the pushes in any order,
+ * and will handle up to 8 of them.
+ *
+ * If the setup sequence is at the end of the function, then the
+ * next instruction will be a branch back to the start.
+ */
+
+i386_frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ unsigned long locals;
+ unsigned char *p;
+ unsigned char op;
+ CORE_ADDR dummy_bottom;
+ CORE_ADDR adr;
+ int i;
+
+ bzero (fsrp, sizeof *fsrp);
+
+ /* if frame is the end of a dummy, compute where the
+ * beginning would be
+ */
+ dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
+
+ /* check if the PC is in the stack, in a dummy frame */
+ if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
+ {
+ /* all regs were saved by push_call_dummy () */
+ adr = fip->frame - 4;
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ fsrp->regs[i] = adr;
+ adr -= 4;
+ }
+ return;
+ }
+
+ locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
+
+ if (locals >= 0)
+ {
+ adr = fip->frame - 4 - locals;
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_get ();
+ if (op < 0x50 || op > 0x57)
+ break;
+ fsrp->regs[op - 0x50] = adr;
+ adr -= 4;
+ }
+ }
+
+ fsrp->regs[PC_REGNUM] = fip->frame + 4;
+ fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+/* return pc of first real instruction */
+i386_skip_prologue (pc)
+{
+ unsigned char op;
+ int i;
+
+ if (i386_get_frame_setup (pc) < 0)
+ return (pc);
+
+ /* found valid frame setup - codestream now points to
+ * start of push instructions for saving registers
+ */
+
+ /* skip over register saves */
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_peek ();
+ /* break if not pushl inst */
+ if (op < 0x50 || op > 0x57)
+ break;
+ codestream_get ();
+ }
+
+ i386_follow_jump ();
+
+ return (codestream_tell ());
+}
+
+i386_push_dummy_frame ()
+{
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ int regnum;
+
+ sp = push_word (sp, read_register (PC_REGNUM));
+ sp = push_word (sp, read_register (FP_REGNUM));
+ write_register (FP_REGNUM, sp);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ sp = push_word (sp, read_register (regnum));
+ write_register (SP_REGNUM, sp);
+}
+
+i386_pop_frame ()
+{
+ FRAME frame = get_current_frame ();
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ struct frame_info *fi;
+
+ fi = get_frame_info (frame);
+ fp = fi->frame;
+ get_frame_saved_regs (fi, &fsr);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ CORE_ADDR adr;
+ adr = fsr.regs[regnum];
+ if (adr)
+ write_register (regnum, read_memory_integer (adr, 4));
+ }
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
+ write_register (SP_REGNUM, fp + 8);
+ flush_cached_frames ();
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+}
+
+/* this table must line up with REGISTER_NAMES in m-i386.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+i386_register_u_addr (blockend, regnum)
+{
+#if 0
+ /* this will be needed if fp registers are reinstated */
+ /* for now, you can look at them with 'info float'
+ * sys5 wont let you change them with ptrace anyway
+ */
+ if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
+ {
+ int ubase, fpstate;
+ struct user u;
+ ubase = blockend + 4 * (SS + 1) - KSTKSZ;
+ fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
+ return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+ }
+ else
+#endif
+ return (blockend + 4 * regmap[regnum]);
+
+}
+
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ long *lp;
+ /* push extended mode on 387 stack, then pop in double mode
+ *
+ * first, set exception masks so no error is generated -
+ * number will be rounded to inf or 0, if necessary
+ */
+ asm ("pushl %eax"); /* grab a stack slot */
+ asm ("fstcw (%esp)"); /* get 387 control word */
+ asm ("movl (%esp),%eax"); /* save old value */
+ asm ("orl $0x3f,%eax"); /* mask all exceptions */
+ asm ("pushl %eax");
+ asm ("fldcw (%esp)"); /* load new value into 387 */
+
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldt (%eax)"); /* push extended number on 387 stack */
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpl (%eax)"); /* pop double */
+ asm ("fwait");
+
+ asm ("popl %eax"); /* flush modified control word */
+ asm ("fnclex"); /* clear exceptions */
+ asm ("fldcw (%esp)"); /* restore original control word */
+ asm ("popl %eax"); /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ /* push double mode on 387 stack, then pop in extended mode
+ * no errors are possible because every 64-bit pattern
+ * can be converted to an extended
+ */
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldl (%eax)");
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpt (%eax)");
+ asm ("fwait");
+}
+
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
+
+static
+print_387_control_word (control)
+unsigned short control;
+{
+ printf ("control 0x%04x: ", control);
+ printf ("compute to ");
+ switch ((control >> 8) & 3)
+ {
+ case 0: printf ("24 bits; "); break;
+ case 1: printf ("(bad); "); break;
+ case 2: printf ("53 bits; "); break;
+ case 3: printf ("64 bits; "); break;
+ }
+ printf ("round ");
+ switch ((control >> 10) & 3)
+ {
+ case 0: printf ("NEAREST; "); break;
+ case 1: printf ("DOWN; "); break;
+ case 2: printf ("UP; "); break;
+ case 3: printf ("CHOP; "); break;
+ }
+ if (control & 0x3f)
+ {
+ printf ("mask:");
+ if (control & 0x0001) printf (" INVALID");
+ if (control & 0x0002) printf (" DENORM");
+ if (control & 0x0004) printf (" DIVZ");
+ if (control & 0x0008) printf (" OVERF");
+ if (control & 0x0010) printf (" UNDERF");
+ if (control & 0x0020) printf (" LOS");
+ printf (";");
+ }
+ printf ("\n");
+ if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
+ control & 0xe080);
+}
+
+static
+print_387_status_word (status)
+ unsigned short status;
+{
+ printf ("status 0x%04x: ", status);
+ if (status & 0xff)
+ {
+ printf ("exceptions:");
+ if (status & 0x0001) printf (" INVALID");
+ if (status & 0x0002) printf (" DENORM");
+ if (status & 0x0004) printf (" DIVZ");
+ if (status & 0x0008) printf (" OVERF");
+ if (status & 0x0010) printf (" UNDERF");
+ if (status & 0x0020) printf (" LOS");
+ if (status & 0x0040) printf (" FPSTACK");
+ printf ("; ");
+ }
+ printf ("flags: %d%d%d%d; ",
+ (status & 0x4000) != 0,
+ (status & 0x0400) != 0,
+ (status & 0x0200) != 0,
+ (status & 0x0100) != 0);
+
+ printf ("top %d\n", (status >> 11) & 7);
+}
+
+static
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf ("last exception: ");
+ printf ("opcode 0x%x; ", ep->opcode);
+ printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
+ printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
+
+ top = (ep->status >> 11) & 7;
+
+ printf ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf ("valid "); break;
+ case 1: printf ("zero "); break;
+ case 2: printf ("trap "); break;
+ case 3: printf ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf ("%02x", ep->regs[fpreg][i]);
+
+ i387_to_double (ep->regs[fpreg], (char *)&val);
+ printf (" %g\n", val);
+ }
+ if (ep->r0)
+ printf ("warning: reserved0 is 0x%x\n", ep->r0);
+ if (ep->r1)
+ printf ("warning: reserved1 is 0x%x\n", ep->r1);
+ if (ep->r2)
+ printf ("warning: reserved2 is 0x%x\n", ep->r2);
+ if (ep->r3)
+ printf ("warning: reserved3 is 0x%x\n", ep->r3);
+}
+
+#ifndef U_FPSTATE
+#define U_FPSTATE(u) u.u_fpstate
+#endif
+
+i386_float_info ()
+{
+ struct user u; /* just for address computations */
+ int i;
+ /* fpstate defined in <sys/user.h> */
+ struct fpstate *fpstatep;
+ char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
+ unsigned int uaddr;
+ char fpvalid;
+ unsigned int rounded_addr;
+ unsigned int rounded_size;
+ extern int corechan;
+ int skip;
+
+ uaddr = (char *)&u.u_fpvalid - (char *)&u;
+ if (have_inferior_p())
+ {
+ unsigned int data;
+ unsigned int mask;
+
+ rounded_addr = uaddr & -sizeof (int);
+ data = ptrace (3, inferior_pid, rounded_addr, 0);
+ mask = 0xff << ((uaddr - rounded_addr) * 8);
+
+ fpvalid = ((data & mask) != 0);
+ }
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror ("seek on core file");
+ if (myread (corechan, &fpvalid, 1) < 0)
+ perror ("read on core file");
+
+ }
+
+ if (fpvalid == 0)
+ {
+ printf ("no floating point status saved\n");
+ return;
+ }
+
+ uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+ if (have_inferior_p ())
+ {
+ int *ip;
+
+ rounded_addr = uaddr & -sizeof (int);
+ rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
+ sizeof (int) - 1) / sizeof (int);
+ skip = uaddr - rounded_addr;
+
+ ip = (int *)buf;
+ for (i = 0; i < rounded_size; i++)
+ {
+ *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
+ rounded_addr += sizeof (int);
+ }
+ }
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror_with_name ("seek on core file");
+ if (myread (corechan, buf, sizeof (struct fpstate)) < 0)
+ perror_with_name ("read from core file");
+ skip = 0;
+ }
+
+ fpstatep = (struct fpstate *)(buf + skip);
+ print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
+}
+
diff --git a/gnu/usr.bin/kgdb/config/i386-pinsn.c b/gnu/usr.bin/kgdb/config/i386-pinsn.c
new file mode 100644
index 000000000000..649baaf56bf6
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/i386-pinsn.c
@@ -0,0 +1,1812 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual. Usually, there is a capital letter, followed
+ * by a small letter. The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size. Refer to
+ * the Intel manual for details.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0
+#define Mp OP_E, 0 /* ? */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rw OP_rm, w_mode
+#define Rd OP_rm, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define ONE OP_ONE, 0
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, lptr
+#define Av OP_DIR, v_mode
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSSI, b_mode
+#define Xv OP_DSSI, v_mode
+#define Yb OP_ESDI, b_mode
+#define Yv OP_ESDI, v_mode
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
+int OP_J(), OP_SEG();
+int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
+int OP_D(), OP_T(), OP_rm();
+
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+#define eAX_reg 107
+#define eCX_reg 108
+#define eDX_reg 109
+#define eBX_reg 110
+#define eSP_reg 111
+#define eBP_reg 112
+#define eSI_reg 113
+#define eDI_reg 114
+
+#define lptr 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define GRP1b NULL, NULL, 0
+#define GRP1S NULL, NULL, 1
+#define GRP1Ss NULL, NULL, 2
+#define GRP2b NULL, NULL, 3
+#define GRP2S NULL, NULL, 4
+#define GRP2b_one NULL, NULL, 5
+#define GRP2S_one NULL, NULL, 6
+#define GRP2b_cl NULL, NULL, 7
+#define GRP2S_cl NULL, NULL, 8
+#define GRP3b NULL, NULL, 9
+#define GRP3S NULL, NULL, 10
+#define GRP4 NULL, NULL, 11
+#define GRP5 NULL, NULL, 12
+#define GRP6 NULL, NULL, 13
+#define GRP7 NULL, NULL, 14
+#define GRP8 NULL, NULL, 15
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE
+
+struct dis386 {
+ char *name;
+ int (*op1)();
+ int bytemode1;
+ int (*op2)();
+ int bytemode2;
+ int (*op3)();
+ int bytemode3;
+};
+
+struct dis386 dis386[] = {
+ /* 00 */
+ { "addb", Eb, Gb },
+ { "addS", Ev, Gv },
+ { "addb", Gb, Eb },
+ { "addS", Gv, Ev },
+ { "addb", AL, Ib },
+ { "addS", eAX, Iv },
+ { "pushl", es },
+ { "popl", es },
+ /* 08 */
+ { "orb", Eb, Gb },
+ { "orS", Ev, Gv },
+ { "orb", Gb, Eb },
+ { "orS", Gv, Ev },
+ { "orb", AL, Ib },
+ { "orS", eAX, Iv },
+ { "pushl", cs },
+ { "(bad)" }, /* 0x0f extended opcode escape */
+ /* 10 */
+ { "adcb", Eb, Gb },
+ { "adcS", Ev, Gv },
+ { "adcb", Gb, Eb },
+ { "adcS", Gv, Ev },
+ { "adcb", AL, Ib },
+ { "adcS", eAX, Iv },
+ { "pushl", ss },
+ { "popl", ss },
+ /* 18 */
+ { "sbbb", Eb, Gb },
+ { "sbbS", Ev, Gv },
+ { "sbbb", Gb, Eb },
+ { "sbbS", Gv, Ev },
+ { "sbbb", AL, Ib },
+ { "sbbS", eAX, Iv },
+ { "pushl", ds },
+ { "popl", ds },
+ /* 20 */
+ { "andb", Eb, Gb },
+ { "andS", Ev, Gv },
+ { "andb", Gb, Eb },
+ { "andS", Gv, Ev },
+ { "andb", AL, Ib },
+ { "andS", eAX, Iv },
+ { "(bad)" }, /* SEG ES prefix */
+ { "daa" },
+ /* 28 */
+ { "subb", Eb, Gb },
+ { "subS", Ev, Gv },
+ { "subb", Gb, Eb },
+ { "subS", Gv, Ev },
+ { "subb", AL, Ib },
+ { "subS", eAX, Iv },
+ { "(bad)" }, /* SEG CS prefix */
+ { "das" },
+ /* 30 */
+ { "xorb", Eb, Gb },
+ { "xorS", Ev, Gv },
+ { "xorb", Gb, Eb },
+ { "xorS", Gv, Ev },
+ { "xorb", AL, Ib },
+ { "xorS", eAX, Iv },
+ { "(bad)" }, /* SEG SS prefix */
+ { "aaa" },
+ /* 38 */
+ { "cmpb", Eb, Gb },
+ { "cmpS", Ev, Gv },
+ { "cmpb", Gb, Eb },
+ { "cmpS", Gv, Ev },
+ { "cmpb", AL, Ib },
+ { "cmpS", eAX, Iv },
+ { "(bad)" }, /* SEG DS prefix */
+ { "aas" },
+ /* 40 */
+ { "incS", eAX },
+ { "incS", eCX },
+ { "incS", eDX },
+ { "incS", eBX },
+ { "incS", eSP },
+ { "incS", eBP },
+ { "incS", eSI },
+ { "incS", eDI },
+ /* 48 */
+ { "decS", eAX },
+ { "decS", eCX },
+ { "decS", eDX },
+ { "decS", eBX },
+ { "decS", eSP },
+ { "decS", eBP },
+ { "decS", eSI },
+ { "decS", eDI },
+ /* 50 */
+ { "pushS", eAX },
+ { "pushS", eCX },
+ { "pushS", eDX },
+ { "pushS", eBX },
+ { "pushS", eSP },
+ { "pushS", eBP },
+ { "pushS", eSI },
+ { "pushS", eDI },
+ /* 58 */
+ { "popS", eAX },
+ { "popS", eCX },
+ { "popS", eDX },
+ { "popS", eBX },
+ { "popS", eSP },
+ { "popS", eBP },
+ { "popS", eSI },
+ { "popS", eDI },
+ /* 60 */
+ { "pusha" },
+ { "popa" },
+ { "boundS", Gv, Ma },
+ { "arpl", Ew, Gw },
+ { "(bad)" }, /* seg fs */
+ { "(bad)" }, /* seg gs */
+ { "(bad)" }, /* op size prefix */
+ { "(bad)" }, /* adr size prefix */
+ /* 68 */
+ { "pushS", Iv }, /* 386 book wrong */
+ { "imulS", Gv, Ev, Iv },
+ { "pushl", sIb }, /* push of byte really pushes 4 bytes */
+ { "imulS", Gv, Ev, Ib },
+ { "insb", Yb, indirDX },
+ { "insS", Yv, indirDX },
+ { "outsb", indirDX, Xb },
+ { "outsS", indirDX, Xv },
+ /* 70 */
+ { "jo", Jb },
+ { "jno", Jb },
+ { "jb", Jb },
+ { "jae", Jb },
+ { "je", Jb },
+ { "jne", Jb },
+ { "jbe", Jb },
+ { "ja", Jb },
+ /* 78 */
+ { "js", Jb },
+ { "jns", Jb },
+ { "jp", Jb },
+ { "jnp", Jb },
+ { "jl", Jb },
+ { "jnl", Jb },
+ { "jle", Jb },
+ { "jg", Jb },
+ /* 80 */
+ { GRP1b },
+ { GRP1S },
+ { "(bad)" },
+ { GRP1Ss },
+ { "testb", Eb, Gb },
+ { "testS", Ev, Gv },
+ { "xchgb", Eb, Gb },
+ { "xchgS", Ev, Gv },
+ /* 88 */
+ { "movb", Eb, Gb },
+ { "movS", Ev, Gv },
+ { "movb", Gb, Eb },
+ { "movS", Gv, Ev },
+ { "movw", Ew, Sw },
+ { "leaS", Gv, M },
+ { "movw", Sw, Ew },
+ { "popS", Ev },
+ /* 90 */
+ { "nop" },
+ { "xchgS", eCX, eAX },
+ { "xchgS", eDX, eAX },
+ { "xchgS", eBX, eAX },
+ { "xchgS", eSP, eAX },
+ { "xchgS", eBP, eAX },
+ { "xchgS", eSI, eAX },
+ { "xchgS", eDI, eAX },
+ /* 98 */
+ { "cwtl" },
+ { "cltd" },
+ { "lcall", Ap },
+ { "(bad)" }, /* fwait */
+ { "pushf" },
+ { "popf" },
+ { "sahf" },
+ { "lahf" },
+ /* a0 */
+ { "movb", AL, Ob },
+ { "movS", eAX, Ov },
+ { "movb", Ob, AL },
+ { "movS", Ov, eAX },
+ { "movsb", Yb, Xb },
+ { "movsS", Yv, Xv },
+ { "cmpsb", Yb, Xb },
+ { "cmpsS", Yv, Xv },
+ /* a8 */
+ { "testb", AL, Ib },
+ { "testS", eAX, Iv },
+ { "stosb", Yb, AL },
+ { "stosS", Yv, eAX },
+ { "lodsb", AL, Xb },
+ { "lodsS", eAX, Xv },
+ { "scasb", AL, Xb },
+ { "scasS", eAX, Xv },
+ /* b0 */
+ { "movb", AL, Ib },
+ { "movb", CL, Ib },
+ { "movb", DL, Ib },
+ { "movb", BL, Ib },
+ { "movb", AH, Ib },
+ { "movb", CH, Ib },
+ { "movb", DH, Ib },
+ { "movb", BH, Ib },
+ /* b8 */
+ { "movS", eAX, Iv },
+ { "movS", eCX, Iv },
+ { "movS", eDX, Iv },
+ { "movS", eBX, Iv },
+ { "movS", eSP, Iv },
+ { "movS", eBP, Iv },
+ { "movS", eSI, Iv },
+ { "movS", eDI, Iv },
+ /* c0 */
+ { GRP2b },
+ { GRP2S },
+ { "ret", Iw },
+ { "ret" },
+ { "lesS", Gv, Mp },
+ { "ldsS", Gv, Mp },
+ { "movb", Eb, Ib },
+ { "movS", Ev, Iv },
+ /* c8 */
+ { "enter", Iw, Ib },
+ { "leave" },
+ { "lret", Iw },
+ { "lret" },
+ { "int3" },
+ { "int", Ib },
+ { "into" },
+ { "iret" },
+ /* d0 */
+ { GRP2b_one },
+ { GRP2S_one },
+ { GRP2b_cl },
+ { GRP2S_cl },
+ { "aam", Ib },
+ { "aad", Ib },
+ { "(bad)" },
+ { "xlat" },
+ /* d8 */
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ /* e0 */
+ { "loopne", Jb },
+ { "loope", Jb },
+ { "loop", Jb },
+ { "jCcxz", Jb },
+ { "inb", AL, Ib },
+ { "inS", eAX, Ib },
+ { "outb", Ib, AL },
+ { "outS", Ib, eAX },
+ /* e8 */
+ { "call", Av },
+ { "jmp", Jv },
+ { "ljmp", Ap },
+ { "jmp", Jb },
+ { "inb", AL, indirDX },
+ { "inS", eAX, indirDX },
+ { "outb", indirDX, AL },
+ { "outS", indirDX, eAX },
+ /* f0 */
+ { "(bad)" }, /* lock prefix */
+ { "(bad)" },
+ { "(bad)" }, /* repne */
+ { "(bad)" }, /* repz */
+ { "hlt" },
+ { "cmc" },
+ { GRP3b },
+ { GRP3S },
+ /* f8 */
+ { "clc" },
+ { "stc" },
+ { "cli" },
+ { "sti" },
+ { "cld" },
+ { "std" },
+ { GRP4 },
+ { GRP5 },
+};
+
+struct dis386 dis386_twobyte[] = {
+ /* 00 */
+ { GRP6 },
+ { GRP7 },
+ { "larS", Gv, Ew },
+ { "lslS", Gv, Ew },
+ { "(bad)" },
+ { "(bad)" },
+ { "clts" },
+ { "(bad)" },
+ /* 08 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 10 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 18 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 20 */
+ /* these are all backward in appendix A of the intel book */
+ { "movl", Rd, Cd },
+ { "movl", Rd, Dd },
+ { "movl", Cd, Rd },
+ { "movl", Dd, Rd },
+ { "movl", Rd, Td },
+ { "(bad)" },
+ { "movl", Td, Rd },
+ { "(bad)" },
+ /* 28 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 30 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 38 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 40 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 48 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 50 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 58 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 60 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 68 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 70 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 78 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 80 */
+ { "jo", Jv },
+ { "jno", Jv },
+ { "jb", Jv },
+ { "jae", Jv },
+ { "je", Jv },
+ { "jne", Jv },
+ { "jbe", Jv },
+ { "ja", Jv },
+ /* 88 */
+ { "js", Jv },
+ { "jns", Jv },
+ { "jp", Jv },
+ { "jnp", Jv },
+ { "jl", Jv },
+ { "jge", Jv },
+ { "jle", Jv },
+ { "jg", Jv },
+ /* 90 */
+ { "seto", Eb },
+ { "setno", Eb },
+ { "setb", Eb },
+ { "setae", Eb },
+ { "sete", Eb },
+ { "setne", Eb },
+ { "setbe", Eb },
+ { "seta", Eb },
+ /* 98 */
+ { "sets", Eb },
+ { "setns", Eb },
+ { "setp", Eb },
+ { "setnp", Eb },
+ { "setl", Eb },
+ { "setge", Eb },
+ { "setle", Eb },
+ { "setg", Eb },
+ /* a0 */
+ { "pushl", fs },
+ { "popl", fs },
+ { "(bad)" },
+ { "btS", Ev, Gv },
+ { "shldS", Ev, Gv, Ib },
+ { "shldS", Ev, Gv, CL },
+ { "(bad)" },
+ { "(bad)" },
+ /* a8 */
+ { "pushl", gs },
+ { "popl", gs },
+ { "(bad)" },
+ { "btsS", Ev, Gv },
+ { "shrdS", Ev, Gv, Ib },
+ { "shrdS", Ev, Gv, CL },
+ { "(bad)" },
+ { "imulS", Gv, Ev },
+ /* b0 */
+ { "(bad)" },
+ { "(bad)" },
+ { "lssS", Gv, Mp }, /* 386 lists only Mp */
+ { "btrS", Ev, Gv },
+ { "lfsS", Gv, Mp }, /* 386 lists only Mp */
+ { "lgsS", Gv, Mp }, /* 386 lists only Mp */
+ { "movzbS", Gv, Eb },
+ { "movzwS", Gv, Ew },
+ /* b8 */
+ { "(bad)" },
+ { "(bad)" },
+ { GRP8 },
+ { "btcS", Ev, Gv },
+ { "bsfS", Gv, Ev },
+ { "bsrS", Gv, Ev },
+ { "movsbS", Gv, Eb },
+ { "movswS", Gv, Ew },
+ /* c0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* c8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* d0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* d8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *codep;
+static int mod;
+static int rm;
+static int reg;
+
+static char *names32[]={
+ "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static char *names16[] = {
+ "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static char *names8[] = {
+ "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static char *names_seg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+
+struct dis386 grps[][8] = {
+ /* GRP1b */
+ {
+ { "addb", Eb, Ib },
+ { "orb", Eb, Ib },
+ { "adcb", Eb, Ib },
+ { "sbbb", Eb, Ib },
+ { "andb", Eb, Ib },
+ { "subb", Eb, Ib },
+ { "xorb", Eb, Ib },
+ { "cmpb", Eb, Ib }
+ },
+ /* GRP1S */
+ {
+ { "addS", Ev, Iv },
+ { "orS", Ev, Iv },
+ { "adcS", Ev, Iv },
+ { "sbbS", Ev, Iv },
+ { "andS", Ev, Iv },
+ { "subS", Ev, Iv },
+ { "xorS", Ev, Iv },
+ { "cmpS", Ev, Iv }
+ },
+ /* GRP1Ss */
+ {
+ { "addS", Ev, sIb },
+ { "orS", Ev, sIb },
+ { "adcS", Ev, sIb },
+ { "sbbS", Ev, sIb },
+ { "andS", Ev, sIb },
+ { "subS", Ev, sIb },
+ { "xorS", Ev, sIb },
+ { "cmpS", Ev, sIb }
+ },
+ /* GRP2b */
+ {
+ { "rolb", Eb, Ib },
+ { "rorb", Eb, Ib },
+ { "rclb", Eb, Ib },
+ { "rcrb", Eb, Ib },
+ { "shlb", Eb, Ib },
+ { "shrb", Eb, Ib },
+ { "(bad)" },
+ { "sarb", Eb, Ib },
+ },
+ /* GRP2S */
+ {
+ { "rolS", Ev, Ib },
+ { "rorS", Ev, Ib },
+ { "rclS", Ev, Ib },
+ { "rcrS", Ev, Ib },
+ { "shlS", Ev, Ib },
+ { "shrS", Ev, Ib },
+ { "(bad)" },
+ { "sarS", Ev, Ib },
+ },
+ /* GRP2b_one */
+ {
+ { "rolb", Eb },
+ { "rorb", Eb },
+ { "rclb", Eb },
+ { "rcrb", Eb },
+ { "shlb", Eb },
+ { "shrb", Eb },
+ { "(bad)" },
+ { "sarb", Eb },
+ },
+ /* GRP2S_one */
+ {
+ { "rolS", Ev },
+ { "rorS", Ev },
+ { "rclS", Ev },
+ { "rcrS", Ev },
+ { "shlS", Ev },
+ { "shrS", Ev },
+ { "(bad)" },
+ { "sarS", Ev },
+ },
+ /* GRP2b_cl */
+ {
+ { "rolb", Eb, CL },
+ { "rorb", Eb, CL },
+ { "rclb", Eb, CL },
+ { "rcrb", Eb, CL },
+ { "shlb", Eb, CL },
+ { "shrb", Eb, CL },
+ { "(bad)" },
+ { "sarb", Eb, CL },
+ },
+ /* GRP2S_cl */
+ {
+ { "rolS", Ev, CL },
+ { "rorS", Ev, CL },
+ { "rclS", Ev, CL },
+ { "rcrS", Ev, CL },
+ { "shlS", Ev, CL },
+ { "shrS", Ev, CL },
+ { "(bad)" },
+ { "sarS", Ev, CL }
+ },
+ /* GRP3b */
+ {
+ { "testb", Eb, Ib },
+ { "(bad)", Eb },
+ { "notb", Eb },
+ { "negb", Eb },
+ { "mulb", AL, Eb },
+ { "imulb", AL, Eb },
+ { "divb", AL, Eb },
+ { "idivb", AL, Eb }
+ },
+ /* GRP3S */
+ {
+ { "testS", Ev, Iv },
+ { "(bad)" },
+ { "notS", Ev },
+ { "negS", Ev },
+ { "mulS", eAX, Ev },
+ { "imulS", eAX, Ev },
+ { "divS", eAX, Ev },
+ { "idivS", eAX, Ev },
+ },
+ /* GRP4 */
+ {
+ { "incb", Eb },
+ { "decb", Eb },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* GRP5 */
+ {
+ { "incS", Ev },
+ { "decS", Ev },
+ { "call", indirEv },
+ { "lcall", indirEv },
+ { "jmp", indirEv },
+ { "ljmp", indirEv },
+ { "pushS", Ev },
+ { "(bad)" },
+ },
+ /* GRP6 */
+ {
+ { "sldt", Ew },
+ { "str", Ew },
+ { "lldt", Ew },
+ { "ltr", Ew },
+ { "verr", Ew },
+ { "verw", Ew },
+ { "(bad)" },
+ { "(bad)" }
+ },
+ /* GRP7 */
+ {
+ { "sgdt", Ew },
+ { "sidt", Ew },
+ { "lgdt", Ew },
+ { "lidt", Ew },
+ { "smsw", Ew },
+ { "(bad)" },
+ { "lmsw", Ew },
+ { "(bad)" },
+ },
+ /* GRP8 */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "btS", Ev, Ib },
+ { "btsS", Ev, Ib },
+ { "btrS", Ev, Ib },
+ { "btcS", Ev, Ib },
+ }
+};
+
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADR 0x400
+#define PREFIX_FWAIT 0x800
+
+static int prefixes;
+
+ckprefix ()
+{
+ prefixes = 0;
+ while (1)
+ {
+ switch (*codep)
+ {
+ case 0xf3:
+ prefixes |= PREFIX_REPZ;
+ break;
+ case 0xf2:
+ prefixes |= PREFIX_REPNZ;
+ break;
+ case 0xf0:
+ prefixes |= PREFIX_LOCK;
+ break;
+ case 0x2e:
+ prefixes |= PREFIX_CS;
+ break;
+ case 0x36:
+ prefixes |= PREFIX_SS;
+ break;
+ case 0x3e:
+ prefixes |= PREFIX_DS;
+ break;
+ case 0x26:
+ prefixes |= PREFIX_ES;
+ break;
+ case 0x64:
+ prefixes |= PREFIX_FS;
+ break;
+ case 0x65:
+ prefixes |= PREFIX_GS;
+ break;
+ case 0x66:
+ prefixes |= PREFIX_DATA;
+ break;
+ case 0x67:
+ prefixes |= PREFIX_ADR;
+ break;
+ case 0x9b:
+ prefixes |= PREFIX_FWAIT;
+ break;
+ default:
+ return;
+ }
+ codep++;
+ }
+}
+
+static int dflag;
+static int aflag;
+
+static char op1out[100], op2out[100], op3out[100];
+static int start_pc;
+
+/*
+ * disassemble the first instruction in 'inbuf'. You have to make
+ * sure all of the bytes of the instruction are filled in.
+ * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ * (see topic "Redundant prefixes" in the "Differences from 8086"
+ * section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ * be used to print the target address if this is a relative jump or call
+ * 'outbuf' gets filled in with the disassembled instruction. it should
+ * be long enough to hold the longest disassembled instruction.
+ * 100 bytes is certainly enough, unless symbol printing is added later
+ * The function returns the length of this instruction in bytes.
+ */
+i386dis (pc, inbuf, outbuf)
+ int pc;
+ unsigned char *inbuf;
+ char *outbuf;
+{
+ struct dis386 *dp;
+ char *p;
+ int i;
+ int enter_instruction;
+ char *first, *second, *third;
+ int needcomma;
+
+ obuf[0] = 0;
+ op1out[0] = 0;
+ op2out[0] = 0;
+ op3out[0] = 0;
+
+ start_pc = pc;
+ start_codep = inbuf;
+ codep = inbuf;
+
+ ckprefix ();
+
+ if (*codep == 0xc8)
+ enter_instruction = 1;
+ else
+ enter_instruction = 0;
+
+ obufp = obuf;
+
+ if (prefixes & PREFIX_REPZ)
+ oappend ("repz ");
+ if (prefixes & PREFIX_REPNZ)
+ oappend ("repnz ");
+ if (prefixes & PREFIX_LOCK)
+ oappend ("lock ");
+
+ if ((prefixes & PREFIX_FWAIT)
+ && ((*codep < 0xd8) || (*codep > 0xdf)))
+ {
+ /* fwait not followed by floating point instruction */
+ oappend ("fwait");
+ strcpy (outbuf, obuf);
+ return (1);
+ }
+
+ /* these would be initialized to 0 if disassembling for 8086 or 286 */
+ dflag = 1;
+ aflag = 1;
+
+ if (prefixes & PREFIX_DATA)
+ dflag ^= 1;
+
+ if (prefixes & PREFIX_ADR)
+ {
+ aflag ^= 1;
+ oappend ("addr16 ");
+ }
+
+ if (*codep == 0x0f)
+ dp = &dis386_twobyte[*++codep];
+ else
+ dp = &dis386[*codep];
+ codep++;
+ mod = (*codep >> 6) & 3;
+ reg = (*codep >> 3) & 7;
+ rm = *codep & 7;
+
+ if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+ {
+ dofloat ();
+ }
+ else
+ {
+ if (dp->name == NULL)
+ dp = &grps[dp->bytemode1][reg];
+
+ putop (dp->name);
+
+ obufp = op1out;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+
+ obufp = op2out;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+
+ obufp = op3out;
+ if (dp->op3)
+ (*dp->op3)(dp->bytemode3);
+ }
+
+ obufp = obuf + strlen (obuf);
+ for (i = strlen (obuf); i < 6; i++)
+ oappend (" ");
+ oappend (" ");
+
+ /* enter instruction is printed with operands in the
+ * same order as the intel book; everything else
+ * is printed in reverse order
+ */
+ if (enter_instruction)
+ {
+ first = op1out;
+ second = op2out;
+ third = op3out;
+ }
+ else
+ {
+ first = op3out;
+ second = op2out;
+ third = op1out;
+ }
+ needcomma = 0;
+ if (*first)
+ {
+ oappend (first);
+ needcomma = 1;
+ }
+ if (*second)
+ {
+ if (needcomma)
+ oappend (",");
+ oappend (second);
+ needcomma = 1;
+ }
+ if (*third)
+ {
+ if (needcomma)
+ oappend (",");
+ oappend (third);
+ }
+ strcpy (outbuf, obuf);
+ return (codep - inbuf);
+}
+
+char *float_mem[] = {
+ /* d8 */
+ "fadds",
+ "fmuls",
+ "fcoms",
+ "fcomps",
+ "fsubs",
+ "fsubrs",
+ "fdivs",
+ "fdivrs",
+ /* d9 */
+ "flds",
+ "(bad)",
+ "fsts",
+ "fstps",
+ "fldenv",
+ "fldcw",
+ "fNstenv",
+ "fNstcw",
+ /* da */
+ "fiaddl",
+ "fimull",
+ "ficoml",
+ "ficompl",
+ "fisubl",
+ "fisubrl",
+ "fidivl",
+ "fidivrl",
+ /* db */
+ "fildl",
+ "(bad)",
+ "fistl",
+ "fistpl",
+ "(bad)",
+ "fldt",
+ "(bad)",
+ "fstpt",
+ /* dc */
+ "faddl",
+ "fmull",
+ "fcoml",
+ "fcompl",
+ "fsubl",
+ "fsubrl",
+ "fdivl",
+ "fdivrl",
+ /* dd */
+ "fldl",
+ "(bad)",
+ "fstl",
+ "fstpl",
+ "frstor",
+ "(bad)",
+ "fNsave",
+ "fNstsw",
+ /* de */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* df */
+ "fild",
+ "(bad)",
+ "fist",
+ "fistp",
+ "fbld",
+ "fildll",
+ "fbstp",
+ "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+int OP_ST(), OP_STi();
+
+#define FGRPd9_2 NULL, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1
+#define FGRPd9_5 NULL, NULL, 2
+#define FGRPd9_6 NULL, NULL, 3
+#define FGRPd9_7 NULL, NULL, 4
+#define FGRPda_5 NULL, NULL, 5
+#define FGRPdb_4 NULL, NULL, 6
+#define FGRPde_3 NULL, NULL, 7
+#define FGRPdf_4 NULL, NULL, 8
+
+struct dis386 float_reg[][8] = {
+ /* d8 */
+ {
+ { "fadd", ST, STi },
+ { "fmul", ST, STi },
+ { "fcom", STi },
+ { "fcomp", STi },
+ { "fsub", ST, STi },
+ { "fsubr", ST, STi },
+ { "fdiv", ST, STi },
+ { "fdivr", ST, STi },
+ },
+ /* d9 */
+ {
+ { "fld", STi },
+ { "fxch", STi },
+ { FGRPd9_2 },
+ { "(bad)" },
+ { FGRPd9_4 },
+ { FGRPd9_5 },
+ { FGRPd9_6 },
+ { FGRPd9_7 },
+ },
+ /* da */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPda_5 },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* db */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPdb_4 },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* dc */
+ {
+ { "fadd", STi, ST },
+ { "fmul", STi, ST },
+ { "(bad)" },
+ { "(bad)" },
+ { "fsub", STi, ST },
+ { "fsubr", STi, ST },
+ { "fdiv", STi, ST },
+ { "fdivr", STi, ST },
+ },
+ /* dd */
+ {
+ { "ffree", STi },
+ { "(bad)" },
+ { "fst", STi },
+ { "fstp", STi },
+ { "fucom", STi },
+ { "fucomp", STi },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* de */
+ {
+ { "faddp", STi, ST },
+ { "fmulp", STi, ST },
+ { "(bad)" },
+ { FGRPde_3 },
+ { "fsubp", STi, ST },
+ { "fsubrp", STi, ST },
+ { "fdivp", STi, ST },
+ { "fdivrp", STi, ST },
+ },
+ /* df */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPdf_4 },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+};
+
+
+char *fgrps[][8] = {
+ /* d9_2 0 */
+ {
+ "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* d9_4 1 */
+ {
+ "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+ },
+
+ /* d9_5 2 */
+ {
+ "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+ },
+
+ /* d9_6 3 */
+ {
+ "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+ },
+
+ /* d9_7 4 */
+ {
+ "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+ },
+
+ /* da_5 5 */
+ {
+ "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* db_4 6 */
+ {
+ "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+ "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+ },
+
+ /* de_3 7 */
+ {
+ "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* df_4 8 */
+ {
+ "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+};
+
+
+dofloat ()
+{
+ struct dis386 *dp;
+ unsigned char floatop;
+
+ floatop = codep[-1];
+
+ if (mod != 3)
+ {
+ putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+ obufp = op1out;
+ OP_E (v_mode);
+ return;
+ }
+ codep++;
+
+ dp = &float_reg[floatop - 0xd8][reg];
+ if (dp->name == NULL)
+ {
+ putop (fgrps[dp->bytemode1][rm]);
+ /* instruction fnstsw is only one with strange arg */
+ if (floatop == 0xdf && *codep == 0xe0)
+ strcpy (op1out, "%eax");
+ }
+ else
+ {
+ putop (dp->name);
+ obufp = op1out;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+ obufp = op2out;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+ }
+}
+
+/* ARGSUSED */
+OP_ST (ignore)
+{
+ oappend ("%st");
+}
+
+/* ARGSUSED */
+OP_STi (ignore)
+{
+ sprintf (scratchbuf, "%%st(%d)", rm);
+ oappend (scratchbuf);
+}
+
+
+/* capital letters in template are macros */
+putop (template)
+ char *template;
+{
+ char *p;
+
+ for (p = template; *p; p++)
+ {
+ switch (*p)
+ {
+ default:
+ *obufp++ = *p;
+ break;
+ case 'C': /* For jcxz/jecxz */
+ if (aflag == 0)
+ *obufp++ = 'e';
+ break;
+ case 'N':
+ if ((prefixes & PREFIX_FWAIT) == 0)
+ *obufp++ = 'n';
+ break;
+ case 'S':
+ /* operand size flag */
+ if (dflag)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ break;
+ }
+ }
+ *obufp = 0;
+}
+
+oappend (s)
+char *s;
+{
+ strcpy (obufp, s);
+ obufp += strlen (s);
+ *obufp = 0;
+}
+
+append_prefix ()
+{
+ if (prefixes & PREFIX_CS)
+ oappend ("%cs:");
+ if (prefixes & PREFIX_DS)
+ oappend ("%ds:");
+ if (prefixes & PREFIX_SS)
+ oappend ("%ss:");
+ if (prefixes & PREFIX_ES)
+ oappend ("%es:");
+ if (prefixes & PREFIX_FS)
+ oappend ("%fs:");
+ if (prefixes & PREFIX_GS)
+ oappend ("%gs:");
+}
+
+OP_indirE (bytemode)
+{
+ oappend ("*");
+ OP_E (bytemode);
+}
+
+OP_E (bytemode)
+{
+ int disp;
+ int havesib;
+ int didoutput = 0;
+ int base;
+ int index;
+ int scale;
+ int havebase;
+
+ /* skip mod/rm byte */
+ codep++;
+
+ havesib = 0;
+ havebase = 0;
+ disp = 0;
+
+ if (mod == 3)
+ {
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[rm]);
+ else
+ oappend (names16[rm]);
+ break;
+ default:
+ oappend ("<bad dis table>");
+ break;
+ }
+ return;
+ }
+
+ append_prefix ();
+ if (rm == 4)
+ {
+ havesib = 1;
+ havebase = 1;
+ scale = (*codep >> 6) & 3;
+ index = (*codep >> 3) & 7;
+ base = *codep & 7;
+ codep++;
+ }
+
+ switch (mod)
+ {
+ case 0:
+ switch (rm)
+ {
+ case 4:
+ /* implies havesib and havebase */
+ if (base == 5) {
+ havebase = 0;
+ disp = get32 ();
+ }
+ break;
+ case 5:
+ disp = get32 ();
+ break;
+ default:
+ havebase = 1;
+ base = rm;
+ break;
+ }
+ break;
+ case 1:
+ disp = *(char *)codep++;
+ if (rm != 4)
+ {
+ havebase = 1;
+ base = rm;
+ }
+ break;
+ case 2:
+ disp = get32 ();
+ if (rm != 4)
+ {
+ havebase = 1;
+ base = rm;
+ }
+ break;
+ }
+
+ if (mod != 0 || rm == 5 || (havesib && base == 5))
+ {
+ sprintf (scratchbuf, "%d", disp);
+ oappend (scratchbuf);
+ }
+
+ if (havebase || havesib)
+ {
+ oappend ("(");
+ if (havebase)
+ oappend (names32[base]);
+ if (havesib)
+ {
+ if (index != 4)
+ {
+ sprintf (scratchbuf, ",%s", names32[index]);
+ oappend (scratchbuf);
+ }
+ sprintf (scratchbuf, ",%d", 1 << scale);
+ oappend (scratchbuf);
+ }
+ oappend (")");
+ }
+}
+
+OP_G (bytemode)
+{
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[reg]);
+ break;
+ case w_mode:
+ oappend (names16[reg]);
+ break;
+ case d_mode:
+ oappend (names32[reg]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[reg]);
+ else
+ oappend (names16[reg]);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+}
+
+get32 ()
+{
+ int x = 0;
+
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ x |= (*codep++ & 0xff) << 16;
+ x |= (*codep++ & 0xff) << 24;
+ return (x);
+}
+
+get16 ()
+{
+ int x = 0;
+
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ return (x);
+}
+
+OP_REG (code)
+{
+ char *s;
+
+ switch (code)
+ {
+ case indir_dx_reg: s = "(%dx)"; break;
+ case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+ case sp_reg: case bp_reg: case si_reg: case di_reg:
+ s = names16[code - ax_reg];
+ break;
+ case es_reg: case ss_reg: case cs_reg:
+ case ds_reg: case fs_reg: case gs_reg:
+ s = names_seg[code - es_reg];
+ break;
+ case al_reg: case ah_reg: case cl_reg: case ch_reg:
+ case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+ s = names8[code - al_reg];
+ break;
+ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+ case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+ if (dflag)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ break;
+ default:
+ s = "<internal disassembler error>";
+ break;
+ }
+ oappend (s);
+}
+
+OP_I (bytemode)
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ op = *codep++ & 0xff;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = get16 ();
+ break;
+ case w_mode:
+ op = get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+}
+
+OP_sI (bytemode)
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ op = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = (short)get16();
+ break;
+ case w_mode:
+ op = (short)get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+}
+
+OP_J (bytemode)
+{
+ int disp;
+ int mask = -1;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ disp = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ disp = get32 ();
+ else
+ {
+ disp = (short)get16 ();
+ /* for some reason, a data16 prefix on a jump instruction
+ means that the pc is masked to 16 bits after the
+ displacement is added! */
+ mask = 0xffff;
+ }
+ break;
+ default:
+ oappend ("<internal disassembelr error>");
+ return;
+ }
+
+ sprintf (scratchbuf, "0x%x",
+ (start_pc + codep - start_codep + disp) & mask);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_SEG (dummy)
+{
+ static char *sreg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+ };
+
+ oappend (sreg[reg]);
+}
+
+OP_DIR (size)
+{
+ int seg, offset;
+
+ switch (size)
+ {
+ case lptr:
+ if (aflag)
+ {
+ offset = get32 ();
+ seg = get16 ();
+ }
+ else
+ {
+ offset = get16 ();
+ seg = get16 ();
+ }
+ sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+ oappend (scratchbuf);
+ break;
+ case v_mode:
+ if (aflag)
+ offset = get32 ();
+ else
+ offset = (short)get16 ();
+
+ sprintf (scratchbuf, "0x%x",
+ start_pc + codep - start_codep + offset);
+ oappend (scratchbuf);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+}
+
+/* ARGSUSED */
+OP_OFF (bytemode)
+{
+ int off;
+
+ if (aflag)
+ off = get32 ();
+ else
+ off = get16 ();
+
+ sprintf (scratchbuf, "0x%x", off);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_ESDI (dummy)
+{
+ oappend ("%es:(");
+ oappend (aflag ? "%edi" : "%di");
+ oappend (")");
+}
+
+/* ARGSUSED */
+OP_DSSI (dummy)
+{
+ oappend ("%ds:(");
+ oappend (aflag ? "%esi" : "%si");
+ oappend (")");
+}
+
+/* ARGSUSED */
+OP_ONE (dummy)
+{
+ oappend ("1");
+}
+
+/* ARGSUSED */
+OP_C (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%cr%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_D (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%db%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_T (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%tr%d", reg);
+ oappend (scratchbuf);
+}
+
+OP_rm (bytemode)
+{
+ switch (bytemode)
+ {
+ case d_mode:
+ oappend (names32[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ }
+}
+
+/* GDB interface */
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+
+#define MAXLEN 20
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ /* should be expanded if disassembler prints symbol names */
+ char outbuf[100];
+ int n;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ n = i386dis ((int)memaddr, buffer, outbuf);
+
+ fputs (outbuf, stream);
+
+ return (n);
+}
+
diff --git a/gnu/usr.bin/kgdb/config/i386bsd-dep.c b/gnu/usr.bin/kgdb/config/i386bsd-dep.c
new file mode 100644
index 000000000000..d007f55dc4b7
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/i386bsd-dep.c
@@ -0,0 +1,1893 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)i386bsd-dep.c 6.10 (Berkeley) 6/26/91";
+#endif /* not lint */
+
+/* Low level interface to ptrace, for GDB when running on the Intel 386.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "value.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <a.out.h>
+
+#ifndef N_SET_MAGIC
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#define curpcb Xcurpcb /* XXX avoid leaking declaration from pcb.h */
+#include <sys/user.h>
+#undef curpcb
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+
+#include <machine/reg.h>
+
+#ifdef KERNELDEBUG
+#ifndef NEWVM
+#include <sys/vmmac.h>
+#include <machine/pte.h>
+#else
+#include <sys/proc.h> /* for curproc */
+#endif
+#include <machine/vmparam.h>
+#include <machine/cpu.h>
+#include <ctype.h>
+#include "symtab.h" /* XXX */
+
+#undef vtophys /* XXX */
+
+extern int kernel_debugging;
+
+#define KERNOFF ((unsigned)KERNBASE)
+#ifndef NEWVM
+#define INKERNEL(x) ((x) >= KERNOFF && (x) < KERNOFF + ctob(slr))
+#define INUPAGE(x) \
+ ((x) >= KERNEL_U_ADDR && (x) < KERNEL_U_ADDR + NBPG)
+#else
+#define INKERNEL(x) ((x) >= KERNOFF)
+#endif
+
+#define PT_ADDR_ANY ((caddr_t) 1)
+
+/*
+ * Convert from sysmap pte index to system virtual address & vice-versa.
+ * (why aren't these in one of the system vm macro files???)
+ */
+#define smxtob(a) (sbr + (a) * sizeof(pte))
+#define btosmx(b) (((b) - sbr) / sizeof(pte))
+
+static int ok_to_cache();
+static int found_pcb;
+#ifdef NEWVM
+static CORE_ADDR curpcb;
+static CORE_ADDR kstack;
+#endif
+
+static void setregmap();
+
+extern int errno;
+
+/*
+ * This function simply calls ptrace with the given arguments. It exists so
+ * that all calls to ptrace are isolated in this machine-dependent file.
+ */
+int
+call_ptrace(request, pid, arg3, arg4)
+ int request;
+ pid_t pid;
+ caddr_t arg3;
+ int arg4;
+{
+ return(ptrace(request, pid, arg3, arg4));
+}
+
+kill_inferior()
+{
+ if (remote_debugging) {
+#ifdef KERNELDEBUG
+ if (kernel_debugging)
+ /*
+ * It's a very, very bad idea to go away leaving
+ * breakpoints in a remote kernel or to leave it
+ * stopped at a breakpoint.
+ */
+ clear_breakpoints();
+#endif
+ remote_close(0);
+ inferior_died();
+ } else if (inferior_pid != 0) {
+ ptrace(PT_KILL, inferior_pid, 0, 0);
+ wait(0);
+ inferior_died();
+ }
+}
+
+/*
+ * This is used when GDB is exiting. It gives less chance of error.
+ */
+kill_inferior_fast()
+{
+ if (remote_debugging) {
+#ifdef KERNELDEBUG
+ if (kernel_debugging)
+ clear_breakpoints();
+#endif
+ remote_close(0);
+ return;
+ }
+ if (inferior_pid == 0)
+ return;
+
+ ptrace(PT_KILL, inferior_pid, 0, 0);
+ wait(0);
+}
+
+/*
+ * Resume execution of the inferior process. If STEP is nonzero, single-step
+ * it. If SIGNAL is nonzero, give it that signal.
+ */
+void
+resume(step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ if (remote_debugging)
+ remote_resume(step, signal);
+ else {
+ ptrace(step ? PT_STEP : PT_CONTINUE, inferior_pid,
+ PT_ADDR_ANY, signal);
+ if (errno)
+ perror_with_name("ptrace");
+ }
+}
+
+#ifdef ATTACH_DETACH
+extern int attach_flag;
+
+/*
+ * Start debugging the process whose number is PID.
+ */
+attach(pid)
+ int pid;
+{
+ errno = 0;
+ ptrace(PT_ATTACH, pid, 0, 0);
+ if (errno)
+ perror_with_name("ptrace");
+ attach_flag = 1;
+ return pid;
+}
+
+/*
+ * Stop debugging the process whose number is PID and continue it
+ * with signal number SIGNAL. SIGNAL = 0 means just continue it.
+ */
+void
+detach(signal)
+ int signal;
+{
+ errno = 0;
+ ptrace(PT_DETACH, inferior_pid, PT_ADDR_ANY, signal);
+ if (errno)
+ perror_with_name("ptrace");
+ attach_flag = 0;
+}
+#endif /* ATTACH_DETACH */
+
+static unsigned int
+get_register_offset()
+{
+ unsigned int offset;
+ struct user u; /* XXX */
+ unsigned int flags = (char *) &u.u_pcb.pcb_flags - (char *) &u;
+
+ setregmap(ptrace(PT_READ_U, inferior_pid, (caddr_t)flags, 0));
+
+#ifdef NEWVM
+ offset = (char *) &u.u_kproc.kp_proc.p_md.md_regs - (char *) &u;
+ offset = ptrace(PT_READ_U, inferior_pid, (caddr_t)offset, 0) -
+ USRSTACK;
+#else
+ offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace(PT_READ_U, inferior_pid, (caddr_t)offset, 0) -
+ KERNEL_U_ADDR;
+#endif
+
+ return offset;
+}
+
+void
+fetch_inferior_registers()
+{
+ register int regno;
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+ unsigned int offset;
+
+ if (remote_debugging) {
+ extern char registers[];
+
+ remote_fetch_registers(registers);
+ return;
+ }
+
+ offset = get_register_offset();
+
+ for (regno = 0; regno < NUM_REGS; regno++) {
+ regaddr = register_addr(regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE(regno); i += sizeof(int)) {
+ *(int *)&buf[i] = ptrace(PT_READ_U, inferior_pid,
+ (caddr_t)regaddr, 0);
+ regaddr += sizeof(int);
+ }
+ supply_register(regno, buf);
+ }
+}
+
+/*
+ * Store our register values back into the inferior. If REGNO is -1, do this
+ * for all registers. Otherwise, REGNO specifies which register (so we can
+ * save time).
+ */
+store_inferior_registers(regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ extern char registers[];
+ register int i;
+ unsigned int offset;
+
+ if (remote_debugging) {
+ extern char registers[];
+
+ remote_store_registers(registers);
+ return;
+ }
+
+ offset = get_register_offset();
+
+ if (regno >= 0) {
+ regaddr = register_addr(regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE(regno); i += sizeof(int)) {
+ errno = 0;
+ ptrace(PT_WRITE_U, inferior_pid, (caddr_t)regaddr,
+ *(int *) &registers[REGISTER_BYTE(regno) + i]);
+ if (errno != 0) {
+ sprintf(buf, "writing register number %d(%d)",
+ regno, i);
+ perror_with_name(buf);
+ }
+ regaddr += sizeof(int);
+ }
+ } else
+ for (regno = 0; regno < NUM_REGS; regno++) {
+ regaddr = register_addr(regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE(regno);
+ i += sizeof(int)) {
+ errno = 0;
+ ptrace(PT_WRITE_U, inferior_pid,
+ (caddr_t)regaddr,
+ *(int *) &registers[REGISTER_BYTE(regno) + i]);
+ if (errno != 0) {
+ sprintf(buf,
+ "writing register number %d(%d)",
+ regno, i);
+ perror_with_name(buf);
+ }
+ regaddr += sizeof(int);
+ }
+ }
+}
+
+/*
+ * Copy LEN bytes from inferior's memory starting at MEMADDR to debugger
+ * memory starting at MYADDR. On failure (cannot read from inferior, usually
+ * because address is out of bounds) returns the value of errno.
+ */
+int
+read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof(int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count = (((memaddr + len) - addr) + sizeof(int) - 1) /
+ sizeof(int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca(count * sizeof(int));
+ extern int errno;
+
+ if (remote_debugging)
+ return (remote_read_inferior_memory(memaddr, myaddr, len));
+
+ /* Read all the longwords */
+ errno = 0;
+ for (i = 0; i < count && errno == 0; i++, addr += sizeof(int))
+ buffer[i] = ptrace(PT_READ_I, inferior_pid, (caddr_t)addr, 0);
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy((char *) buffer + (memaddr & (sizeof(int) - 1)), myaddr, len);
+ return(errno);
+}
+
+/*
+ * Copy LEN bytes of data from debugger memory at MYADDR to inferior's memory
+ * at MEMADDR. On failure (cannot write the inferior) returns the value of
+ * errno.
+ */
+
+int
+write_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof(int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count = (((memaddr + len) - addr) + sizeof(int) - 1) /
+ sizeof(int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca(count * sizeof(int));
+ extern int errno;
+
+ /*
+ * Fill start and end extra bytes of buffer with existing memory
+ * data.
+ */
+ if (remote_debugging)
+ return (remote_write_inferior_memory(memaddr, myaddr, len));
+
+ /*
+ * Fill start and end extra bytes of buffer with existing memory
+ * data.
+ */
+ buffer[0] = ptrace(PT_READ_I, inferior_pid, (caddr_t)addr, 0);
+
+ if (count > 1)
+ buffer[count - 1] = ptrace(PT_READ_I, inferior_pid,
+ (caddr_t)addr + (count - 1) * sizeof(int), 0);
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy(myaddr, (char *) buffer + (memaddr & (sizeof(int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ errno = 0;
+ for (i = 0; i < count && errno == 0; i++, addr += sizeof(int))
+ ptrace(PT_WRITE_I, inferior_pid, (caddr_t)addr, buffer[i]);
+
+ return(errno);
+}
+
+
+/*
+ * Work with core dump and executable files, for GDB.
+ * This code would be in core.c if it weren't machine-dependent.
+ */
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(hdr) 0
+#endif /* no N_TXTADDR */
+
+#ifndef N_DATADDR
+#define N_DATADDR(hdr) hdr.a_text
+#endif /* no N_DATADDR */
+
+/*
+ * Make COFF and non-COFF names for things a little more compatible to reduce
+ * conditionals later.
+ */
+
+#ifndef AOUTHDR
+#define AOUTHDR struct exec
+#endif
+
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+/* File names of core file and executable file. */
+
+extern char *corefile;
+extern char *execfile;
+
+/* Descriptors on which core file and executable file are open.
+ Note that the execchan is closed when an inferior is created
+ and reopened if the inferior dies or is killed. */
+
+extern int corechan;
+extern int execchan;
+
+/* Last modification time of executable file.
+ Also used in source.c to compare against mtime of a source file. */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file. */
+
+extern CORE_ADDR data_start;
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+ Note that the data area in the exec file is used only when there is no core file. */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data. */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data. */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data. */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data. */
+
+extern int stack_offset;
+
+/* a.out header saved in core file. */
+
+extern AOUTHDR core_aouthdr;
+
+/* a.out header of exec file. */
+
+extern AOUTHDR exec_aouthdr;
+
+extern void validate_files ();
+
+extern int (*core_file_hook)();
+
+#ifdef KERNELDEBUG
+/*
+ * Kernel debugging routines.
+ */
+
+#define IOTOP 0x100000 /* XXX should get this from include file */
+#define IOBASE 0xa0000 /* XXX should get this from include file */
+
+static CORE_ADDR file_offset;
+static CORE_ADDR lowram;
+static CORE_ADDR sbr;
+static CORE_ADDR slr;
+static struct pcb pcb;
+
+static CORE_ADDR
+ksym_lookup(name)
+ char *name;
+{
+ struct symbol *sym;
+ int i;
+
+ if ((i = lookup_misc_func(name)) < 0)
+ error("kernel symbol `%s' not found.", name);
+
+ return (misc_function_vector[i].address);
+}
+
+/*
+ * return true if 'len' bytes starting at 'addr' can be read out as
+ * longwords and/or locally cached (this is mostly for memory mapped
+ * i/o register access when debugging remote kernels).
+ *
+ * XXX the HP code does this differently with NEWVM
+ */
+static int
+ok_to_cache(addr, len)
+{
+ static CORE_ADDR atdevbase;
+
+ if (! atdevbase)
+ atdevbase = ksym_lookup("atdevbase");
+
+ if (addr >= atdevbase && addr < atdevbase + (IOTOP - IOBASE))
+ return (0);
+
+ return (1);
+}
+
+static
+physrd(addr, dat, len)
+ u_int addr;
+ char *dat;
+{
+ if (lseek(corechan, addr - file_offset, L_SET) == -1)
+ return (-1);
+ if (read(corechan, dat, len) != len)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * When looking at kernel data space through /dev/mem or with a core file, do
+ * virtual memory mapping.
+ */
+#ifdef NEWVM
+static CORE_ADDR
+vtophys(addr)
+ CORE_ADDR addr;
+{
+ CORE_ADDR v;
+ struct pte pte;
+ static CORE_ADDR PTD = -1;
+ CORE_ADDR current_ptd;
+
+ /*
+ * If we're looking at the kernel stack,
+ * munge the address to refer to the user space mapping instead;
+ * that way we get the requested process's kstack, not the running one.
+ */
+ if (addr >= kstack && addr < kstack + ctob(UPAGES))
+ addr = (addr - kstack) + curpcb;
+
+ /*
+ * We may no longer have a linear system page table...
+ *
+ * Here's the scoop. IdlePTD contains the physical address
+ * of a page table directory that always maps the kernel.
+ * IdlePTD is in memory that is mapped 1-to-1, so we can
+ * find it easily given its 'virtual' address from ksym_lookup().
+ * For hysterical reasons, the value of IdlePTD is stored in sbr.
+ *
+ * To look up a kernel address, we first convert it to a 1st-level
+ * address and look it up in IdlePTD. This gives us the physical
+ * address of a page table page; we extract the 2nd-level part of
+ * VA and read the 2nd-level pte. Finally, we add the offset part
+ * of the VA into the physical address from the pte and return it.
+ *
+ * User addresses are a little more complicated. If we don't have
+ * a current PCB from read_pcb(), we use PTD, which is the (fixed)
+ * virtual address of the current ptd. Since it's NOT in 1-to-1
+ * kernel space, we must look it up using IdlePTD. If we do have
+ * a pcb, we get the ptd from pcb_ptd.
+ */
+
+ if (INKERNEL(addr))
+ current_ptd = sbr;
+ else if (found_pcb == 0) {
+ if (PTD == -1)
+ PTD = vtophys(ksym_lookup("PTD"));
+ current_ptd = PTD;
+ } else
+ current_ptd = pcb.pcb_ptd;
+
+ /*
+ * Read the first-level page table (ptd).
+ */
+ v = current_ptd + ((unsigned)addr >> PD_SHIFT) * sizeof pte;
+ if (physrd(v, (char *)&pte, sizeof pte) || pte.pg_v == 0)
+ return (~0);
+
+ /*
+ * Read the second-level page table.
+ */
+ v = i386_ptob(pte.pg_pfnum) + ((addr&PT_MASK) >> PG_SHIFT) * sizeof pte;
+ if (physrd(v, (char *) &pte, sizeof(pte)) || pte.pg_v == 0)
+ return (~0);
+
+ addr = i386_ptob(pte.pg_pfnum) + (addr & PGOFSET);
+#if 0
+ printf("vtophys(%x) -> %x\n", oldaddr, addr);
+#endif
+ return (addr);
+}
+#else
+static CORE_ADDR
+vtophys(addr)
+ CORE_ADDR addr;
+{
+ CORE_ADDR v;
+ struct pte pte;
+ CORE_ADDR oldaddr = addr;
+
+ if (found_pcb == 0 && INUPAGE(addr)) {
+ static CORE_ADDR pSwtchmap;
+
+ if (pSwtchmap == 0)
+ pSwtchmap = vtophys(ksym_lookup("Swtchmap"));
+ addr = pSwtchmap;
+ } else if (INKERNEL(addr)) {
+ /*
+ * In system space get system pte. If valid or reclaimable
+ * then physical address is combination of its page number
+ * and the page offset of the original address.
+ */
+ addr = smxtob(btop(addr - KERNOFF)) - KERNOFF;
+ } else {
+ v = btop(addr);
+ if (v < pcb.pcb_p0lr)
+ addr = (CORE_ADDR) pcb.pcb_p0br +
+ v * sizeof (struct pte);
+ else if (v >= pcb.pcb_p1lr && v < P1PAGES)
+ addr = (CORE_ADDR) pcb.pcb_p0br +
+ ((pcb.pcb_szpt * NPTEPG - HIGHPAGES) -
+ (BTOPUSRSTACK - v)) * sizeof (struct pte);
+ else
+ return (~0);
+
+ /*
+ * For p0/p1 address, user-level page table should be in
+ * kernel vm. Do second-level indirect by recursing.
+ */
+ if (!INKERNEL(addr))
+ return (~0);
+
+ addr = vtophys(addr);
+ }
+ /*
+ * Addr is now address of the pte of the page we are interested in;
+ * get the pte and paste up the physical address.
+ */
+ if (physrd(addr, (char *) &pte, sizeof(pte)))
+ return (~0);
+
+ if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0))
+ return (~0);
+
+ addr = (CORE_ADDR)ptob(pte.pg_pfnum) + (oldaddr & PGOFSET);
+#if 0
+ printf("vtophys(%x) -> %x\n", oldaddr, addr);
+#endif
+ return (addr);
+}
+
+#endif
+
+static
+kvread(addr)
+ CORE_ADDR addr;
+{
+ CORE_ADDR paddr = vtophys(addr);
+
+ if (paddr != ~0)
+ if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0);
+ return (addr);
+
+ return (~0);
+}
+
+static void
+read_pcb(uaddr)
+ u_int uaddr;
+{
+ int i;
+ int *pcb_regs = (int *)&pcb;
+
+#ifdef NEWVM
+ if (physrd(uaddr, (char *)&pcb, sizeof pcb))
+ error("cannot read pcb at %x\n", uaddr);
+ printf("current pcb at %x\n", uaddr);
+#else
+ if (physrd(uaddr, (char *)&pcb, sizeof pcb))
+ error("cannot read pcb at %x\n", uaddr);
+ printf("p0br %x p0lr %x p1br %x p1lr %x\n",
+ pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
+#endif
+
+ /*
+ * get the register values out of the sys pcb and
+ * store them where `read_register' will find them.
+ */
+ for (i = 0; i < 8; ++i)
+ supply_register(i, &pcb_regs[i+10]);
+ supply_register(8, &pcb_regs[8]); /* eip */
+ supply_register(9, &pcb_regs[9]); /* eflags */
+ for (i = 10; i < 13; ++i) /* cs, ss, ds */
+ supply_register(i, &pcb_regs[i+9]);
+ supply_register(13, &pcb_regs[18]); /* es */
+ for (i = 14; i < 16; ++i) /* fs, gs */
+ supply_register(i, &pcb_regs[i+8]);
+
+ /* XXX 80387 registers? */
+}
+
+static void
+setup_kernel_debugging()
+{
+ struct stat stb;
+ int devmem = 0;
+ CORE_ADDR addr;
+
+ fstat(corechan, &stb);
+ if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
+ devmem = 1;
+
+#ifdef NEWVM
+ physrd(ksym_lookup("IdlePTD") - KERNOFF, &sbr, sizeof sbr);
+ slr = 2 * NPTEPG; /* XXX temporary */
+ printf("IdlePTD %x\n", sbr);
+ curpcb = ksym_lookup("curpcb") - KERNOFF;
+ physrd(curpcb, &curpcb, sizeof curpcb);
+ kstack = ksym_lookup("kstack");
+#else
+ sbr = ksym_lookup("Sysmap");
+ slr = ksym_lookup("Syssize");
+ printf("sbr %x slr %x\n", sbr, slr);
+#endif
+
+ /*
+ * pcb where "panic" saved registers in first thing in current
+ * u area.
+ */
+#ifndef NEWVM
+ read_pcb(vtophys(ksym_lookup("u")));
+#endif
+ found_pcb = 1;
+ if (!devmem) {
+ /* find stack frame */
+ CORE_ADDR panicstr;
+ char buf[256];
+ register char *cp;
+
+ panicstr = kvread(ksym_lookup("panicstr"));
+ if (panicstr == ~0)
+ return;
+ (void) kernel_core_file_hook(panicstr, buf, sizeof(buf));
+ for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
+ if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+ *cp = '?';
+ if (*cp)
+ *cp = '\0';
+ printf("panic: %s\n", buf);
+ read_pcb(ksym_lookup("dumppcb") - KERNOFF);
+ }
+#ifdef NEWVM
+ else
+ read_pcb(vtophys(kstack));
+#endif
+
+ stack_start = USRSTACK;
+ stack_end = USRSTACK + ctob(UPAGES);
+}
+
+set_paddr_command(arg)
+ char *arg;
+{
+ u_int uaddr;
+
+ if (!arg)
+ error_no_arg("ps-style address for new current process");
+ if (!kernel_debugging)
+ error("not debugging kernel");
+ uaddr = (u_int) parse_and_eval_address(arg);
+#ifndef NEWVM
+ read_pcb(ctob(uaddr));
+#else
+ /* p_addr is now a pcb virtual address */
+ read_pcb(vtophys(uaddr));
+ curpcb = uaddr;
+#endif
+
+ flush_cached_frames();
+ set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
+ select_frame(get_current_frame(), 0);
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local
+ * buffer 'buf'. Return 0 if read ok, 1 otherwise. On read
+ * errors, portion of buffer not read is zeroed.
+ */
+kernel_core_file_hook(addr, buf, len)
+ CORE_ADDR addr;
+ char *buf;
+ int len;
+{
+ int i;
+ CORE_ADDR paddr;
+
+ while (len > 0) {
+ paddr = vtophys(addr);
+ if (paddr == ~0) {
+ bzero(buf, len);
+ return (1);
+ }
+ /* we can't read across a page boundary */
+ i = min(len, NBPG - (addr & PGOFSET));
+ if (physrd(paddr, buf, i)) {
+ bzero(buf, len);
+ return (1);
+ }
+ buf += i;
+ addr += i;
+ len -= i;
+ }
+ return (0);
+}
+#endif
+
+core_file_command(filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+#ifdef KERNELDEBUG
+ struct stat stb;
+#endif
+
+ /*
+ * Discard all vestiges of any previous core file and mark data and
+ * stack spaces as empty.
+ */
+ if (corefile)
+ free(corefile);
+ corefile = 0;
+ core_file_hook = 0;
+
+ if (corechan >= 0)
+ close(corechan);
+ corechan = -1;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename == 0) {
+ if (from_tty)
+ printf("No core file now.\n");
+ return;
+ }
+ filename = tilde_expand(filename);
+ make_cleanup(free, filename);
+ if (have_inferior_p())
+ error("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open(filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name(filename);
+
+#ifdef KERNELDEBUG
+ fstat(corechan, &stb);
+
+ if (kernel_debugging) {
+ setup_kernel_debugging();
+ core_file_hook = kernel_core_file_hook;
+ } else if ((stb.st_mode & S_IFMT) == S_IFCHR &&
+ stb.st_rdev == makedev(2, 1)) {
+ /* looking at /dev/kmem */
+ data_offset = data_start = KERNOFF;
+ data_end = ~0; /* XXX */
+ stack_end = stack_start = data_end;
+ } else
+#endif
+ {
+ /*
+ * 4.2-style core dump file.
+ */
+ struct user u;
+ unsigned int reg_offset;
+
+ val = myread(corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name("Not a core file: reading upage");
+ if (val != sizeof u)
+ error("Not a core file: could only read %d bytes", val);
+
+ /*
+ * We are depending on exec_file_command having been
+ * called previously to set exec_data_start. Since
+ * the executable and the core file share the same
+ * text segment, the address of the data segment will
+ * be the same in both.
+ */
+ data_start = exec_data_start;
+
+#ifndef NEWVM
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /*
+ * Some machines put an absolute address in here and
+ * some put the offset in the upage of the regs.
+ */
+ reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+#else
+ /*
+ * 386bsd does not put the stack end in a fixed virtual
+ * location, so we get the beginning and depend on the
+ * MAXSSIZ constant for the full length of the stack to
+ * find the end.
+ * (See code & comments in kern_execve.c, search for USRSTACK)
+ */
+ stack_end = (CORE_ADDR) u.u_kproc.kp_eproc.e_vm.vm_maxsaddr
+ + MAXSSIZ;
+
+ data_end = data_start +
+ NBPG * u.u_kproc.kp_eproc.e_vm.vm_dsize;
+ stack_start = stack_end -
+ NBPG * u.u_kproc.kp_eproc.e_vm.vm_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG *
+ (UPAGES + u.u_kproc.kp_eproc.e_vm.vm_dsize);
+
+ reg_offset = (int) u.u_kproc.kp_proc.p_md.md_regs - USRSTACK;
+#endif
+
+ setregmap(u.u_pcb.pcb_flags);
+
+ /*
+ * I don't know where to find this info. So, for now,
+ * mark it as not available.
+ */
+ /* N_SET_MAGIC (core_aouthdr, 0); */
+ bzero ((char *) &core_aouthdr, sizeof core_aouthdr);
+
+ /*
+ * Read the register values out of the core file and
+ * store them where `read_register' will find them.
+ */
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++) {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek(corechan, register_addr(regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread(corechan, buf, sizeof buf)) < 0) {
+ char *buffer = (char *) alloca(strlen(reg_names[regno]) + 30);
+ strcpy(buffer, "Reading register ");
+ strcat(buffer, reg_names[regno]);
+ perror_with_name(buffer);
+ }
+ supply_register(regno, buf);
+ }
+ }
+ }
+#endif
+ if (filename[0] == '/')
+ corefile = savestring(filename, strlen(filename));
+ else
+ corefile = concat(current_directory, "/", filename);
+
+ set_current_frame(create_new_frame(read_register(FP_REGNUM),
+ read_pc()));
+ select_frame(get_current_frame(), 0);
+ validate_files();
+}
+
+exec_file_command(filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+
+ /*
+ * Eliminate all traces of old exec file. Mark text segment as empty.
+ */
+
+ if (execfile)
+ free(execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end = 0;
+ stack_start = 0;
+ stack_end = 0;
+ text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close(execchan);
+ execchan = -1;
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename) {
+ filename = tilde_expand(filename);
+ make_cleanup(free, filename);
+
+ execchan = openp(getenv("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name(filename);
+
+ {
+ struct stat st_exec;
+
+#ifdef HEADER_SEEK_FD
+ HEADER_SEEK_FD(execchan);
+#endif
+
+ val = myread(execchan, &exec_aouthdr, sizeof(AOUTHDR));
+
+ if (val < 0)
+ perror_with_name(filename);
+
+#ifdef KERNELDEBUG
+ if (kernel_debugging) {
+ /* Gross and disgusting XXX */
+ text_start = KERNTEXT_BASE;
+ exec_data_start = KERNTEXT_BASE +
+ (exec_aouthdr.a_text + 4095) & ~ 4095;
+ } else {
+#endif
+ text_start = N_TXTADDR(exec_aouthdr);
+ exec_data_start = N_DATADDR(exec_aouthdr);
+#ifdef KERNELDEBUG
+ }
+#endif
+
+ text_offset = N_TXTOFF(exec_aouthdr);
+ exec_data_offset = N_TXTOFF(exec_aouthdr) + exec_aouthdr.a_text;
+
+ text_end = text_start + exec_aouthdr.a_text;
+ exec_data_end = exec_data_start + exec_aouthdr.a_data;
+
+ fstat(execchan, &st_exec);
+ exec_mtime = st_exec.st_mtime;
+ }
+
+ validate_files();
+ } else if (from_tty)
+ printf("No exec file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
+
+int dummy_code[] = {
+ 0xb8909090, /* nop; nop; nop; movl $0x32323232,%eax */
+ 0x32323232,
+#define DUMMY_CALL_INDEX 1
+ 0x90ccd0ff, /* call %eax; int3; nop */
+};
+
+/*
+ * Build `dummy' call instructions on inferior's stack to cause
+ * it to call a subroutine.
+ *
+ * N.B. - code in wait_for_inferior requires that sp < pc < fp when
+ * we take the trap 2 above so it will recognize that we stopped
+ * at a `dummy' call. So, after the call sp is *not* decremented
+ * to clean the arguments, code & other stuff we lay on the stack.
+ * Since the regs are restored to saved values at the breakpoint,
+ * sp will get reset correctly. Also, this restore means we don't
+ * have to construct frame linkage info to save pc & fp. The lack
+ * of frame linkage means we can't do a backtrace, etc., if the
+ * called function gets a fault or hits a breakpoint but code in
+ * run_stack_dummy makes this impossible anyway.
+ */
+CORE_ADDR
+setup_dummy(sp, funaddr, nargs, args, struct_return_bytes, pushfn)
+ CORE_ADDR sp;
+ CORE_ADDR funaddr;
+ int nargs;
+ value *args;
+ int struct_return_bytes;
+ CORE_ADDR (*pushfn)();
+{
+ int padding, i;
+ CORE_ADDR top = sp, struct_addr, pc;
+
+ i = arg_stacklen(nargs, args) + struct_return_bytes
+ + sizeof(dummy_code);
+ if (i & 3)
+ padding = 4 - (i & 3);
+ else
+ padding = 0;
+ pc = sp - sizeof(dummy_code);
+ sp = pc - padding - struct_return_bytes;
+ struct_addr = sp;
+ while (--nargs >= 0)
+ sp = (*pushfn)(sp, *args++);
+ if (struct_return_bytes)
+ STORE_STRUCT_RETURN(struct_addr, sp);
+ write_register(SP_REGNUM, sp);
+
+ dummy_code[DUMMY_CALL_INDEX] = (int)funaddr;
+ write_memory(pc, (char *)dummy_code, sizeof(dummy_code));
+
+ return pc;
+}
+
+/* helper functions for m-i386.h */
+
+/* stdio style buffering to minimize calls to ptrace */
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[sizeof (int)];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() (codestream_addr + codestream_off)
+#define codestream_peek() (codestream_cnt == 0 ? \
+ codestream_fill(1): codestream_buf[codestream_off])
+#define codestream_get() (codestream_cnt-- == 0 ? \
+ codestream_fill(0) : codestream_buf[codestream_off++])
+
+static unsigned char
+codestream_fill (peek_flag)
+{
+ codestream_addr = codestream_next_addr;
+ codestream_next_addr += sizeof (int);
+ codestream_off = 0;
+ codestream_cnt = sizeof (int);
+ read_memory (codestream_addr,
+ (unsigned char *)codestream_buf,
+ sizeof (int));
+
+ if (peek_flag)
+ return (codestream_peek());
+ else
+ return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+{
+ codestream_next_addr = place & -sizeof (int);
+ codestream_cnt = 0;
+ codestream_fill (1);
+ while (codestream_tell() != place)
+ codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+ unsigned char *buf;
+{
+ unsigned char *p;
+ int i;
+ p = buf;
+ for (i = 0; i < count; i++)
+ *p++ = codestream_get ();
+}
+
+/* next instruction is a jump, move to target */
+static
+i386_follow_jump ()
+{
+ int long_delta;
+ short short_delta;
+ char byte_delta;
+ int data16;
+ int pos;
+
+ pos = codestream_tell ();
+
+ data16 = 0;
+ if (codestream_peek () == 0x66)
+ {
+ codestream_get ();
+ data16 = 1;
+ }
+
+ switch (codestream_get ())
+ {
+ case 0xe9:
+ /* relative jump: if data16 == 0, disp32, else disp16 */
+ if (data16)
+ {
+ codestream_read ((unsigned char *)&short_delta, 2);
+ pos += short_delta + 3; /* include size of jmp inst */
+ }
+ else
+ {
+ codestream_read ((unsigned char *)&long_delta, 4);
+ pos += long_delta + 5;
+ }
+ break;
+ case 0xeb:
+ /* relative jump, disp8 (ignore data16) */
+ codestream_read ((unsigned char *)&byte_delta, 1);
+ pos += byte_delta + 2;
+ break;
+ }
+ codestream_seek (pos + data16);
+}
+
+/*
+ * find & return amound a local space allocated, and advance codestream to
+ * first register push (if any)
+ *
+ * if entry sequence doesn't make sense, return -1, and leave
+ * codestream pointer random
+ */
+static long
+i386_get_frame_setup (pc)
+{
+ unsigned char op;
+
+ codestream_seek (pc);
+
+ i386_follow_jump ();
+
+ op = codestream_get ();
+
+ if (op == 0x58) /* popl %eax */
+ {
+ /*
+ * this function must start with
+ *
+ * popl %eax 0x58
+ * xchgl %eax, (%esp) 0x87 0x04 0x24
+ * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
+ *
+ * (the system 5 compiler puts out the second xchg
+ * inst, and the assembler doesn't try to optimize it,
+ * so the 'sib' form gets generated)
+ *
+ * this sequence is used to get the address of the return
+ * buffer for a function that returns a structure
+ */
+ int pos;
+ unsigned char buf[4];
+ static unsigned char proto1[3] = { 0x87,0x04,0x24 };
+ static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
+ pos = codestream_tell ();
+ codestream_read (buf, 4);
+ if (bcmp (buf, proto1, 3) == 0)
+ pos += 3;
+ else if (bcmp (buf, proto2, 4) == 0)
+ pos += 4;
+
+ codestream_seek (pos);
+ op = codestream_get (); /* update next opcode */
+ }
+
+ if (op == 0x55) /* pushl %esp */
+ {
+ /* check for movl %esp, %ebp - can be written two ways */
+ switch (codestream_get ())
+ {
+ case 0x8b:
+ if (codestream_get () != 0xec)
+ return (-1);
+ break;
+ case 0x89:
+ if (codestream_get () != 0xe5)
+ return (-1);
+ break;
+ default:
+ return (-1);
+ }
+ /* check for stack adjustment
+ *
+ * subl $XXX, %esp
+ *
+ * note: you can't subtract a 16 bit immediate
+ * from a 32 bit reg, so we don't have to worry
+ * about a data16 prefix
+ */
+ op = codestream_peek ();
+ if (op == 0x83)
+ {
+ /* subl with 8 bit immed */
+ codestream_get ();
+ if (codestream_get () != 0xec)
+ return (-1);
+ /* subl with signed byte immediate
+ * (though it wouldn't make sense to be negative)
+ */
+ return (codestream_get());
+ }
+ else if (op == 0x81)
+ {
+ /* subl with 32 bit immed */
+ int locals;
+ codestream_get();
+ if (codestream_get () != 0xec)
+ return (-1);
+ /* subl with 32 bit immediate */
+ codestream_read ((unsigned char *)&locals, 4);
+ return (locals);
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ else if (op == 0xc8)
+ {
+ /* enter instruction: arg is 16 bit unsigned immed */
+ unsigned short slocals;
+ codestream_read ((unsigned char *)&slocals, 2);
+ codestream_get (); /* flush final byte of enter instruction */
+ return (slocals);
+ }
+ return (-1);
+}
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+/* on the 386, the instruction following the call could be:
+ * popl %ecx - one arg
+ * addl $imm, %esp - imm/4 args; imm may be 8 or 32 bits
+ * anything else - zero args
+ */
+
+int
+i386_frame_num_args (fi)
+ struct frame_info fi;
+{
+ int retpc;
+ unsigned char op;
+ struct frame_info *pfi;
+
+ pfi = get_prev_frame_info ((fi));
+ if (pfi == 0)
+ {
+ /* Note: this can happen if we are looking at the frame for
+ main, because FRAME_CHAIN_VALID won't let us go into
+ start. If we have debugging symbols, that's not really
+ a big deal; it just means it will only show as many arguments
+ to main as are declared. */
+ return -1;
+ }
+ else
+ {
+ retpc = pfi->pc;
+ op = read_memory_integer (retpc, 1);
+ if (op == 0x59)
+ /* pop %ecx */
+ return 1;
+ else if (op == 0x83)
+ {
+ op = read_memory_integer (retpc+1, 1);
+ if (op == 0xc4)
+ /* addl $<signed imm 8 bits>, %esp */
+ return (read_memory_integer (retpc+2,1)&0xff)/4;
+ else
+ return 0;
+ }
+ else if (op == 0x81)
+ { /* add with 32 bit immediate */
+ op = read_memory_integer (retpc+1, 1);
+ if (op == 0xc4)
+ /* addl $<imm 32>, %esp */
+ return read_memory_integer (retpc+2, 4) / 4;
+ else
+ return 0;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+
+/*
+ * parse the first few instructions of the function to see
+ * what registers were stored.
+ *
+ * We handle these cases:
+ *
+ * The startup sequence can be at the start of the function,
+ * or the function can start with a branch to startup code at the end.
+ *
+ * %ebp can be set up with either the 'enter' instruction, or
+ * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful,
+ * but was once used in the sys5 compiler)
+ *
+ * Local space is allocated just below the saved %ebp by either the
+ * 'enter' instruction, or by 'subl $<size>, %esp'. 'enter' has
+ * a 16 bit unsigned argument for space to allocate, and the
+ * 'addl' instruction could have either a signed byte, or
+ * 32 bit immediate.
+ *
+ * Next, the registers used by this function are pushed. In
+ * the sys5 compiler they will always be in the order: %edi, %esi, %ebx
+ * (and sometimes a harmless bug causes it to also save but not restore %eax);
+ * however, the code below is willing to see the pushes in any order,
+ * and will handle up to 8 of them.
+ *
+ * If the setup sequence is at the end of the function, then the
+ * next instruction will be a branch back to the start.
+ */
+
+i386_frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ unsigned long locals;
+ unsigned char *p;
+ unsigned char op;
+ CORE_ADDR dummy_bottom;
+ CORE_ADDR adr;
+ int i;
+
+ bzero (fsrp, sizeof *fsrp);
+
+#if 0
+ /* if frame is the end of a dummy, compute where the
+ * beginning would be
+ */
+ dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
+
+ /* check if the PC is in the stack, in a dummy frame */
+ if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
+ {
+ /* all regs were saved by push_call_dummy () */
+ adr = fip->frame - 4;
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ fsrp->regs[i] = adr;
+ adr -= 4;
+ }
+ return;
+ }
+#endif
+
+ locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
+
+ if (locals >= 0)
+ {
+ adr = fip->frame - 4 - locals;
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_get ();
+ if (op < 0x50 || op > 0x57)
+ break;
+ fsrp->regs[op - 0x50] = adr;
+ adr -= 4;
+ }
+ }
+
+ fsrp->regs[PC_REGNUM] = fip->frame + 4;
+ fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+/* return pc of first real instruction */
+i386_skip_prologue (pc)
+{
+ unsigned char op;
+ int i;
+
+ if (i386_get_frame_setup (pc) < 0)
+ return (pc);
+
+ /* found valid frame setup - codestream now points to
+ * start of push instructions for saving registers
+ */
+
+ /* skip over register saves */
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_peek ();
+ /* break if not pushl inst */
+ if (op < 0x50 || op > 0x57)
+ break;
+ codestream_get ();
+ }
+
+ i386_follow_jump ();
+
+ return (codestream_tell ());
+}
+
+i386_pop_frame ()
+{
+ FRAME frame = get_current_frame ();
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ struct frame_info *fi;
+
+ fi = get_frame_info (frame);
+ fp = fi->frame;
+ get_frame_saved_regs (fi, &fsr);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ CORE_ADDR adr;
+ adr = fsr.regs[regnum];
+ if (adr)
+ write_register (regnum, read_memory_integer (adr, 4));
+ }
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
+ write_register (SP_REGNUM, fp + 8);
+ flush_cached_frames ();
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+}
+
+/* this table must line up with REGISTER_NAMES in m-i386.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int trapmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS,
+ tDS, tES, tES, tES /* lies: no fs or gs */
+};
+#if defined(FM_TRAP) || defined(EX_TRAPSTK)
+static int syscallmap[] =
+{
+ sEAX, sECX, sEDX, sEBX,
+ sESP, sEBP, sESI, sEDI,
+ sEIP, sEFLAGS, sCS, sSS,
+ sSS, sSS, sSS, sSS /* lies: no ds, es, fs or gs */
+};
+#endif
+static int *regmap;
+
+static void
+setregmap(flags)
+ int flags;
+{
+#ifdef FM_TRAP
+ regmap = flags & FM_TRAP ? trapmap: syscallmap;
+#elif EX_TRAPSTK
+ regmap = flags & EX_TRAPSTK ? trapmap : syscallmap;
+#else
+ regmap = trapmap; /* the lesser evil */
+#endif
+}
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+i386_register_u_addr (blockend, regnum)
+{
+#if 0
+ /* this will be needed if fp registers are reinstated */
+ /* for now, you can look at them with 'info float'
+ * sys5 wont let you change them with ptrace anyway
+ */
+ if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
+ {
+ int ubase, fpstate;
+ struct user u;
+ ubase = blockend + 4 * (SS + 1) - KSTKSZ;
+ fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
+ return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+ }
+ else
+#endif
+ return (blockend + 4 * regmap[regnum]);
+}
+
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ long *lp;
+ /* push extended mode on 387 stack, then pop in double mode
+ *
+ * first, set exception masks so no error is generated -
+ * number will be rounded to inf or 0, if necessary
+ */
+ asm ("pushl %eax"); /* grab a stack slot */
+ asm ("fstcw (%esp)"); /* get 387 control word */
+ asm ("movl (%esp),%eax"); /* save old value */
+ asm ("orl $0x3f,%eax"); /* mask all exceptions */
+ asm ("pushl %eax");
+ asm ("fldcw (%esp)"); /* load new value into 387 */
+
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldt (%eax)"); /* push extended number on 387 stack */
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpl (%eax)"); /* pop double */
+ asm ("fwait");
+
+ asm ("popl %eax"); /* flush modified control word */
+ asm ("fnclex"); /* clear exceptions */
+ asm ("fldcw (%esp)"); /* restore original control word */
+ asm ("popl %eax"); /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ /* push double mode on 387 stack, then pop in extended mode
+ * no errors are possible because every 64-bit pattern
+ * can be converted to an extended
+ */
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldl (%eax)");
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpt (%eax)");
+ asm ("fwait");
+}
+
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
+
+static
+print_387_control_word (control)
+unsigned short control;
+{
+ printf ("control 0x%04x: ", control);
+ printf ("compute to ");
+ switch ((control >> 8) & 3)
+ {
+ case 0: printf ("24 bits; "); break;
+ case 1: printf ("(bad); "); break;
+ case 2: printf ("53 bits; "); break;
+ case 3: printf ("64 bits; "); break;
+ }
+ printf ("round ");
+ switch ((control >> 10) & 3)
+ {
+ case 0: printf ("NEAREST; "); break;
+ case 1: printf ("DOWN; "); break;
+ case 2: printf ("UP; "); break;
+ case 3: printf ("CHOP; "); break;
+ }
+ if (control & 0x3f)
+ {
+ printf ("mask:");
+ if (control & 0x0001) printf (" INVALID");
+ if (control & 0x0002) printf (" DENORM");
+ if (control & 0x0004) printf (" DIVZ");
+ if (control & 0x0008) printf (" OVERF");
+ if (control & 0x0010) printf (" UNDERF");
+ if (control & 0x0020) printf (" LOS");
+ printf (";");
+ }
+ printf ("\n");
+ if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
+ control & 0xe080);
+}
+
+static
+print_387_status_word (status)
+ unsigned short status;
+{
+ printf ("status 0x%04x: ", status);
+ if (status & 0xff)
+ {
+ printf ("exceptions:");
+ if (status & 0x0001) printf (" INVALID");
+ if (status & 0x0002) printf (" DENORM");
+ if (status & 0x0004) printf (" DIVZ");
+ if (status & 0x0008) printf (" OVERF");
+ if (status & 0x0010) printf (" UNDERF");
+ if (status & 0x0020) printf (" LOS");
+ if (status & 0x0040) printf (" FPSTACK");
+ printf ("; ");
+ }
+ printf ("flags: %d%d%d%d; ",
+ (status & 0x4000) != 0,
+ (status & 0x0400) != 0,
+ (status & 0x0200) != 0,
+ (status & 0x0100) != 0);
+
+ printf ("top %d\n", (status >> 11) & 7);
+}
+
+static
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf ("opcode 0x%x; ", ep->opcode);
+ printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
+ printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
+
+ top = (ep->status >> 11) & 7;
+
+ printf (" regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ int st_regno;
+ double val;
+
+ /* The physical regno `fpreg' is only relevant as an index into the
+ * tag word. Logical `%st' numbers are required for indexing ep->regs.
+ */
+ st_regno = (fpreg + 8 - top) & 7;
+
+ printf ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : " ");
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf ("valid "); break;
+ case 1: printf ("zero "); break;
+ case 2: printf ("trap "); break;
+ case 3: printf ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf ("%02x", ep->regs[st_regno][i]);
+
+ i387_to_double (ep->regs[st_regno], (char *)&val);
+ printf (" %g\n", val);
+ }
+#if 0 /* reserved fields are always 0xffff on 486's */
+ if (ep->r0)
+ printf ("warning: reserved0 is 0x%x\n", ep->r0);
+ if (ep->r1)
+ printf ("warning: reserved1 is 0x%x\n", ep->r1);
+ if (ep->r2)
+ printf ("warning: reserved2 is 0x%x\n", ep->r2);
+ if (ep->r3)
+ printf ("warning: reserved3 is 0x%x\n", ep->r3);
+#endif
+}
+
+#ifdef __FreeBSD__
+#define fpstate save87
+#define U_FPSTATE(u) u.u_pcb.pcb_savefpu
+#endif
+
+#ifndef U_FPSTATE
+#define U_FPSTATE(u) u.u_fpstate
+#endif
+
+i386_float_info ()
+{
+ struct user u; /* just for address computations */
+ int i;
+ /* fpstate defined in <sys/user.h> */
+ struct fpstate *fpstatep;
+ char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
+ unsigned int uaddr;
+ char fpvalid;
+ unsigned int rounded_addr;
+ unsigned int rounded_size;
+ extern int corechan;
+ int skip;
+
+#ifndef __FreeBSD__ /* XXX - look at pcb flags */
+ uaddr = (char *)&u.u_fpvalid - (char *)&u;
+ if (have_inferior_p())
+ {
+ unsigned int data;
+ unsigned int mask;
+
+ rounded_addr = uaddr & -sizeof (int);
+ data = ptrace (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0);
+ mask = 0xff << ((uaddr - rounded_addr) * 8);
+
+ fpvalid = ((data & mask) != 0);
+ }
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror ("seek on core file");
+ if (myread (corechan, &fpvalid, 1) < 0)
+ perror ("read on core file");
+
+ }
+
+ if (fpvalid == 0)
+ {
+ printf ("no floating point status saved\n");
+ return;
+ }
+#endif /* not __FreeBSD__ */
+
+ uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+ if (have_inferior_p ())
+ {
+ int *ip;
+
+ rounded_addr = uaddr & -sizeof (int);
+ rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
+ sizeof (int) - 1) / sizeof (int);
+ skip = uaddr - rounded_addr;
+
+ ip = (int *)buf;
+ for (i = 0; i < rounded_size; i++)
+ {
+ *ip++ = ptrace (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0);
+ rounded_addr += sizeof (int);
+ }
+ }
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror_with_name ("seek on core file");
+ if (myread (corechan, buf, sizeof (struct fpstate)) < 0)
+ perror_with_name ("read from core file");
+ skip = 0;
+ }
+
+ fpstatep = (struct fpstate *)(buf + skip);
+#ifdef __FreeBSD__
+ print_387_status (fpstatep->sv_ex_sw, (struct env387 *)fpstatep);
+#else
+ print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
+#endif
+}
+
+void
+_initialize_i386bsd_dep()
+{
+#ifdef KERNELDEBUG
+ add_com ("process-address", class_obscure, set_paddr_command,
+ "The process identified by (ps-style) ADDR becomes the\n\
+\"current\" process context for kernel debugging.");
+ add_com_alias ("paddr", "process-address", class_obscure, 0);
+#endif
+}
diff --git a/gnu/usr.bin/kgdb/config/m-i386-sv32.h b/gnu/usr.bin/kgdb/config/m-i386-sv32.h
new file mode 100644
index 000000000000..38fb4eb6d5b6
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/m-i386-sv32.h
@@ -0,0 +1,28 @@
+/* Macro defintions for i386, running System V 3.2.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "m-i386.h"
+
+/* Apparently there is inconsistency among various System V's about what
+ the name of this field is. */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
+
+/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
+ is not. This makes problems for inflow.c. */
+#define TIOCGETC_BROKEN
diff --git a/gnu/usr.bin/kgdb/config/m-i386.h b/gnu/usr.bin/kgdb/config/m-i386.h
new file mode 100644
index 000000000000..5449ec454c95
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/m-i386.h
@@ -0,0 +1,394 @@
+/* Macro defintions for i386.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Define the bit, byte, and word ordering of the machine. */
+/* #define BITS_BIG_ENDIAN */
+/* #define BYTES_BIG_ENDIAN */
+/* #define WORDS_BIG_ENDIAN */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+
+#ifndef i386
+#define i386
+#endif
+
+/* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
+Sys V/386 3.2.
+
+On some machines, gdb crashes when it's starting up while calling the
+vendor's termio tgetent() routine. It always works when run under
+itself (actually, under 3.2, it's not an infinitely recursive bug.)
+After some poking around, it appears that depending on the environment
+size, or whether you're running YP, or the phase of the moon or something,
+the stack is not always long-aligned when main() is called, and tgetent()
+takes strong offense at that. On some machines this bug never appears, but
+on those where it does, it occurs quite reliably. */
+#define ALIGN_STACK_ON_STARTUP
+
+/* define USG if you are using sys5 /usr/include's */
+#define USG
+
+/* USG systems need these */
+#define vfork() fork()
+#define MAXPATHLEN 500
+
+/* define this if you don't have the extension to coff that allows
+ * file names to appear in the string table
+ * (aux.x_file.x_foff)
+ */
+#define COFF_NO_LONG_FILE_NAMES
+
+/* turn this on when rest of gdb is ready */
+/* #define IEEE_FLOAT */
+
+#define NBPG NBPC
+#define UPAGES USIZE
+
+#define HAVE_TERMIO
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+/* #define SET_STACK_LIMIT_HUGE not in sys5 */
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+/* #define NAMES_HAVE_UNDERSCORE */
+
+/* Specify debugger information format. */
+
+/* #define READ_DBX_FORMAT */
+#define COFF_FORMAT
+
+/* number of traps that happen between exec'ing the shell
+ * to run an inferior, and when we finally get to
+ * the inferior code. This is 2 on most implementations.
+ */
+#define START_INFERIOR_TRAPS_EXPECTED 4
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0xe0000000
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0x80000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 1
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the 386. */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+
+
+/* Largest integer type */
+#define LONGEST long
+
+/* Name of the builtin type for the LONGEST type above. */
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 16
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* the order of the first 8 registers must match the compiler's
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "ps", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP_REGNUM 5 /* Contains address of executing stack frame */
+#define SP_REGNUM 4 /* Contains address of top of stack */
+
+#define PC_REGNUM 8
+#define PS_REGNUM 9
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { (SP) -= sizeof (ADDR); \
+ write_memory ((SP), &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { i386_pop_frame (); }
+
+/* this is
+ * call 11223344 (32 bit relative)
+ * int3
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
+{ \
+ int from, to, delta, loc; \
+ loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+ from = loc + 5; \
+ to = (int)(fun); \
+ delta = to - from; \
+ *(int *)((char *)(dummyname) + 1) = delta; \
+}
+
+
+#if 0
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) {}
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR {}
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR {}
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS {}
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS {}
+#endif
diff --git a/gnu/usr.bin/kgdb/config/m-i386bsd.h b/gnu/usr.bin/kgdb/config/m-i386bsd.h
new file mode 100644
index 000000000000..15d97b23d339
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/m-i386bsd.h
@@ -0,0 +1,375 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1991 by William Jolitz at UUNET Technologies, Inc.
+ *
+ * @(#)m-i386bsd.h 6.7 (Berkeley) 5/8/91
+ */
+
+/* Macro definitions for i386.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Define the bit, byte, and word ordering of the machine. */
+/* #define BITS_BIG_ENDIAN */
+/* #define BYTES_BIG_ENDIAN */
+/* #define WORDS_BIG_ENDIAN */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ * [ MODIFIED FOR 386BSD W. Jolitz ]
+ */
+
+#ifndef i386
+#define i386 1
+#define i386b 1
+#endif
+
+#define IEEE_FLOAT
+#define LONG_LONG
+
+/* Library stuff: POSIX tty (not supported yet), V7 tty (sigh), vprintf. */
+
+#define HAVE_TERMIOS 1
+#define USE_OLD_TTY 1
+#define HAVE_VPRINTF 1
+
+/* We support local and remote kernel debugging. */
+
+#define KERNELDEBUG 1
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Specify debugger information format. */
+
+#define READ_DBX_FORMAT
+
+/* number of traps that happen between exec'ing the shell
+ * to run an inferior, and when we finally get to
+ * the inferior code. This is 2 on most implementations.
+ */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#ifdef NEWVM
+#include <machine/vmparam.h>
+#define KERNEL_U_ADDR USRSTACK
+#else
+#define KERNEL_U_ADDR 0xfdffd000
+#endif
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR KERNEL_U_ADDR
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 1
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) \
+ strchr("\302\303\312\313\317", read_memory_integer(pc, 1))
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the 386. */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+
+
+/* Largest integer type */
+#define LONGEST long long
+
+/* Name of the builtin type for the LONGEST type above. */
+#define BUILTIN_TYPE_LONGEST builtin_type_long_long
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 16
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* the order of the first 8 registers must match the compiler's
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "ps", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP_REGNUM 5 /* Contains address of executing stack frame */
+#define SP_REGNUM 4 /* Contains address of top of stack */
+
+#define PC_REGNUM 8
+#define PS_REGNUM 9
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { (SP) -= sizeof (ADDR); \
+ write_memory ((SP), &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+#ifdef KERNELDEBUG
+#define KERNTEXT_BASE 0xfe000000
+#ifdef NEWVM
+#define KERNSTACK_TOP (read_register(SP_REGNUM) + 0x2000) /* approximate */
+#else
+/* #define KERNSTACK_TOP (P1PAGES << PGSHIFT) */
+#define KERNSTACK_TOP 0xfe000000
+#endif
+extern int kernel_debugging;
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && \
+ !kernel_debugging ? outside_startup_file(FRAME_SAVED_PC(thisframe)) :\
+ (chain >= read_register(SP_REGNUM) && chain < KERNSTACK_TOP))
+#else
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+#endif
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { i386_pop_frame (); }
+
+#define NEW_CALL_FUNCTION
+
+#if 0
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) {}
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR {}
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR {}
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS {}
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS {}
+#endif
diff --git a/gnu/usr.bin/kgdb/config/m-i386g-sv32.h b/gnu/usr.bin/kgdb/config/m-i386g-sv32.h
new file mode 100644
index 000000000000..3d69eea184e0
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/m-i386g-sv32.h
@@ -0,0 +1,28 @@
+/* Macro defintions for i386, running System V 3.2.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "m-i386gas.h"
+
+/* Apparently there is inconsistency among various System V's about what
+ the name of this field is. */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
+
+/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
+ is not. This makes problems for inflow.c. */
+#define TIOCGETC_BROKEN
diff --git a/gnu/usr.bin/kgdb/config/m-i386gas.h b/gnu/usr.bin/kgdb/config/m-i386gas.h
new file mode 100644
index 000000000000..fbd21385cc77
--- /dev/null
+++ b/gnu/usr.bin/kgdb/config/m-i386gas.h
@@ -0,0 +1,37 @@
+/* Macro definitions for i386 using the GNU object file format.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ *
+ * i386gnu: COFF_ENCAPSULATE
+ */
+
+
+#define COFF_ENCAPSULATE
+
+#include "m-i386.h"
+
+
+#define NAMES_HAVE_UNDERSCORE
+
+#undef COFF_FORMAT
+#define READ_DBX_FORMAT
+
diff --git a/gnu/usr.bin/kgdb/copying.c b/gnu/usr.bin/kgdb/copying.c
new file mode 100644
index 000000000000..b3d75198078e
--- /dev/null
+++ b/gnu/usr.bin/kgdb/copying.c
@@ -0,0 +1,215 @@
+/* Do not modify this file; it is created automatically
+ by copying.awk. */
+extern int immediate_quit;
+static void
+copying_info ()
+{
+ immediate_quit++;
+ printf_filtered ("\n");
+ printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
+ printf_filtered (" Version 1, February 1989\n");
+ printf_filtered ("\n");
+ printf_filtered (" Copyright (C) 1989 Free Software Foundation, Inc.\n");
+ printf_filtered (" 675 Mass Ave, Cambridge, MA 02139, USA\n");
+ printf_filtered (" Everyone is permitted to copy and distribute verbatim copies\n");
+ printf_filtered (" of this license document, but changing it is not allowed.\n");
+ printf_filtered ("\n");
+ printf_filtered (" Preamble\n");
+ printf_filtered ("\n");
+ printf_filtered (" The license agreements of most software companies try to keep users\n");
+ printf_filtered ("at the mercy of those companies. By contrast, our General Public\n");
+ printf_filtered ("License is intended to guarantee your freedom to share and change free\n");
+ printf_filtered ("software--to make sure the software is free for all its users. The\n");
+ printf_filtered ("General Public License applies to the Free Software Foundation's\n");
+ printf_filtered ("software and to any other program whose authors commit to using it.\n");
+ printf_filtered ("You can use it for your programs, too.\n");
+ printf_filtered ("\n");
+ printf_filtered (" When we speak of free software, we are referring to freedom, not\n");
+ printf_filtered ("price. Specifically, the General Public License is designed to make\n");
+ printf_filtered ("sure that you have the freedom to give away or sell copies of free\n");
+ printf_filtered ("software, that you receive source code or can get it if you want it,\n");
+ printf_filtered ("that you can change the software or use pieces of it in new free\n");
+ printf_filtered ("programs; and that you know you can do these things.\n");
+ printf_filtered ("\n");
+ printf_filtered (" To protect your rights, we need to make restrictions that forbid\n");
+ printf_filtered ("anyone to deny you these rights or to ask you to surrender the rights.\n");
+ printf_filtered ("These restrictions translate to certain responsibilities for you if you\n");
+ printf_filtered ("distribute copies of the software, or if you modify it.\n");
+ printf_filtered ("\n");
+ printf_filtered (" For example, if you distribute copies of a such a program, whether\n");
+ printf_filtered ("gratis or for a fee, you must give the recipients all the rights that\n");
+ printf_filtered ("you have. You must make sure that they, too, receive or can get the\n");
+ printf_filtered ("source code. And you must tell them their rights.\n");
+ printf_filtered ("\n");
+ printf_filtered (" We protect your rights with two steps: (1) copyright the software, and\n");
+ printf_filtered ("(2) offer you this license which gives you legal permission to copy,\n");
+ printf_filtered ("distribute and/or modify the software.\n");
+ printf_filtered ("\n");
+ printf_filtered (" Also, for each author's protection and ours, we want to make certain\n");
+ printf_filtered ("that everyone understands that there is no warranty for this free\n");
+ printf_filtered ("software. If the software is modified by someone else and passed on, we\n");
+ printf_filtered ("want its recipients to know that what they have is not the original, so\n");
+ printf_filtered ("that any problems introduced by others will not reflect on the original\n");
+ printf_filtered ("authors' reputations.\n");
+ printf_filtered ("\n");
+ printf_filtered (" The precise terms and conditions for copying, distribution and\n");
+ printf_filtered ("modification follow.\n");
+ printf_filtered (" \n");
+ printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
+ printf_filtered (" TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n");
+ printf_filtered ("\n");
+ printf_filtered (" 0. This License Agreement applies to any program or other work which\n");
+ printf_filtered ("contains a notice placed by the copyright holder saying it may be\n");
+ printf_filtered ("distributed under the terms of this General Public License. The\n");
+ printf_filtered ("\"Program\", below, refers to any such program or work, and a \"work based\n");
+ printf_filtered ("on the Program\" means either the Program or any work containing the\n");
+ printf_filtered ("Program or a portion of it, either verbatim or with modifications. Each\n");
+ printf_filtered ("licensee is addressed as \"you\".\n");
+ printf_filtered ("\n");
+ printf_filtered (" 1. You may copy and distribute verbatim copies of the Program's source\n");
+ printf_filtered ("code as you receive it, in any medium, provided that you conspicuously and\n");
+ printf_filtered ("appropriately publish on each copy an appropriate copyright notice and\n");
+ printf_filtered ("disclaimer of warranty; keep intact all the notices that refer to this\n");
+ printf_filtered ("General Public License and to the absence of any warranty; and give any\n");
+ printf_filtered ("other recipients of the Program a copy of this General Public License\n");
+ printf_filtered ("along with the Program. You may charge a fee for the physical act of\n");
+ printf_filtered ("transferring a copy.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 2. You may modify your copy or copies of the Program or any portion of\n");
+ printf_filtered ("it, and copy and distribute such modifications under the terms of Paragraph\n");
+ printf_filtered ("1 above, provided that you also do the following:\n");
+ printf_filtered ("\n");
+ printf_filtered (" a) cause the modified files to carry prominent notices stating that\n");
+ printf_filtered (" you changed the files and the date of any change; and\n");
+ printf_filtered ("\n");
+ printf_filtered (" b) cause the whole of any work that you distribute or publish, that\n");
+ printf_filtered (" in whole or in part contains the Program or any part thereof, either\n");
+ printf_filtered (" with or without modifications, to be licensed at no charge to all\n");
+ printf_filtered (" third parties under the terms of this General Public License (except\n");
+ printf_filtered (" that you may choose to grant warranty protection to some or all\n");
+ printf_filtered (" third parties, at your option).\n");
+ printf_filtered ("\n");
+ printf_filtered (" c) If the modified program normally reads commands interactively when\n");
+ printf_filtered (" run, you must cause it, when started running for such interactive use\n");
+ printf_filtered (" in the simplest and most usual way, to print or display an\n");
+ printf_filtered (" announcement including an appropriate copyright notice and a notice\n");
+ printf_filtered (" that there is no warranty (or else, saying that you provide a\n");
+ printf_filtered (" warranty) and that users may redistribute the program under these\n");
+ printf_filtered (" conditions, and telling the user how to view a copy of this General\n");
+ printf_filtered (" Public License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" d) You may charge a fee for the physical act of transferring a\n");
+ printf_filtered (" copy, and you may at your option offer warranty protection in\n");
+ printf_filtered (" exchange for a fee.\n");
+ printf_filtered ("\n");
+ printf_filtered ("Mere aggregation of another independent work with the Program (or its\n");
+ printf_filtered ("derivative) on a volume of a storage or distribution medium does not bring\n");
+ printf_filtered ("the other work under the scope of these terms.\n");
+ printf_filtered (" \n");
+ printf_filtered (" 3. You may copy and distribute the Program (or a portion or derivative of\n");
+ printf_filtered ("it, under Paragraph 2) in object code or executable form under the terms of\n");
+ printf_filtered ("Paragraphs 1 and 2 above provided that you also do one of the following:\n");
+ printf_filtered ("\n");
+ printf_filtered (" a) accompany it with the complete corresponding machine-readable\n");
+ printf_filtered (" source code, which must be distributed under the terms of\n");
+ printf_filtered (" Paragraphs 1 and 2 above; or,\n");
+ printf_filtered ("\n");
+ printf_filtered (" b) accompany it with a written offer, valid for at least three\n");
+ printf_filtered (" years, to give any third party free (except for a nominal charge\n");
+ printf_filtered (" for the cost of distribution) a complete machine-readable copy of the\n");
+ printf_filtered (" corresponding source code, to be distributed under the terms of\n");
+ printf_filtered (" Paragraphs 1 and 2 above; or,\n");
+ printf_filtered ("\n");
+ printf_filtered (" c) accompany it with the information you received as to where the\n");
+ printf_filtered (" corresponding source code may be obtained. (This alternative is\n");
+ printf_filtered (" allowed only for noncommercial distribution and only if you\n");
+ printf_filtered (" received the program in object code or executable form alone.)\n");
+ printf_filtered ("\n");
+ printf_filtered ("Source code for a work means the preferred form of the work for making\n");
+ printf_filtered ("modifications to it. For an executable file, complete source code means\n");
+ printf_filtered ("all the source code for all modules it contains; but, as a special\n");
+ printf_filtered ("exception, it need not include source code for modules which are standard\n");
+ printf_filtered ("libraries that accompany the operating system on which the executable\n");
+ printf_filtered ("file runs, or for standard header files or definitions files that\n");
+ printf_filtered ("accompany that operating system.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 4. You may not copy, modify, sublicense, distribute or transfer the\n");
+ printf_filtered ("Program except as expressly provided under this General Public License.\n");
+ printf_filtered ("Any attempt otherwise to copy, modify, sublicense, distribute or transfer\n");
+ printf_filtered ("the Program is void, and will automatically terminate your rights to use\n");
+ printf_filtered ("the Program under this License. However, parties who have received\n");
+ printf_filtered ("copies, or rights to use copies, from you under this General Public\n");
+ printf_filtered ("License will not have their licenses terminated so long as such parties\n");
+ printf_filtered ("remain in full compliance.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 5. By copying, distributing or modifying the Program (or any work based\n");
+ printf_filtered ("on the Program) you indicate your acceptance of this license to do so,\n");
+ printf_filtered ("and all its terms and conditions.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 6. Each time you redistribute the Program (or any work based on the\n");
+ printf_filtered ("Program), the recipient automatically receives a license from the original\n");
+ printf_filtered ("licensor to copy, distribute or modify the Program subject to these\n");
+ printf_filtered ("terms and conditions. You may not impose any further restrictions on the\n");
+ printf_filtered ("recipients' exercise of the rights granted herein.\n");
+ printf_filtered (" \n");
+ printf_filtered (" 7. The Free Software Foundation may publish revised and/or new versions\n");
+ printf_filtered ("of the General Public License from time to time. Such new versions will\n");
+ printf_filtered ("be similar in spirit to the present version, but may differ in detail to\n");
+ printf_filtered ("address new problems or concerns.\n");
+ printf_filtered ("\n");
+ printf_filtered ("Each version is given a distinguishing version number. If the Program\n");
+ printf_filtered ("specifies a version number of the license which applies to it and \"any\n");
+ printf_filtered ("later version\", you have the option of following the terms and conditions\n");
+ printf_filtered ("either of that version or of any later version published by the Free\n");
+ printf_filtered ("Software Foundation. If the Program does not specify a version number of\n");
+ printf_filtered ("the license, you may choose any version ever published by the Free Software\n");
+ printf_filtered ("Foundation.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 8. If you wish to incorporate parts of the Program into other free\n");
+ printf_filtered ("programs whose distribution conditions are different, write to the author\n");
+ printf_filtered ("to ask for permission. For software which is copyrighted by the Free\n");
+ printf_filtered ("Software Foundation, write to the Free Software Foundation; we sometimes\n");
+ printf_filtered ("make exceptions for this. Our decision will be guided by the two goals\n");
+ printf_filtered ("of preserving the free status of all derivatives of our free software and\n");
+ printf_filtered ("of promoting the sharing and reuse of software generally.\n");
+ printf_filtered ("\n");
+ immediate_quit--;
+}
+
+static void
+warranty_info ()
+{
+ immediate_quit++;
+ printf_filtered (" NO WARRANTY\n");
+ printf_filtered ("\n");
+ printf_filtered (" 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");
+ printf_filtered ("FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n");
+ printf_filtered ("OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");
+ printf_filtered ("PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");
+ printf_filtered ("OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");
+ printf_filtered ("MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n");
+ printf_filtered ("TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n");
+ printf_filtered ("PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");
+ printf_filtered ("REPAIR OR CORRECTION.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");
+ printf_filtered ("WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");
+ printf_filtered ("REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");
+ printf_filtered ("INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");
+ printf_filtered ("OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");
+ printf_filtered ("TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");
+ printf_filtered ("YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");
+ printf_filtered ("PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");
+ printf_filtered ("POSSIBILITY OF SUCH DAMAGES.\n");
+ printf_filtered ("\n");
+ immediate_quit--;
+}
+
+void
+_initialize_copying ()
+{
+ add_info ("copying", copying_info,
+ "Conditions for redistributing copies of GDB.");
+ add_info ("warranty", warranty_info,
+ "Various kinds of warranty you do not have.");
+}
diff --git a/gnu/usr.bin/kgdb/core.c b/gnu/usr.bin/kgdb/core.c
new file mode 100644
index 000000000000..8272794e0d22
--- /dev/null
+++ b/gnu/usr.bin/kgdb/core.c
@@ -0,0 +1,579 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)core.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Work with core dump and executable files, for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#include <a.out.h>
+#endif
+#ifndef N_MAGIC
+#ifdef COFF_FORMAT
+#define N_MAGIC(exec) ((exec).magic)
+#else
+#define N_MAGIC(exec) ((exec).a_magic)
+#endif
+#endif
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#ifdef UMAX_CORE
+#include <sys/ptrace.h>
+#else
+#include <sys/user.h>
+#endif
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(hdr) 0
+#endif /* no N_TXTADDR */
+
+#ifndef N_DATADDR
+#define N_DATADDR(hdr) hdr.a_text
+#endif /* no N_DATADDR */
+
+#ifndef COFF_FORMAT
+#ifndef AOUTHDR
+#define AOUTHDR struct exec
+#endif
+#endif
+
+extern core_file_command (), exec_file_command ();
+
+/* Hook for `exec_file_command' command to call. */
+
+void (*exec_file_display_hook) ();
+
+/* File names of core file and executable file. */
+
+char *corefile;
+char *execfile;
+
+/* Descriptors on which core file and executable file are open.
+ Note that the execchan is closed when an inferior is created
+ and reopened if the inferior dies or is killed. */
+
+int corechan;
+int execchan;
+
+/* Last modification time of executable file.
+ Also used in source.c to compare against mtime of a source file. */
+
+int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file. */
+
+CORE_ADDR data_start;
+CORE_ADDR data_end;
+CORE_ADDR stack_start;
+CORE_ADDR stack_end;
+
+#if defined (REG_STACK_SEGMENT)
+/* Start and end of the register stack segment. */
+CORE_ADDR reg_stack_start;
+CORE_ADDR reg_stack_end;
+#endif /* REG_STACK_SEGMENT */
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+ Note that the data area in the exec file is used only when there is no core file. */
+
+CORE_ADDR text_start;
+CORE_ADDR text_end;
+
+CORE_ADDR exec_data_start;
+CORE_ADDR exec_data_end;
+
+/* Offset within executable file of start of text area data. */
+
+int text_offset;
+
+/* Offset within executable file of start of data area data. */
+
+int exec_data_offset;
+
+/* Offset within core file of start of data area data. */
+
+int data_offset;
+
+/* Offset within core file of start of stack area data. */
+
+int stack_offset;
+
+#ifdef COFF_FORMAT
+/* various coff data structures */
+
+FILHDR file_hdr;
+SCNHDR text_hdr;
+SCNHDR data_hdr;
+
+#endif /* not COFF_FORMAT */
+
+/* a.out header saved in core file. */
+
+AOUTHDR core_aouthdr;
+
+/* a.out header of exec file. */
+
+AOUTHDR exec_aouthdr;
+
+void validate_files ();
+unsigned int register_addr ();
+
+/* Call this to specify the hook for exec_file_command to call back.
+ This is called from the x-window display code. */
+
+void
+specify_exec_file_hook (hook)
+ void (*hook) ();
+{
+ exec_file_display_hook = hook;
+}
+
+/* The exec file must be closed before running an inferior.
+ If it is needed again after the inferior dies, it must
+ be reopened. */
+
+void
+close_exec_file ()
+{
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+}
+
+void
+reopen_exec_file ()
+{
+ if (execchan < 0 && execfile != 0)
+ {
+ char *filename = concat (execfile, "", "");
+ exec_file_command (filename, 0);
+ free (filename);
+ }
+}
+
+/* If we have both a core file and an exec file,
+ print a warning if they don't go together.
+ This should really check that the core file came
+ from that exec file, but I don't know how to do it. */
+
+void
+validate_files ()
+{
+ if (execfile != 0 && corefile != 0)
+ {
+ struct stat st_core;
+
+ if (fstat (corechan, &st_core) < 0)
+ /* It might be a good idea to print an error message.
+ On the other hand, if the user tries to *do* anything with
+ the core file, (s)he'll find out soon enough. */
+ return;
+
+ if (N_MAGIC (core_aouthdr) != 0
+ && bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
+ printf ("Warning: core file does not match specified executable file.\n");
+ else if (exec_mtime > st_core.st_mtime) {
+#ifdef KERNELDEBUG
+ extern int kernel_debugging;
+ if (!kernel_debugging)
+#endif
+ printf ("Warning: exec file is newer than core file.\n");
+ }
+ }
+}
+
+/* Return the name of the executable file as a string.
+ ERR nonzero means get error if there is none specified;
+ otherwise return 0 in that case. */
+
+char *
+get_exec_file (err)
+ int err;
+{
+ if (err && execfile == 0)
+ error ("No executable file specified.\n\
+Use the \"exec-file\" and \"symbol-file\" commands.");
+ return execfile;
+}
+
+int
+have_core_file_p ()
+{
+ return corefile != 0;
+}
+
+static void
+files_info ()
+{
+ char *symfile;
+ extern char *get_sym_file ();
+
+ if (execfile)
+ printf ("Executable file \"%s\".\n", execfile);
+ else
+ printf ("No executable file\n");
+ if (corefile == 0)
+ printf ("No core dump file\n");
+ else
+ printf ("Core dump file \"%s\".\n", corefile);
+
+ if (have_inferior_p ())
+ printf ("Using the running image of the program, rather than these files.\n");
+
+ symfile = get_sym_file ();
+ if (symfile != 0)
+ printf ("Symbols from \"%s\".\n", symfile);
+
+#ifdef FILES_INFO_HOOK
+ if (FILES_INFO_HOOK ())
+ return;
+#endif
+
+ if (! have_inferior_p ())
+ {
+ if (execfile)
+ {
+ printf ("Text segment in executable from 0x%x to 0x%x.\n",
+ text_start, text_end);
+ printf ("Data segment in executable from 0x%x to 0x%x.\n",
+ exec_data_start, exec_data_end);
+ if (corefile)
+ printf ("(But since we have a core file, we're using...)\n");
+ }
+ if (corefile)
+ {
+ printf ("Data segment in core file from 0x%x to 0x%x.\n",
+ data_start, data_end);
+ printf ("Stack segment in core file from 0x%x to 0x%x.\n",
+ stack_start, stack_end);
+ }
+ }
+}
+
+/* Read "memory data" from core file and/or executable file.
+ Returns zero if successful, 1 if xfer_core_file failed, errno value if
+ ptrace failed. */
+
+int
+read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ if (len == 0)
+ return 0;
+
+ if (have_inferior_p ())
+ {
+ if (remote_debugging)
+ return remote_read_inferior_memory (memaddr, myaddr, len);
+ else
+ return read_inferior_memory (memaddr, myaddr, len);
+ }
+ else
+ return xfer_core_file (memaddr, myaddr, len);
+}
+
+/* Write LEN bytes of data starting at address MYADDR
+ into debugged program memory at address MEMADDR.
+ Returns zero if successful, or an errno value if ptrace failed. */
+
+int
+write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ if (have_inferior_p ())
+ {
+ if (remote_debugging)
+ return remote_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return write_inferior_memory (memaddr, myaddr, len);
+ }
+ else
+ error ("Can write memory only when program being debugged is running.");
+}
+
+#ifndef XFER_CORE_FILE
+int (*core_file_hook)(); /* hook to handle special core files like
+ like /dev/mem and crash dumps */
+
+/* Read from the program's memory (except for inferior processes).
+ This function is misnamed, since it only reads, never writes; and
+ since it will use the core file and/or executable file as necessary.
+
+ It should be extended to write as well as read, FIXME, for patching files.
+
+ Return 0 if address could be read, 1 if not. */
+
+int
+xfer_core_file (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ register int val;
+ int xferchan;
+ char **xferfile;
+ int fileptr;
+ int returnval = 0;
+
+ if (core_file_hook)
+ return ((*core_file_hook)(memaddr, myaddr, len));
+
+ while (len > 0)
+ {
+ xferfile = 0;
+ xferchan = 0;
+
+ /* Determine which file the next bunch of addresses reside in,
+ and where in the file. Set the file's read/write pointer
+ to point at the proper place for the desired address
+ and set xferfile and xferchan for the correct file.
+
+ If desired address is nonexistent, leave them zero.
+
+ i is set to the number of bytes that can be handled
+ along with the next address.
+
+ We put the most likely tests first for efficiency. */
+
+ /* Note that if there is no core file
+ data_start and data_end are equal. */
+ if (memaddr >= data_start && memaddr < data_end)
+ {
+ i = min (len, data_end - memaddr);
+ fileptr = memaddr - data_start + data_offset;
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+ /* Note that if there is no core file
+ stack_start and stack_end are equal. */
+ else if (memaddr >= stack_start && memaddr < stack_end)
+ {
+ i = min (len, stack_end - memaddr);
+ fileptr = memaddr - stack_start + stack_offset;
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+#ifdef REG_STACK_SEGMENT
+ /* Pyramids have an extra segment in the virtual address space
+ for the (control) stack of register-window frames */
+ else if (memaddr >= reg_stack_start && memaddr < reg_stack_end)
+ {
+ i = min (len, reg_stack_end - memaddr);
+ fileptr = memaddr - reg_stack_start + reg_stack_offset;
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+#endif /* REG_STACK_SEGMENT */
+
+ else if (corechan < 0
+ && memaddr >= exec_data_start && memaddr < exec_data_end)
+ {
+ i = min (len, exec_data_end - memaddr);
+ fileptr = memaddr - exec_data_start + exec_data_offset;
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ else if (memaddr >= text_start && memaddr < text_end)
+ {
+ i = min (len, text_end - memaddr);
+ fileptr = memaddr - text_start + text_offset;
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ else if (memaddr < text_start)
+ {
+ i = min (len, text_start - memaddr);
+ }
+ else if (memaddr >= text_end
+ && memaddr < (corechan >= 0? data_start : exec_data_start))
+ {
+ i = min (len, data_start - memaddr);
+ }
+ else if (corechan >= 0
+ && memaddr >= data_end && memaddr < stack_start)
+ {
+ i = min (len, stack_start - memaddr);
+ }
+ else if (corechan < 0 && memaddr >= exec_data_end)
+ {
+ /* Since there is nothing at higher addresses than data
+ (without a core file or an inferior, there is no
+ stack, set i to do the rest of the operation now. */
+ i = len;
+ }
+#ifdef REG_STACK_SEGMENT
+ else if (memaddr >= reg_stack_end && reg_stack_end != 0)
+ {
+ i = min (len, reg_stack_start - memaddr);
+ }
+ else if (memaddr >= stack_end && memaddr < reg_stack_start)
+#else /* no REG_STACK_SEGMENT. */
+ else if (memaddr >= stack_end && stack_end != 0)
+#endif /* no REG_STACK_SEGMENT. */
+ {
+ /* Since there is nothing at higher addresses than
+ the stack, set i to do the rest of the operation now. */
+ i = len;
+ }
+ else
+ {
+ /* Address did not classify into one of the known ranges.
+ This shouldn't happen; we catch the endpoints. */
+ fatal ("Internal: Bad case logic in xfer_core_file.");
+ }
+
+ /* Now we know which file to use.
+ Set up its pointer and transfer the data. */
+ if (xferfile)
+ {
+ if (*xferfile == 0)
+ if (xferfile == &execfile)
+ error ("No program file to examine.");
+ else
+ error ("No core dump file or running program to examine.");
+ val = lseek (xferchan, fileptr, 0);
+ if (val == -1)
+ perror_with_name (*xferfile);
+ val = myread (xferchan, myaddr, i);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ }
+ /* If this address is for nonexistent memory,
+ read zeros if reading, or do nothing if writing.
+ Actually, we never right. */
+ else
+ {
+ bzero (myaddr, i);
+ returnval = 1;
+ }
+
+ memaddr += i;
+ myaddr += i;
+ len -= i;
+ }
+ return returnval;
+}
+#endif /* XFER_CORE_FILE */
+
+/* My replacement for the read system call.
+ Used like `read' but keeps going if `read' returns too soon. */
+
+int
+myread (desc, addr, len)
+ int desc;
+ char *addr;
+ int len;
+{
+ register int val;
+ int orglen = len;
+
+ while (len > 0)
+ {
+ val = read (desc, addr, len);
+ if (val < 0)
+ return val;
+ if (val == 0)
+ return orglen - len;
+ len -= val;
+ addr += val;
+ }
+ return orglen;
+}
+
+#ifdef REGISTER_U_ADDR
+
+/* Return the address in the core dump or inferior of register REGNO.
+ BLOCKEND is the address of the end of the user structure. */
+
+unsigned int
+register_addr (regno, blockend)
+ int regno;
+ int blockend;
+{
+ int addr;
+
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+#endif /* REGISTER_U_ADDR */
+
+void
+_initialize_core()
+{
+ corechan = -1;
+ execchan = -1;
+ corefile = 0;
+ execfile = 0;
+ exec_file_display_hook = 0;
+
+ text_start = 0;
+ text_end = 0;
+ data_start = 0;
+ data_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ add_com ("core-file", class_files, core_file_command,
+ "Use FILE as core dump for examining memory and registers.\n\
+No arg means have no core file.");
+ add_com ("exec-file", class_files, exec_file_command,
+ "Use FILE as program for getting contents of pure memory.\n\
+If FILE cannot be found as specified, your execution directory path\n\
+is searched for a command of that name.\n\
+No arg means have no executable file.");
+ add_info ("files", files_info, "Names of files being debugged.");
+}
+
diff --git a/gnu/usr.bin/kgdb/cplus-dem.c b/gnu/usr.bin/kgdb/cplus-dem.c
new file mode 100644
index 000000000000..8ea9c8bb55ac
--- /dev/null
+++ b/gnu/usr.bin/kgdb/cplus-dem.c
@@ -0,0 +1,996 @@
+/* Demangler for GNU C++
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ written by James Clark (jjc@jclark.uucp)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is for g++ 1.36.1 (November 6 version). It will probably
+ require changes for any other version.
+
+ Modified for g++ 1.36.2 (November 18 version). */
+
+/* This file exports one function
+
+ char *cplus_demangle (const char *name, int mode)
+
+ If NAME is a mangled function name produced by GNU C++, then
+ a pointer to a malloced string giving a C++ representation
+ of the name will be returned; otherwise NULL will be returned.
+ It is the caller's responsibility to free the string which
+ is returned.
+
+ If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
+ Otherwise they are not.
+ If MODE >= 0, parameters are emitted; otherwise not.
+
+ For example,
+
+ cplus_demangle ("foo__1Ai", 0) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", 1) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", -1) => "A::foo"
+
+ cplus_demangle ("foo__1Afe", 0) => "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", 1) => "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", -1) => "A::foo"
+
+ This file imports xmalloc and xrealloc, which are like malloc and
+ realloc except that they generate a fatal error if there is no
+ available memory. */
+
+/* #define nounderscore 1 /* define this is names don't start with _ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef USG
+#include <memory.h>
+#include <string.h>
+#else
+#include <strings.h>
+#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
+#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
+#define strchr index
+#define strrchr rindex
+#endif
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifdef __STDC__
+extern char *cplus_demangle (const char *type, int mode);
+#else
+extern char *cplus_demangle ();
+#endif
+
+#ifdef __STDC__
+extern char *xmalloc (int);
+extern char *xrealloc (char *, int);
+#else
+extern char *xmalloc ();
+extern char *xrealloc ();
+#endif
+
+static char **typevec = 0;
+static int ntypes = 0;
+static int typevec_size = 0;
+
+static struct {
+ const char *in;
+ const char *out;
+} optable[] = {
+ "new", " new",
+ "delete", " delete",
+ "ne", "!=",
+ "eq", "==",
+ "ge", ">=",
+ "gt", ">",
+ "le", "<=",
+ "lt", "<",
+ "plus", "+",
+ "minus", "-",
+ "mult", "*",
+ "convert", "+", /* unary + */
+ "negate", "-", /* unary - */
+ "trunc_mod", "%",
+ "trunc_div", "/",
+ "truth_andif", "&&",
+ "truth_orif", "||",
+ "truth_not", "!",
+ "postincrement", "++",
+ "postdecrement", "--",
+ "bit_ior", "|",
+ "bit_xor", "^",
+ "bit_and", "&",
+ "bit_not", "~",
+ "call", "()",
+ "cond", "?:",
+ "alshift", "<<",
+ "arshift", ">>",
+ "component", "->",
+ "indirect", "*",
+ "method_call", "->()",
+ "addr", "&", /* unary & */
+ "array", "[]",
+ "nop", "", /* for operator= */
+};
+
+/* Beware: these aren't '\0' terminated. */
+
+typedef struct {
+ char *b; /* pointer to start of string */
+ char *p; /* pointer after last character */
+ char *e; /* pointer after end of allocated space */
+} string;
+
+#ifdef __STDC__
+static void string_need (string *s, int n);
+static void string_delete (string *s);
+static void string_init (string *s);
+static void string_clear (string *s);
+static int string_empty (string *s);
+static void string_append (string *p, const char *s);
+static void string_appends (string *p, string *s);
+static void string_appendn (string *p, const char *s, int n);
+static void string_prepend (string *p, const char *s);
+#if 0
+static void string_prepends (string *p, string *s);
+#endif
+static void string_prependn (string *p, const char *s, int n);
+static int get_count (const char **type, int *count);
+static int do_args (const char **type, string *decl, int arg_mode);
+static int do_type (const char **type, string *result, int arg_mode);
+static int do_arg (const char **type, string *result, int arg_mode);
+static void munge_function_name (string *name, int arg_mode);
+static void remember_type (const char *type, int len);
+#else
+static void string_need ();
+static void string_delete ();
+static void string_init ();
+static void string_clear ();
+static int string_empty ();
+static void string_append ();
+static void string_appends ();
+static void string_appendn ();
+static void string_prepend ();
+static void string_prepends ();
+static void string_prependn ();
+static int get_count ();
+static int do_args ();
+static int do_type ();
+static int do_arg ();
+static int do_args ();
+static void munge_function_name ();
+static void remember_type ();
+#endif
+
+char *
+cplus_demangle (type, arg_mode)
+ const char *type;
+ int arg_mode;
+{
+ string decl;
+ int n;
+ int success = 0;
+ int constructor = 0;
+ int const_flag = 0;
+ int i;
+ const char *p;
+#ifndef LONGERNAMES
+ const char *premangle;
+#endif
+
+# define print_ansi_qualifiers (arg_mode > 0)
+# define print_arg_types (arg_mode >= 0)
+
+ if (type == NULL || *type == '\0')
+ return NULL;
+#ifndef nounderscore
+ if (*type++ != '_')
+ return NULL;
+#endif
+ p = type;
+ while (*p != '\0' && !(*p == '_' && p[1] == '_'))
+ p++;
+ if (*p == '\0')
+ {
+ /* destructor */
+ if (type[0] == '_' && type[1] == '$' && type[2] == '_')
+ {
+ int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
+ char *tem = (char *) xmalloc (n);
+ strcpy (tem, type + 3);
+ strcat (tem, "::~");
+ strcat (tem, type + 3);
+ strcat (tem, "()");
+ return tem;
+ }
+ /* static data member */
+ if (*type != '_' && (p = strchr (type, '$')) != NULL)
+ {
+ int n = strlen (type) + 2;
+ char *tem = (char *) xmalloc (n);
+ memcpy (tem, type, p - type);
+ strcpy (tem + (p - type), "::");
+ strcpy (tem + (p - type) + 2, p + 1);
+ return tem;
+ }
+ /* virtual table "_vt$" */
+ if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
+ {
+ int n = strlen (type + 4) + 14 + 1;
+ char *tem = (char *) xmalloc (n);
+ strcpy (tem, type + 4);
+ strcat (tem, " virtual table");
+ return tem;
+ }
+ return NULL;
+ }
+
+ string_init (&decl);
+
+ if (p == type)
+ {
+ if (!isdigit (p[2]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ constructor = 1;
+ }
+ else
+ {
+ string_appendn (&decl, type, p - type);
+ munge_function_name (&decl, arg_mode);
+ }
+ p += 2;
+
+#ifndef LONGERNAMES
+ premangle = p;
+#endif
+ switch (*p)
+ {
+ case 'C':
+ /* a const member function */
+ if (!isdigit (p[1]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ p += 1;
+ const_flag = 1;
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (strlen (p) < n)
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ if (constructor)
+ {
+ string_appendn (&decl, p, n);
+ string_append (&decl, "::");
+ string_appendn (&decl, p, n);
+ }
+ else
+ {
+ string_prepend (&decl, "::");
+ string_prependn (&decl, p, n);
+ }
+ p += n;
+#ifndef LONGERNAMES
+ remember_type (premangle, p - premangle);
+#endif
+ success = do_args (&p, &decl, arg_mode);
+ if (const_flag && print_arg_types)
+ string_append (&decl, " const");
+ break;
+ case 'F':
+ p += 1;
+ success = do_args (&p, &decl, arg_mode);
+ break;
+ }
+
+ for (i = 0; i < ntypes; i++)
+ if (typevec[i] != NULL)
+ free (typevec[i]);
+ ntypes = 0;
+ if (typevec != NULL)
+ {
+ free ((char *)typevec);
+ typevec = NULL;
+ typevec_size = 0;
+ }
+
+ if (success)
+ {
+ string_appendn (&decl, "", 1);
+ return decl.b;
+ }
+ else
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+}
+
+static int
+get_count (type, count)
+ const char **type;
+ int *count;
+{
+ if (!isdigit (**type))
+ return 0;
+ *count = **type - '0';
+ *type += 1;
+ /* see flush_repeats in cplus-method.c */
+ if (isdigit (**type))
+ {
+ const char *p = *type;
+ int n = *count;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (*p == '_')
+ {
+ *type = p + 1;
+ *count = n;
+ }
+ }
+ return 1;
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (type, result, arg_mode)
+ const char **type;
+ string *result;
+ int arg_mode;
+{
+ int n;
+ int done;
+ int non_empty = 0;
+ int success;
+ string decl;
+ const char *remembered_type;
+
+ string_init (&decl);
+ string_init (result);
+
+ done = 0;
+ success = 1;
+ while (success && !done)
+ {
+ int member;
+ switch (**type)
+ {
+ case 'P':
+ *type += 1;
+ string_prepend (&decl, "*");
+ break;
+
+ case 'R':
+ *type += 1;
+ string_prepend (&decl, "&");
+ break;
+
+ case 'T':
+ *type += 1;
+ if (!get_count (type, &n) || n >= ntypes)
+ success = 0;
+ else
+ {
+ remembered_type = typevec[n];
+ type = &remembered_type;
+ }
+ break;
+
+ case 'F':
+ *type += 1;
+ if (!string_empty (&decl) && decl.b[0] == '*')
+ {
+ string_prepend (&decl, "(");
+ string_append (&decl, ")");
+ }
+ if (!do_args (type, &decl, arg_mode) || **type != '_')
+ success = 0;
+ else
+ *type += 1;
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ int constp = 0;
+ int volatilep = 0;
+
+ member = **type == 'M';
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_append (&decl, ")");
+ string_prepend (&decl, "::");
+ string_prependn (&decl, *type, n);
+ string_prepend (&decl, "(");
+ *type += n;
+ if (member)
+ {
+ if (**type == 'C')
+ {
+ *type += 1;
+ constp = 1;
+ }
+ if (**type == 'V')
+ {
+ *type += 1;
+ volatilep = 1;
+ }
+ if (*(*type)++ != 'F')
+ {
+ success = 0;
+ break;
+ }
+ }
+ if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
+ {
+ success = 0;
+ break;
+ }
+ *type += 1;
+ if (! print_ansi_qualifiers)
+ break;
+ if (constp)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "const");
+ }
+ if (volatilep)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "volatile");
+ }
+ break;
+ }
+
+ case 'C':
+ if ((*type)[1] == 'P')
+ {
+ *type += 1;
+ if (print_ansi_qualifiers)
+ {
+ if (!string_empty (&decl))
+ string_prepend (&decl, " ");
+ string_prepend (&decl, "const");
+ }
+ break;
+ }
+
+ /* fall through */
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ done = 0;
+ non_empty = 0;
+ while (success && !done)
+ {
+ switch (**type)
+ {
+ case 'C':
+ *type += 1;
+ if (print_ansi_qualifiers)
+ {
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "const");
+ }
+ break;
+ case 'U':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "unsigned");
+ break;
+ case 'V':
+ *type += 1;
+ if (print_ansi_qualifiers)
+ {
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "volatile");
+ }
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ if (success)
+ switch (**type)
+ {
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "void");
+ break;
+ case 'x':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long long");
+ break;
+ case 'l':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long");
+ break;
+ case 'i':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "int");
+ break;
+ case 's':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "short");
+ break;
+ case 'c':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "char");
+ break;
+ case 'r':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long double");
+ break;
+ case 'd':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "double");
+ break;
+ case 'f':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "float");
+ break;
+ case 'G':
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ if (non_empty)
+ string_append (result, " ");
+ string_appendn (result, *type, n);
+ *type += n;
+ break;
+ default:
+ success = 0;
+ break;
+ }
+
+ if (success)
+ {
+ if (!string_empty (&decl))
+ {
+ string_append (result, " ");
+ string_appends (result, &decl);
+ }
+ string_delete (&decl);
+ return 1;
+ }
+ else
+ {
+ string_delete (&decl);
+ string_delete (result);
+ return 0;
+ }
+}
+
+/* `result' will be initialised in do_type; it will be freed on failure */
+
+static int
+do_arg (type, result, arg_mode)
+ const char **type;
+ string *result;
+ int arg_mode;
+{
+ const char *start = *type;
+
+ if (!do_type (type, result, arg_mode))
+ return 0;
+ remember_type (start, *type - start);
+ return 1;
+}
+
+static void
+remember_type (start, len)
+ const char *start;
+ int len;
+{
+ char *tem;
+
+ if (ntypes >= typevec_size)
+ {
+ if (typevec_size == 0)
+ {
+ typevec_size = 3;
+ typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
+ }
+ else
+ {
+ typevec_size *= 2;
+ typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
+ }
+ }
+ tem = (char *) xmalloc (len + 1);
+ memcpy (tem, start, len);
+ tem[len] = '\0';
+ typevec[ntypes++] = tem;
+}
+
+/* `decl' must be already initialised, usually non-empty;
+ it won't be freed on failure */
+
+static int
+do_args (type, decl, arg_mode)
+ const char **type;
+ string *decl;
+ int arg_mode;
+{
+ string arg;
+ int need_comma = 0;
+
+ if (print_arg_types)
+ string_append (decl, "(");
+
+ while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
+ {
+ if (**type == 'N')
+ {
+ int r;
+ int t;
+ *type += 1;
+ if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
+ return 0;
+ while (--r >= 0)
+ {
+ const char *tem = typevec[t];
+ if (need_comma && print_arg_types)
+ string_append (decl, ", ");
+ if (!do_arg (&tem, &arg, arg_mode))
+ return 0;
+ if (print_arg_types)
+ string_appends (decl, &arg);
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+ else
+ {
+ if (need_comma & print_arg_types)
+ string_append (decl, ", ");
+ if (!do_arg (type, &arg, arg_mode))
+ return 0;
+ if (print_arg_types)
+ string_appends (decl, &arg);
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+
+ if (**type == 'v')
+ *type += 1;
+ else if (**type == 'e')
+ {
+ *type += 1;
+ if (print_arg_types)
+ {
+ if (need_comma)
+ string_append (decl, ",");
+ string_append (decl, "...");
+ }
+ }
+
+ if (print_arg_types)
+ string_append (decl, ")");
+ return 1;
+}
+
+static void
+munge_function_name (name, arg_mode)
+ string *name;
+ int arg_mode;
+{
+ if (!string_empty (name) && name->p - name->b >= 3
+ && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
+ {
+ int i;
+ /* see if it's an assignment expression */
+ if (name->p - name->b >= 10 /* op$assign_ */
+ && memcmp (name->b + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 10;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 10, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ string_append (name, "=");
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 3;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 3, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ return;
+ }
+ }
+ }
+ return;
+ }
+ else if (!string_empty (name) && name->p - name->b >= 5
+ && memcmp (name->b, "type$", 5) == 0)
+ {
+ /* type conversion operator */
+ string type;
+ const char *tem = name->b + 5;
+ if (do_type (&tem, &type, arg_mode))
+ {
+ string_clear (name);
+ string_append (name, "operator ");
+ string_appends (name, &type);
+ string_delete (&type);
+ return;
+ }
+ }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+ string *s;
+ int n;
+{
+ if (s->b == NULL)
+ {
+ if (n < 32)
+ n = 32;
+ s->p = s->b = (char *) xmalloc (n);
+ s->e = s->b + n;
+ }
+ else if (s->e - s->p < n)
+ {
+ int tem = s->p - s->b;
+ n += tem;
+ n *= 2;
+ s->b = (char *) xrealloc (s->b, n);
+ s->p = s->b + tem;
+ s->e = s->b + n;
+ }
+}
+
+static void
+string_delete (s)
+ string *s;
+{
+ if (s->b != NULL)
+ {
+ free (s->b);
+ s->b = s->e = s->p = NULL;
+ }
+}
+
+static void
+string_init (s)
+ string *s;
+{
+ s->b = s->p = s->e = NULL;
+}
+
+static void
+string_clear (s)
+ string *s;
+{
+ s->p = s->b;
+}
+
+static int
+string_empty (s)
+ string *s;
+{
+ return s->b == s->p;
+}
+
+static void
+string_append (p, s)
+ string *p;
+ const char *s;
+{
+ int n;
+ if (s == NULL || *s == '\0')
+ return;
+ n = strlen (s);
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_appends (p, s)
+ string *p, *s;
+{
+ int n;
+ if (s->b == s->p)
+ return;
+ n = s->p - s->b;
+ string_need (p, n);
+ memcpy (p->p, s->b, n);
+ p->p += n;
+}
+
+static void
+string_appendn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ if (n == 0)
+ return;
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_prepend (p, s)
+ string *p;
+ const char *s;
+{
+ if (s == NULL || *s == '\0')
+ return;
+ string_prependn (p, s, strlen (s));
+}
+
+#if 0
+static void
+string_prepends (p, s)
+ string *p, *s;
+{
+ if (s->b == s->p)
+ return;
+ string_prependn (p, s->b, s->p - s->b);
+}
+#endif
+
+static void
+string_prependn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ char *q;
+
+ if (n == 0)
+ return;
+ string_need (p, n);
+ for (q = p->p - 1; q >= p->b; q--)
+ q[n] = q[0];
+ memcpy (p->b, s, n);
+ p->p += n;
+}
diff --git a/gnu/usr.bin/kgdb/dbxread.c b/gnu/usr.bin/kgdb/dbxread.c
new file mode 100644
index 000000000000..7a25665536a4
--- /dev/null
+++ b/gnu/usr.bin/kgdb/dbxread.c
@@ -0,0 +1,5727 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)dbxread.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Read dbx symbol tables and convert to internal format, for GDB.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Symbol read-in occurs in two phases:
+ 1. A scan (read_dbx_symtab()) of the entire executable, whose sole
+ purpose is to make a list of symbols (partial symbol table)
+ which will cause symbols
+ to be read in if referenced. This scan happens when the
+ "symbol-file" command is given (symbol_file_command()).
+ 2. Full read-in of symbols. (psymtab_to_symtab()). This happens
+ when a symbol in a file for which symbols have not yet been
+ read in is referenced.
+ 2a. The "add-file" command. Similar to #2. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+
+#ifdef READ_DBX_FORMAT
+
+#ifdef USG
+#include <sys/types.h>
+#include <fcntl.h>
+#define L_SET 0
+#define L_INCR 1
+#endif
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#include "stab.gnu.h"
+#else
+#include <a.out.h>
+#include <stab.h>
+#endif
+#include <ctype.h>
+
+#ifndef NO_GNU_STABS
+/*
+ * Define specifically gnu symbols here.
+ */
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+#ifndef N_INDR
+#define N_INDR 0xa
+#endif
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+#ifndef N_SETA
+#define N_SETA 0x14 /* Absolute set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+#ifndef N_SETT
+#define N_SETT 0x16 /* Text set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+#ifndef N_SETD
+#define N_SETD 0x18 /* Data set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+#ifndef N_SETB
+#define N_SETB 0x1A /* Bss set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+/* Macros dealing with the set element symbols defined in a.out.h */
+#define SET_ELEMENT_P(x) ((x)>=N_SETA&&(x)<=(N_SETB|N_EXT))
+#define TYPE_OF_SET_ELEMENT(x) ((x)-N_SETA+N_ABS)
+
+#ifndef N_SETV
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+#endif /* This is output from LD. */
+
+#ifndef N_WARNING
+#define N_WARNING 0x1E /* Warning message to print if file included */
+#endif /* This is input to ld */
+
+#ifndef __GNU_STAB__
+
+/* Line number for the data section. This is to be used to describe
+ the source location of a variable declaration. */
+#ifndef N_DSLINE
+#define N_DSLINE (N_SLINE+N_DATA-N_TEXT)
+#endif
+
+/* Line number for the bss section. This is to be used to describe
+ the source location of a variable declaration. */
+#ifndef N_BSLINE
+#define N_BSLINE (N_SLINE+N_BSS-N_TEXT)
+#endif
+
+#endif /* not __GNU_STAB__ */
+#endif /* NO_GNU_STABS */
+
+#include <obstack.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include "symtab.h"
+
+#ifndef COFF_FORMAT
+#ifndef AOUTHDR
+#define AOUTHDR struct exec
+#endif
+#endif
+
+static void add_symbol_to_list ();
+static void read_dbx_symtab ();
+static void process_one_symbol ();
+static void free_all_psymbols ();
+static struct type *read_type ();
+static struct type *read_range_type ();
+static struct type *read_enum_type ();
+static struct type *read_struct_type ();
+static struct type *read_array_type ();
+static long read_number ();
+static void read_huge_number ();
+static void finish_block ();
+static struct blockvector *make_blockvector ();
+static struct symbol *define_symbol ();
+static void start_subfile ();
+static int hashname ();
+static void hash_symsegs ();
+static struct pending *copy_pending ();
+static void fix_common_block ();
+
+static void add_undefined_type ();
+static void cleanup_undefined_types ();
+
+extern char *index();
+
+extern struct symtab *read_symsegs ();
+extern void free_all_symtabs ();
+extern void free_all_psymtabs ();
+extern void free_inclink_symtabs ();
+
+/* C++ */
+static struct type **read_args ();
+
+/* Macro to determine which symbols to ignore when reading the first symbol
+ of a file. Some machines override this definition. */
+#ifdef N_NSYMS
+#ifndef IGNORE_SYMBOL
+/* This code is used on Ultrix systems. Ignore it */
+#define IGNORE_SYMBOL(type) (type == N_NSYMS)
+#endif
+#else
+#ifndef IGNORE_SYMBOL
+/* Don't ignore any symbols. */
+#define IGNORE_SYMBOL(type) (0)
+#endif
+#endif /* not N_NSYMS */
+
+/* Macro for number of symbol table entries (in usual a.out format).
+ Some machines override this definition. */
+#ifndef NUMBER_OF_SYMBOLS
+#ifdef COFF_HEADER
+#define NUMBER_OF_SYMBOLS \
+ ((COFF_HEADER(hdr) ? hdr.coffhdr.filehdr.f_nsyms : hdr.a_syms) / \
+ sizeof (struct nlist))
+#else
+#define NUMBER_OF_SYMBOLS (hdr.a_syms / sizeof (struct nlist))
+#endif
+#endif
+
+/* Macro for file-offset of symbol table (in usual a.out format). */
+#ifndef SYMBOL_TABLE_OFFSET
+#define SYMBOL_TABLE_OFFSET N_SYMOFF (hdr)
+#endif
+
+/* Macro for file-offset of string table (in usual a.out format). */
+#ifndef STRING_TABLE_OFFSET
+#define STRING_TABLE_OFFSET (N_SYMOFF (hdr) + hdr.a_syms)
+#endif
+
+/* Macro to store the length of the string table data in INTO. */
+#ifndef READ_STRING_TABLE_SIZE
+#define READ_STRING_TABLE_SIZE(INTO) \
+{ val = myread (desc, &INTO, sizeof INTO); \
+ if (val < 0) perror_with_name (name); }
+#endif
+
+/* Macro to declare variables to hold the file's header data. */
+#ifndef DECLARE_FILE_HEADERS
+#define DECLARE_FILE_HEADERS AOUTHDR hdr
+#endif
+
+/* Macro to read the header data from descriptor DESC and validate it.
+ NAME is the file name, for error messages. */
+#ifndef READ_FILE_HEADERS
+#ifdef HEADER_SEEK_FD
+#define READ_FILE_HEADERS(DESC, NAME) \
+{ HEADER_SEEK_FD (DESC); \
+ val = myread (DESC, &hdr, sizeof hdr); \
+ if (val < 0) perror_with_name (NAME); \
+ if (N_BADMAG (hdr)) \
+ error ("File \"%s\" not in executable format.", NAME); }
+#else
+#define READ_FILE_HEADERS(DESC, NAME) \
+{ val = myread (DESC, &hdr, sizeof hdr); \
+ if (val < 0) perror_with_name (NAME); \
+ if (N_BADMAG (hdr)) \
+ error ("File \"%s\" not in executable format.", NAME); }
+#endif
+#endif
+
+/* Non-zero if this is an object (.o) file, rather than an executable.
+ Distinguishing between the two is rarely necessary (and seems like
+ a hack, but there is no other way to do ADDR_OF_TEXT_SEGMENT
+ right for SunOS). */
+#if !defined (IS_OBJECT_FILE)
+/* This will not work
+ if someone decides to make ld preserve relocation info. */
+#define IS_OBJECT_FILE (hdr.a_trsize != 0)
+#endif
+
+/* Macro for size of text segment */
+#ifndef SIZE_OF_TEXT_SEGMENT
+#define SIZE_OF_TEXT_SEGMENT hdr.a_text
+#endif
+
+/* Get the address in debugged memory of the start
+ of the text segment. */
+#if !defined (ADDR_OF_TEXT_SEGMENT)
+#if defined (N_TXTADDR)
+#define ADDR_OF_TEXT_SEGMENT (IS_OBJECT_FILE ? 0 : N_TXTADDR (hdr))
+#else /* no N_TXTADDR */
+#define ADDR_OF_TEXT_SEGMENT 0
+#endif /* no N_TXTADDR */
+#endif /* no ADDR_OF_TEXT_SEGMENT */
+
+/* Macro to get entry point from headers. */
+#ifndef ENTRY_POINT
+#define ENTRY_POINT hdr.a_entry
+#endif
+
+/* Macro for name of symbol to indicate a file compiled with gcc. */
+#ifndef GCC_COMPILED_FLAG_SYMBOL
+#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled."
+#endif
+
+/* Convert stab register number (from `r' declaration) to a gdb REGNUM. */
+
+#ifndef STAB_REG_TO_REGNUM
+#define STAB_REG_TO_REGNUM(VALUE) (VALUE)
+#endif
+
+/* Define this as 1 if a pcc declaration of a char or short argument
+ gives the correct address. Otherwise assume pcc gives the
+ address of the corresponding int, which is not the same on a
+ big-endian machine. */
+
+#ifndef BELIEVE_PCC_PROMOTION
+#define BELIEVE_PCC_PROMOTION 0
+#endif
+
+/* Nonzero means give verbose info on gdb action. From main.c. */
+extern int info_verbose;
+
+/* Chain of symtabs made from reading the file's symsegs.
+ These symtabs do not go into symtab_list themselves,
+ but the information is copied from them when appropriate
+ to make the symtabs that will exist permanently. */
+
+static struct symtab *symseg_chain;
+
+/* Symseg symbol table for the file whose data we are now processing.
+ It is one of those in symseg_chain. Or 0, for a compilation that
+ has no symseg. */
+
+static struct symtab *current_symseg;
+
+/* Name of source file whose symbol data we are now processing.
+ This comes from a symbol of type N_SO. */
+
+static char *last_source_file;
+
+/* Core address of start of text of current source file.
+ This too comes from the N_SO symbol. */
+
+static CORE_ADDR last_source_start_addr;
+
+/* End of the text segment of the executable file,
+ as found in the symbol _etext. */
+
+static CORE_ADDR end_of_text_addr;
+
+/* The list of sub-source-files within the current individual compilation.
+ Each file gets its own symtab with its own linetable and associated info,
+ but they all share one blockvector. */
+
+struct subfile
+{
+ struct subfile *next;
+ char *name;
+ struct linetable *line_vector;
+ int line_vector_length;
+ int line_vector_index;
+ int prev_line_number;
+};
+
+static struct subfile *subfiles;
+
+static struct subfile *current_subfile;
+
+/* Count symbols as they are processed, for error messages. */
+
+static int symnum;
+
+/* Vector of types defined so far, indexed by their dbx type numbers.
+ (In newer sun systems, dbx uses a pair of numbers in parens,
+ as in "(SUBFILENUM,NUMWITHINSUBFILE)". Then these numbers must be
+ translated through the type_translations hash table to get
+ the index into the type vector.) */
+
+static struct typevector *type_vector;
+
+/* Number of elements allocated for type_vector currently. */
+
+static int type_vector_length;
+
+/* Vector of line number information. */
+
+static struct linetable *line_vector;
+
+/* Index of next entry to go in line_vector_index. */
+
+static int line_vector_index;
+
+/* Last line number recorded in the line vector. */
+
+static int prev_line_number;
+
+/* Number of elements allocated for line_vector currently. */
+
+static int line_vector_length;
+
+/* Hash table of global symbols whose values are not known yet.
+ They are chained thru the SYMBOL_VALUE, since we don't
+ have the correct data for that slot yet. */
+/* The use of the LOC_BLOCK code in this chain is nonstandard--
+ it refers to a FORTRAN common block rather than the usual meaning. */
+
+#define HASHSIZE 127
+static struct symbol *global_sym_chain[HASHSIZE];
+
+/* Record the symbols defined for each context in a list.
+ We don't create a struct block for the context until we
+ know how long to make it. */
+
+#define PENDINGSIZE 100
+
+struct pending
+{
+ struct pending *next;
+ int nsyms;
+ struct symbol *symbol[PENDINGSIZE];
+};
+
+/* List of free `struct pending' structures for reuse. */
+struct pending *free_pendings;
+
+/* Here are the three lists that symbols are put on. */
+
+struct pending *file_symbols; /* static at top level, and types */
+
+struct pending *global_symbols; /* global functions and variables */
+
+struct pending *local_symbols; /* everything local to lexical context */
+
+/* List of symbols declared since the last BCOMM. This list is a tail
+ of local_symbols. When ECOMM is seen, the symbols on the list
+ are noted so their proper addresses can be filled in later,
+ using the common block base address gotten from the assembler
+ stabs. */
+
+struct pending *common_block;
+int common_block_i;
+
+/* Stack representing unclosed lexical contexts
+ (that will become blocks, eventually). */
+
+struct context_stack
+{
+ struct pending *locals;
+ struct pending_block *old_blocks;
+ struct symbol *name;
+ CORE_ADDR start_addr;
+ int depth;
+};
+
+struct context_stack *context_stack;
+
+/* Index of first unused entry in context stack. */
+int context_stack_depth;
+
+/* Currently allocated size of context stack. */
+
+int context_stack_size;
+
+/* Nonzero if within a function (so symbols should be local,
+ if nothing says specifically). */
+
+int within_function;
+
+/* List of blocks already made (lexical contexts already closed).
+ This is used at the end to make the blockvector. */
+
+struct pending_block
+{
+ struct pending_block *next;
+ struct block *block;
+};
+
+struct pending_block *pending_blocks;
+
+extern CORE_ADDR startup_file_start; /* From blockframe.c */
+extern CORE_ADDR startup_file_end; /* From blockframe.c */
+
+/* File name symbols were loaded from. */
+
+static char *symfile;
+
+/* Low and high symbol values (inclusive) for the global variable
+ entries in the symbol file. */
+
+static int first_global_sym, last_global_sym;
+
+/* Structures with which to manage partial symbol allocation. */
+
+struct psymbol_allocation_list global_psymbols, static_psymbols;
+
+/* Global variable which, when set, indicates that we are processing a
+ .o file compiled with gcc */
+
+static unsigned char processing_gcc_compilation;
+
+/* Make a list of forward references which haven't been defined. */
+static struct type **undef_types;
+static int undef_types_allocated, undef_types_length;
+
+ /* Setup a define to deal cleanly with the underscore problem */
+
+#ifdef NAMES_HAVE_UNDERSCORE
+#define HASH_OFFSET 1
+#else
+#define HASH_OFFSET 0
+#endif
+
+#if 0
+/* I'm not sure why this is here. To debug bugs which cause
+ an infinite loop of allocations, I suppose. In any event,
+ dumping core when out of memory isn't usually right. */
+static int
+xxmalloc (n)
+{
+ int v = malloc (n);
+ if (v == 0)
+ {
+ fprintf (stderr, "Virtual memory exhausted.\n");
+ abort ();
+ }
+ return v;
+}
+#else /* not 0 */
+#define xxmalloc xmalloc
+#endif /* not 0 */
+
+/* Make a copy of the string at PTR with SIZE characters in the symbol obstack
+ (and add a null character at the end in the copy).
+ Returns the address of the copy. */
+
+static char *
+obsavestring (ptr, size)
+ char *ptr;
+ int size;
+{
+ register char *p = (char *) obstack_alloc (symbol_obstack, size + 1);
+ /* Open-coded bcopy--saves function call time.
+ These strings are usually short. */
+ {
+ register char *p1 = ptr;
+ register char *p2 = p;
+ char *end = ptr + size;
+ while (p1 != end)
+ *p2++ = *p1++;
+ }
+ p[size] = 0;
+ return p;
+}
+
+/* Concatenate strings S1, S2 and S3; return the new string.
+ Space is found in the symbol_obstack. */
+
+static char *
+obconcat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+ register char *val = (char *) obstack_alloc (symbol_obstack, len);
+ strcpy (val, s1);
+ strcat (val, s2);
+ strcat (val, s3);
+ return val;
+}
+
+/* Support for Sun changes to dbx symbol format */
+
+/* For each identified header file, we have a table of types defined
+ in that header file.
+
+ header_files maps header file names to their type tables.
+ It is a vector of n_header_files elements.
+ Each element describes one header file.
+ It contains a vector of types.
+
+ Sometimes it can happen that the same header file produces
+ different results when included in different places.
+ This can result from conditionals or from different
+ things done before including the file.
+ When this happens, there are multiple entries for the file in this table,
+ one entry for each distinct set of results.
+ The entries are distinguished by the INSTANCE field.
+ The INSTANCE field appears in the N_BINCL and N_EXCL symbol table and is
+ used to match header-file references to their corresponding data. */
+
+struct header_file
+{
+ char *name; /* Name of header file */
+ int instance; /* Numeric code distinguishing instances
+ of one header file that produced
+ different results when included.
+ It comes from the N_BINCL or N_EXCL. */
+ struct type **vector; /* Pointer to vector of types */
+ int length; /* Allocated length (# elts) of that vector */
+};
+
+static struct header_file *header_files;
+
+static int n_header_files;
+
+static int n_allocated_header_files;
+
+/* During initial symbol readin, we need to have a structure to keep
+ track of which psymtabs have which bincls in them. This structure
+ is used during readin to setup the list of dependencies within each
+ partial symbol table. */
+
+struct header_file_location
+{
+ char *name; /* Name of header file */
+ int instance; /* See above */
+ struct partial_symtab *pst; /* Partial symtab that has the
+ BINCL/EINCL defs for this file */
+};
+
+/* The actual list and controling variables */
+static struct header_file_location *bincl_list, *next_bincl;
+static int bincls_allocated;
+
+/* Within each object file, various header files are assigned numbers.
+ A type is defined or referred to with a pair of numbers
+ (FILENUM,TYPENUM) where FILENUM is the number of the header file
+ and TYPENUM is the number within that header file.
+ TYPENUM is the index within the vector of types for that header file.
+
+ FILENUM == 1 is special; it refers to the main source of the object file,
+ and not to any header file. FILENUM != 1 is interpreted by looking it up
+ in the following table, which contains indices in header_files. */
+
+static int *this_object_header_files;
+
+static int n_this_object_header_files;
+
+static int n_allocated_this_object_header_files;
+
+/* When a header file is getting special overriding definitions
+ for one source file, record here the header_files index
+ of its normal definition vector.
+ At other times, this is -1. */
+
+static int header_file_prev_index;
+
+/* At the start of reading dbx symbols, allocate our tables. */
+
+static void
+init_header_files ()
+{
+ n_allocated_header_files = 10;
+ header_files = (struct header_file *) xxmalloc (10 * sizeof (struct header_file));
+ n_header_files = 0;
+
+ n_allocated_this_object_header_files = 10;
+ this_object_header_files = (int *) xxmalloc (10 * sizeof (int));
+}
+
+/* At the end of reading dbx symbols, free our tables. */
+
+static void
+free_header_files ()
+{
+ register int i;
+ for (i = 0; i < n_header_files; i++)
+ free (header_files[i].name);
+ if (header_files) free (header_files);
+ if (this_object_header_files)
+ free (this_object_header_files);
+}
+
+/* Called at the start of each object file's symbols.
+ Clear out the mapping of header file numbers to header files. */
+
+static void
+new_object_header_files ()
+{
+ /* Leave FILENUM of 0 free for builtin types and this file's types. */
+ n_this_object_header_files = 1;
+ header_file_prev_index = -1;
+}
+
+/* Add header file number I for this object file
+ at the next successive FILENUM. */
+
+static void
+add_this_object_header_file (i)
+ int i;
+{
+ if (n_this_object_header_files == n_allocated_this_object_header_files)
+ {
+ n_allocated_this_object_header_files *= 2;
+ this_object_header_files
+ = (int *) xrealloc (this_object_header_files,
+ n_allocated_this_object_header_files * sizeof (int));
+ }
+
+ this_object_header_files[n_this_object_header_files++] = i;
+}
+
+/* Add to this file an "old" header file, one already seen in
+ a previous object file. NAME is the header file's name.
+ INSTANCE is its instance code, to select among multiple
+ symbol tables for the same header file. */
+
+static void
+add_old_header_file (name, instance)
+ char *name;
+ int instance;
+{
+ register struct header_file *p = header_files;
+ register int i;
+
+ for (i = 0; i < n_header_files; i++)
+ if (!strcmp (p[i].name, name) && instance == p[i].instance)
+ {
+ add_this_object_header_file (i);
+ return;
+ }
+ error ("Invalid symbol data: \"repeated\" header file that hasn't been seen before, at symtab pos %d.",
+ symnum);
+}
+
+/* Add to this file a "new" header file: definitions for its types follow.
+ NAME is the header file's name.
+ Most often this happens only once for each distinct header file,
+ but not necessarily. If it happens more than once, INSTANCE has
+ a different value each time, and references to the header file
+ use INSTANCE values to select among them.
+
+ dbx output contains "begin" and "end" markers for each new header file,
+ but at this level we just need to know which files there have been;
+ so we record the file when its "begin" is seen and ignore the "end". */
+
+static void
+add_new_header_file (name, instance)
+ char *name;
+ int instance;
+{
+ register int i;
+ register struct header_file *p = header_files;
+ header_file_prev_index = -1;
+
+#if 0
+ /* This code was used before I knew about the instance codes.
+ My first hypothesis is that it is not necessary now
+ that instance codes are handled. */
+
+ /* Has this header file a previous definition?
+ If so, make a new entry anyway so that this use in this source file
+ gets a separate entry. Later source files get the old entry.
+ Record here the index of the old entry, so that any type indices
+ not previously defined can get defined in the old entry as
+ well as in the new one. */
+
+ for (i = 0; i < n_header_files; i++)
+ if (!strcmp (p[i].name, name))
+ {
+ header_file_prev_index = i;
+ }
+
+#endif
+
+ /* Make sure there is room for one more header file. */
+
+ if (n_header_files == n_allocated_header_files)
+ {
+ n_allocated_header_files *= 2;
+ header_files = (struct header_file *)
+ xrealloc (header_files,
+ (n_allocated_header_files
+ * sizeof (struct header_file)));
+ }
+
+ /* Create an entry for this header file. */
+
+ i = n_header_files++;
+ header_files[i].name = savestring (name, strlen(name));
+ header_files[i].instance = instance;
+ header_files[i].length = 10;
+ header_files[i].vector
+ = (struct type **) xxmalloc (10 * sizeof (struct type *));
+ bzero (header_files[i].vector, 10 * sizeof (struct type *));
+
+ add_this_object_header_file (i);
+}
+
+/* Look up a dbx type-number pair. Return the address of the slot
+ where the type for that number-pair is stored.
+ The number-pair is in TYPENUMS.
+
+ This can be used for finding the type associated with that pair
+ or for associating a new type with the pair. */
+
+static struct type **
+dbx_lookup_type (typenums)
+ int typenums[2];
+{
+ register int filenum = typenums[0], index = typenums[1];
+
+ if (filenum < 0 || filenum >= n_this_object_header_files)
+ error ("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.",
+ filenum, index, symnum);
+
+ if (filenum == 0)
+ {
+ /* Type is defined outside of header files.
+ Find it in this object file's type vector. */
+ if (index >= type_vector_length)
+ {
+ type_vector_length *= 2;
+ type_vector = (struct typevector *)
+ xrealloc (type_vector,
+ (sizeof (struct typevector)
+ + type_vector_length * sizeof (struct type *)));
+ bzero (&type_vector->type[type_vector_length / 2],
+ type_vector_length * sizeof (struct type *) / 2);
+ }
+ return &type_vector->type[index];
+ }
+ else
+ {
+ register int real_filenum = this_object_header_files[filenum];
+ register struct header_file *f;
+
+ if (real_filenum >= n_header_files)
+ abort ();
+
+ f = &header_files[real_filenum];
+
+ if (index >= f->length)
+ {
+ f->length *= 2;
+ f->vector = (struct type **)
+ xrealloc (f->vector, f->length * sizeof (struct type *));
+ bzero (&f->vector[f->length / 2],
+ f->length * sizeof (struct type *) / 2);
+ }
+ return &f->vector[index];
+ }
+}
+
+/* Create a type object. Occaisionally used when you need a type
+ which isn't going to be given a type number. */
+
+static struct type *
+dbx_create_type ()
+{
+ register struct type *type =
+ (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type));
+
+ bzero (type, sizeof (struct type));
+ TYPE_VPTR_FIELDNO (type) = -1;
+ return type;
+}
+
+/* Make sure there is a type allocated for type numbers TYPENUMS
+ and return the type object.
+ This can create an empty (zeroed) type object.
+ TYPENUMS may be (-1, -1) to return a new type object that is not
+ put into the type vector, and so may not be referred to by number. */
+
+static struct type *
+dbx_alloc_type (typenums)
+ int typenums[2];
+{
+ register struct type **type_addr;
+ register struct type *type;
+
+ if (typenums[1] != -1)
+ {
+ type_addr = dbx_lookup_type (typenums);
+ type = *type_addr;
+ }
+ else
+ {
+ type_addr = 0;
+ type = 0;
+ }
+
+ /* If we are referring to a type not known at all yet,
+ allocate an empty type for it.
+ We will fill it in later if we find out how. */
+ if (type == 0)
+ {
+ type = dbx_create_type ();
+ if (type_addr)
+ *type_addr = type;
+ }
+
+ return type;
+}
+
+#if 0
+static struct type **
+explicit_lookup_type (real_filenum, index)
+ int real_filenum, index;
+{
+ register struct header_file *f = &header_files[real_filenum];
+
+ if (index >= f->length)
+ {
+ f->length *= 2;
+ f->vector = (struct type **)
+ xrealloc (f->vector, f->length * sizeof (struct type *));
+ bzero (&f->vector[f->length / 2],
+ f->length * sizeof (struct type *) / 2);
+ }
+ return &f->vector[index];
+}
+#endif
+
+/* maintain the lists of symbols and blocks */
+
+/* Add a symbol to one of the lists of symbols. */
+static void
+add_symbol_to_list (symbol, listhead)
+ struct symbol *symbol;
+ struct pending **listhead;
+{
+ /* We keep PENDINGSIZE symbols in each link of the list.
+ If we don't have a link with room in it, add a new link. */
+ if (*listhead == 0 || (*listhead)->nsyms == PENDINGSIZE)
+ {
+ register struct pending *link;
+ if (free_pendings)
+ {
+ link = free_pendings;
+ free_pendings = link->next;
+ }
+ else
+ link = (struct pending *) xxmalloc (sizeof (struct pending));
+
+ link->next = *listhead;
+ *listhead = link;
+ link->nsyms = 0;
+ }
+
+ (*listhead)->symbol[(*listhead)->nsyms++] = symbol;
+}
+
+/* At end of reading syms, or in case of quit,
+ really free as many `struct pending's as we can easily find. */
+
+static void
+really_free_pendings ()
+{
+ struct pending *next, *next1;
+ struct pending_block *bnext, *bnext1;
+
+ for (next = free_pendings; next; next = next1)
+ {
+ next1 = next->next;
+ free (next);
+ }
+ free_pendings = 0;
+
+ for (bnext = pending_blocks; bnext; bnext = bnext1)
+ {
+ bnext1 = bnext->next;
+ free (bnext);
+ }
+ pending_blocks = 0;
+
+ for (next = file_symbols; next; next = next1)
+ {
+ next1 = next->next;
+ free (next);
+ }
+ for (next = global_symbols; next; next = next1)
+ {
+ next1 = next->next;
+ free (next);
+ }
+}
+
+/* Take one of the lists of symbols and make a block from it.
+ Keep the order the symbols have in the list (reversed from the input file).
+ Put the block on the list of pending blocks. */
+
+static void
+finish_block (symbol, listhead, old_blocks, start, end)
+ struct symbol *symbol;
+ struct pending **listhead;
+ struct pending_block *old_blocks;
+ CORE_ADDR start, end;
+{
+ register struct pending *next, *next1;
+ register struct block *block;
+ register struct pending_block *pblock;
+ struct pending_block *opblock;
+ register int i;
+
+ /* Count the length of the list of symbols. */
+
+ for (next = *listhead, i = 0; next; i += next->nsyms, next = next->next);
+
+ block = (struct block *) obstack_alloc (symbol_obstack,
+ (sizeof (struct block)
+ + ((i - 1)
+ * sizeof (struct symbol *))));
+
+ /* Copy the symbols into the block. */
+
+ BLOCK_NSYMS (block) = i;
+ for (next = *listhead; next; next = next->next)
+ {
+ register int j;
+ for (j = next->nsyms - 1; j >= 0; j--)
+ BLOCK_SYM (block, --i) = next->symbol[j];
+ }
+
+ BLOCK_START (block) = start;
+ BLOCK_END (block) = end;
+ BLOCK_SUPERBLOCK (block) = 0; /* Filled in when containing block is made */
+ BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
+
+ /* Put the block in as the value of the symbol that names it. */
+
+ if (symbol)
+ {
+ SYMBOL_BLOCK_VALUE (symbol) = block;
+ BLOCK_FUNCTION (block) = symbol;
+ }
+ else
+ BLOCK_FUNCTION (block) = 0;
+
+ /* Now "free" the links of the list, and empty the list. */
+
+ for (next = *listhead; next; next = next1)
+ {
+ next1 = next->next;
+ next->next = free_pendings;
+ free_pendings = next;
+ }
+ *listhead = 0;
+
+ /* Install this block as the superblock
+ of all blocks made since the start of this scope
+ that don't have superblocks yet. */
+
+ opblock = 0;
+ for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next)
+ {
+ if (BLOCK_SUPERBLOCK (pblock->block) == 0)
+ BLOCK_SUPERBLOCK (pblock->block) = block;
+ opblock = pblock;
+ }
+
+ /* Record this block on the list of all blocks in the file.
+ Put it after opblock, or at the beginning if opblock is 0.
+ This puts the block in the list after all its subblocks. */
+
+ /* Allocate in the symbol_obstack to save time.
+ It wastes a little space. */
+ pblock = (struct pending_block *)
+ obstack_alloc (symbol_obstack,
+ sizeof (struct pending_block));
+ pblock->block = block;
+ if (opblock)
+ {
+ pblock->next = opblock->next;
+ opblock->next = pblock;
+ }
+ else
+ {
+ pblock->next = pending_blocks;
+ pending_blocks = pblock;
+ }
+}
+
+static struct blockvector *
+make_blockvector ()
+{
+ register struct pending_block *next, *next1;
+ register struct blockvector *blockvector;
+ register int i;
+
+ /* Count the length of the list of blocks. */
+
+ for (next = pending_blocks, i = 0; next; next = next->next, i++);
+
+ blockvector = (struct blockvector *)
+ obstack_alloc (symbol_obstack,
+ (sizeof (struct blockvector)
+ + (i - 1) * sizeof (struct block *)));
+
+ /* Copy the blocks into the blockvector.
+ This is done in reverse order, which happens to put
+ the blocks into the proper order (ascending starting address).
+ finish_block has hair to insert each block into the list
+ after its subblocks in order to make sure this is true. */
+
+ BLOCKVECTOR_NBLOCKS (blockvector) = i;
+ for (next = pending_blocks; next; next = next->next)
+ BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
+
+#if 0 /* Now we make the links in the obstack, so don't free them. */
+ /* Now free the links of the list, and empty the list. */
+
+ for (next = pending_blocks; next; next = next1)
+ {
+ next1 = next->next;
+ free (next);
+ }
+#endif
+ pending_blocks = 0;
+
+ return blockvector;
+}
+
+/* Manage the vector of line numbers. */
+
+static void
+record_line (line, pc)
+ int line;
+ CORE_ADDR pc;
+{
+ struct linetable_entry *e;
+ /* Ignore the dummy line number in libg.o */
+
+ if (line == 0xffff)
+ return;
+
+ /* Make sure line vector is big enough. */
+
+ if (line_vector_index + 1 >= line_vector_length)
+ {
+ line_vector_length *= 2;
+ line_vector = (struct linetable *)
+ xrealloc (line_vector,
+ (sizeof (struct linetable)
+ + line_vector_length * sizeof (struct linetable_entry)));
+ current_subfile->line_vector = line_vector;
+ }
+
+ e = line_vector->item + line_vector_index++;
+ e->line = line; e->pc = pc;
+}
+
+/* Start a new symtab for a new source file.
+ This is called when a dbx symbol of type N_SO is seen;
+ it indicates the start of data for one original source file. */
+
+static void
+start_symtab (name, start_addr)
+ char *name;
+ CORE_ADDR start_addr;
+{
+ register struct symtab *s;
+
+ last_source_file = name;
+ last_source_start_addr = start_addr;
+ file_symbols = 0;
+ global_symbols = 0;
+ within_function = 0;
+
+ /* Context stack is initially empty, with room for 10 levels. */
+ context_stack
+ = (struct context_stack *) xxmalloc (10 * sizeof (struct context_stack));
+ context_stack_size = 10;
+ context_stack_depth = 0;
+
+ new_object_header_files ();
+
+ for (s = symseg_chain; s; s = s->next)
+ if (s->ldsymoff == symnum * sizeof (struct nlist))
+ break;
+ current_symseg = s;
+ if (s != 0)
+ return;
+
+ type_vector_length = 160;
+ type_vector = (struct typevector *)
+ xxmalloc (sizeof (struct typevector)
+ + type_vector_length * sizeof (struct type *));
+ bzero (type_vector->type, type_vector_length * sizeof (struct type *));
+
+ /* Initialize the list of sub source files with one entry
+ for this file (the top-level source file). */
+
+ subfiles = 0;
+ current_subfile = 0;
+ start_subfile (name);
+
+#if 0 /* This is now set at the beginning of read_ofile_symtab */
+ /* Set default for compiler to pcc; assume that we aren't processing
+ a gcc compiled file until proved otherwise. */
+
+ processing_gcc_compilation = 0;
+#endif
+}
+
+/* Handle an N_SOL symbol, which indicates the start of
+ code that came from an included (or otherwise merged-in)
+ source file with a different name. */
+
+static void
+start_subfile (name)
+ char *name;
+{
+ register struct subfile *subfile;
+
+ /* Save the current subfile's line vector data. */
+
+ if (current_subfile)
+ {
+ current_subfile->line_vector_index = line_vector_index;
+ current_subfile->line_vector_length = line_vector_length;
+ current_subfile->prev_line_number = prev_line_number;
+ }
+
+ /* See if this subfile is already known as a subfile of the
+ current main source file. */
+
+ for (subfile = subfiles; subfile; subfile = subfile->next)
+ {
+ if (!strcmp (subfile->name, name))
+ {
+ line_vector = subfile->line_vector;
+ line_vector_index = subfile->line_vector_index;
+ line_vector_length = subfile->line_vector_length;
+ prev_line_number = subfile->prev_line_number;
+ current_subfile = subfile;
+ return;
+ }
+ }
+
+ /* This subfile is not known. Add an entry for it. */
+
+ line_vector_index = 0;
+ line_vector_length = 1000;
+ prev_line_number = -2; /* Force first line number to be explicit */
+ line_vector = (struct linetable *)
+ xxmalloc (sizeof (struct linetable)
+ + line_vector_length * sizeof (struct linetable_entry));
+
+ /* Make an entry for this subfile in the list of all subfiles
+ of the current main source file. */
+
+ subfile = (struct subfile *) xxmalloc (sizeof (struct subfile));
+ subfile->next = subfiles;
+ subfile->name = savestring (name, strlen (name));
+ subfile->line_vector = line_vector;
+ subfiles = subfile;
+ current_subfile = subfile;
+}
+
+/* Finish the symbol definitions for one main source file,
+ close off all the lexical contexts for that file
+ (creating struct block's for them), then make the struct symtab
+ for that file and put it in the list of all such.
+
+ END_ADDR is the address of the end of the file's text. */
+
+static void
+end_symtab (end_addr)
+ CORE_ADDR end_addr;
+{
+ register struct symtab *symtab;
+ register struct blockvector *blockvector;
+ register struct subfile *subfile;
+ register struct linetable *lv;
+ struct subfile *nextsub;
+
+ if (current_symseg != 0)
+ {
+ last_source_file = 0;
+ current_symseg = 0;
+ return;
+ }
+
+ /* Finish the lexical context of the last function in the file;
+ pop the context stack. */
+
+ if (context_stack_depth > 0)
+ {
+ register struct context_stack *cstk;
+ context_stack_depth--;
+ cstk = &context_stack[context_stack_depth];
+ /* Make a block for the local symbols within. */
+ finish_block (cstk->name, &local_symbols, cstk->old_blocks,
+ cstk->start_addr, end_addr);
+ }
+
+ /* Cleanup any undefined types that have been left hanging around
+ (this needs to be done before the finish_blocks so that
+ file_symbols is still good). */
+ cleanup_undefined_types ();
+
+ /* Finish defining all the blocks of this symtab. */
+ finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr);
+ finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr);
+ blockvector = make_blockvector ();
+
+ current_subfile->line_vector_index = line_vector_index;
+
+ /* Now create the symtab objects proper, one for each subfile. */
+ /* (The main file is one of them.) */
+
+ for (subfile = subfiles; subfile; subfile = nextsub)
+ {
+ symtab = (struct symtab *) xxmalloc (sizeof (struct symtab));
+ symtab->free_ptr = 0;
+
+ /* Fill in its components. */
+ symtab->blockvector = blockvector;
+ type_vector->length = type_vector_length;
+ symtab->typevector = type_vector;
+ symtab->free_code = free_linetable;
+ if (subfile->next == 0)
+ symtab->free_ptr = (char *) type_vector;
+
+ symtab->filename = subfile->name;
+ lv = subfile->line_vector;
+ lv->nitems = subfile->line_vector_index;
+ symtab->linetable = (struct linetable *)
+ xrealloc (lv, (sizeof (struct linetable)
+ + lv->nitems * sizeof (struct linetable_entry)));
+ symtab->nlines = 0;
+ symtab->line_charpos = 0;
+
+ /* Link the new symtab into the list of such. */
+ symtab->next = symtab_list;
+ symtab_list = symtab;
+
+ nextsub = subfile->next;
+ free (subfile);
+ }
+
+ type_vector = 0;
+ type_vector_length = -1;
+ line_vector = 0;
+ line_vector_length = -1;
+ last_source_file = 0;
+}
+
+#ifdef N_BINCL
+
+/* Handle the N_BINCL and N_EINCL symbol types
+ that act like N_SOL for switching source files
+ (different subfiles, as we call them) within one object file,
+ but using a stack rather than in an arbitrary order. */
+
+struct subfile_stack
+{
+ struct subfile_stack *next;
+ char *name;
+ int prev_index;
+};
+
+struct subfile_stack *subfile_stack;
+
+static void
+push_subfile ()
+{
+ register struct subfile_stack *tem
+ = (struct subfile_stack *) xxmalloc (sizeof (struct subfile_stack));
+
+ tem->next = subfile_stack;
+ subfile_stack = tem;
+ if (current_subfile == 0 || current_subfile->name == 0)
+ abort ();
+ tem->name = current_subfile->name;
+ tem->prev_index = header_file_prev_index;
+}
+
+static char *
+pop_subfile ()
+{
+ register char *name;
+ register struct subfile_stack *link = subfile_stack;
+
+ if (link == 0)
+ abort ();
+
+ name = link->name;
+ subfile_stack = link->next;
+ header_file_prev_index = link->prev_index;
+ free (link);
+
+ return name;
+}
+#endif /* Have N_BINCL */
+
+/* Accumulate the misc functions in bunches of 127.
+ At the end, copy them all into one newly allocated structure. */
+
+#define MISC_BUNCH_SIZE 127
+
+struct misc_bunch
+{
+ struct misc_bunch *next;
+ struct misc_function contents[MISC_BUNCH_SIZE];
+};
+
+/* Bunch currently being filled up.
+ The next field points to chain of filled bunches. */
+
+static struct misc_bunch *misc_bunch;
+
+/* Number of slots filled in current bunch. */
+
+static int misc_bunch_index;
+
+/* Total number of misc functions recorded so far. */
+
+static int misc_count;
+
+static void
+init_misc_functions ()
+{
+ misc_count = 0;
+ misc_bunch = 0;
+ misc_bunch_index = MISC_BUNCH_SIZE;
+}
+
+static void
+record_misc_function (name, address, type)
+ char *name;
+ CORE_ADDR address;
+ int type;
+{
+ register struct misc_bunch *new;
+ register unsigned char mtype;
+
+ if (misc_bunch_index == MISC_BUNCH_SIZE)
+ {
+ new = (struct misc_bunch *) xxmalloc (sizeof (struct misc_bunch));
+ misc_bunch_index = 0;
+ new->next = misc_bunch;
+ misc_bunch = new;
+ }
+ misc_bunch->contents[misc_bunch_index].name = name;
+ misc_bunch->contents[misc_bunch_index].address = address;
+ switch (type &~ N_EXT)
+ {
+ case N_TEXT: mtype = mf_text; break;
+ case N_DATA: mtype = mf_data; break;
+ case N_BSS: mtype = mf_bss; break;
+ case N_ABS: mtype = mf_abs; break;
+#ifdef N_SETV
+ case N_SETV: mtype = mf_data; break;
+#endif
+ default: mtype = mf_unknown; break;
+ }
+ misc_bunch->contents[misc_bunch_index].type = mtype;
+ misc_bunch_index++;
+ misc_count++;
+}
+
+static int
+compare_misc_functions (fn1, fn2)
+ struct misc_function *fn1, *fn2;
+{
+ /* Return a signed result based on unsigned comparisons
+ so that we sort into unsigned numeric order. */
+ if (fn1->address < fn2->address)
+ return -1;
+ if (fn1->address > fn2->address)
+ return 1;
+ return 0;
+}
+
+static void
+discard_misc_bunches ()
+{
+ register struct misc_bunch *next;
+
+ while (misc_bunch)
+ {
+ next = misc_bunch->next;
+ free (misc_bunch);
+ misc_bunch = next;
+ }
+}
+
+/* INCLINK nonzero means bunches are from an incrementally-linked file.
+ Add them to the existing bunches.
+ Otherwise INCLINK is zero, and we start from scratch. */
+static void
+condense_misc_bunches (inclink)
+ int inclink;
+{
+ register int i, j;
+ register struct misc_bunch *bunch;
+#ifdef NAMES_HAVE_UNDERSCORE
+ int offset = 1;
+#else
+ int offset = 0;
+#endif
+
+ if (inclink)
+ {
+ misc_function_vector
+ = (struct misc_function *)
+ xrealloc (misc_function_vector, (misc_count + misc_function_count)
+ * sizeof (struct misc_function));
+ j = misc_function_count;
+ }
+ else
+ {
+ misc_function_vector
+ = (struct misc_function *)
+ xxmalloc (misc_count * sizeof (struct misc_function));
+ j = 0;
+ }
+
+ bunch = misc_bunch;
+ while (bunch)
+ {
+ for (i = 0; i < misc_bunch_index; i++)
+ {
+ misc_function_vector[j] = bunch->contents[i];
+ misc_function_vector[j].name
+ = obconcat (misc_function_vector[j].name
+ + (misc_function_vector[j].name[0] == '_' ? offset : 0),
+ "", "");
+ j++;
+ }
+ bunch = bunch->next;
+ misc_bunch_index = MISC_BUNCH_SIZE;
+ }
+
+ if (inclink)
+ misc_function_count += misc_count;
+ else
+ misc_function_count = j;
+
+ /* Sort the misc functions by address. */
+
+ qsort (misc_function_vector, misc_function_count,
+ sizeof (struct misc_function),
+ compare_misc_functions);
+
+ /* (re)build the hash table (positions changed during the sort) */
+
+ for (i = 0; i < MISC_FUNC_HASH_SIZE; ++i)
+ misc_function_hash_tab[i] = -1;
+ for (i = 0; i < misc_function_count; ++i)
+ {
+ j = hash_symbol(misc_function_vector[i].name) & (MISC_FUNC_HASH_SIZE - 1);
+ misc_function_vector[i].next = misc_function_hash_tab[j];
+ misc_function_hash_tab[j] = i;
+ }
+}
+
+/* Call sort_syms to sort alphabetically
+ the symbols of each block of each symtab. */
+
+static int
+compare_symbols (s1, s2)
+ struct symbol **s1, **s2;
+{
+ register int namediff;
+
+ /* Compare the initial characters. */
+ namediff = SYMBOL_NAME (*s1)[0] - SYMBOL_NAME (*s2)[0];
+ if (namediff != 0) return namediff;
+
+ /* If they match, compare the rest of the names. */
+ namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2));
+ if (namediff != 0) return namediff;
+
+ /* For symbols of the same name, registers should come first. */
+ return ((SYMBOL_CLASS (*s2) == LOC_REGISTER)
+ - (SYMBOL_CLASS (*s1) == LOC_REGISTER));
+}
+
+static void sort_symtab_syms ();
+
+static void
+sort_syms ()
+{
+ register struct symtab *s;
+
+ for (s = symtab_list; s; s = s->next)
+ sort_symtab_syms (s);
+}
+
+static void
+sort_symtab_syms (s)
+ register struct symtab *s;
+{
+ register struct blockvector *bv = BLOCKVECTOR (s);
+ int nbl = BLOCKVECTOR_NBLOCKS (bv);
+ int i;
+ register struct block *b;
+
+ /* Note that in the following sort, we always make sure that
+ register debug symbol declarations always come before regular
+ debug symbol declarations (as might happen when parameters are
+ then put into registers by the compiler). We do this by a
+ correct compare in compare_symbols, and by the reversal of the
+ symbols if we don't sort. This works as long as a register debug
+ symbol always comes after a parameter debug symbol. */
+
+ /* This is no longer necessary; lookup_block_symbol now always
+ prefers some other declaration over a parameter declaration. We
+ still sort the thing (that is necessary), but we don't reverse it
+ if we shouldn't sort it. */
+
+ for (i = 0; i < nbl; i++)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ if (BLOCK_SHOULD_SORT (b))
+ qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+ sizeof (struct symbol *), compare_symbols);
+ }
+}
+
+
+extern struct symtab *psymtab_to_symtab ();
+
+/* The entry point. */
+static CORE_ADDR entry_point;
+
+static char *symfile_string_table;
+static int symfile_string_table_size;
+
+/* This is the symbol-file command. Read the file, analyze its symbols,
+ and add a struct symtab to symtab_list. */
+
+void
+symbol_file_command (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ register int desc;
+ DECLARE_FILE_HEADERS;
+ struct nlist *nlist;
+
+ /* The string table. */
+ char *stringtab;
+
+ /* The size of the string table (buffer is a bizarre name...). */
+ long buffer;
+
+ register int val;
+ extern void close ();
+ struct cleanup *old_chain;
+ struct symtab *symseg;
+ struct stat statbuf;
+
+ dont_repeat ();
+
+ if (name == 0)
+ {
+ if ((symtab_list || partial_symtab_list)
+ && from_tty
+ && !query ("Discard symbol table? ", 0))
+ error ("Not confirmed.");
+ if (symfile)
+ free (symfile);
+ symfile = 0;
+ free_all_symtabs ();
+ free_all_psymtabs ();
+ return;
+ }
+
+ name = tilde_expand (name);
+ make_cleanup (free, name);
+
+ if ((symtab_list || partial_symtab_list)
+ && !query ("Load new symbol table from \"%s\"? ", name))
+ error ("Not confirmed.");
+
+ {
+ char *absolute_name;
+ desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
+ if (desc < 0)
+ perror_with_name (name);
+ else
+ name = absolute_name;
+ }
+
+ old_chain = make_cleanup (close, desc);
+ make_cleanup (free_current_contents, &name);
+
+ READ_FILE_HEADERS (desc, name);
+
+ entry_point = ENTRY_POINT;
+
+ if (NUMBER_OF_SYMBOLS == 0)
+ {
+ if (symfile)
+ free (symfile);
+ symfile = 0;
+ free_all_symtabs ();
+ free_all_psymtabs ();
+ printf ("%s has no symbol-table; symbols discarded.\n", name);
+ fflush (stdout);
+ do_cleanups (old_chain);
+ return;
+ }
+
+ printf ("Reading symbol data from %s...", name);
+ fflush (stdout);
+
+ /* Now read the string table, all at once. */
+ val = lseek (desc, STRING_TABLE_OFFSET, 0);
+ if (val < 0)
+ perror_with_name (name);
+ if (stat (name, &statbuf) == -1)
+ perror_with_name (name);
+ READ_STRING_TABLE_SIZE (buffer);
+ if (buffer >= 0 && buffer < statbuf.st_size)
+ {
+ /* This should speed things up without consuming much
+ extra memory (because probably little of the space is going
+ to be reused anyway, whether in data or stack space).
+
+ A quick test (running GDB on itself and setting 9 breakpoints
+ in different files) showed that memory usage was almost
+ identical for the two cases. */
+#if 0
+#ifdef BROKEN_LARGE_ALLOCA
+ stringtab = (char *) xmalloc (buffer);
+ make_cleanup (free, stringtab);
+#else
+ stringtab = (char *) alloca (buffer);
+#endif
+#endif
+ stringtab = (char *) xmalloc (buffer);
+ symfile_string_table = stringtab;
+ symfile_string_table_size = buffer;
+ }
+ else
+ stringtab = NULL;
+ if (stringtab == NULL)
+ error ("ridiculous string table size: %d bytes", buffer);
+
+ /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
+ Occaisionally, it won't. */
+ val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = myread (desc, stringtab, buffer);
+ if (val < 0)
+ perror_with_name (name);
+
+ /* Throw away the old symbol table. */
+
+ if (symfile)
+ free (symfile);
+ symfile = 0;
+ free_all_symtabs ();
+ free_all_psymtabs ();
+
+ /* Empty the hash table of global syms looking for values. */
+ bzero (global_sym_chain, sizeof global_sym_chain);
+
+ /* Symsegs are no longer supported by GDB. Setting symseg_chain to
+ 0 is easier than finding all the symseg code and eliminating it. */
+ symseg_chain = 0;
+
+ /* Position to read the symbol table. Do not read it all at once. */
+ val = lseek (desc, SYMBOL_TABLE_OFFSET, 0);
+ if (val < 0)
+ perror_with_name (name);
+
+ /* Don't put these on the cleanup chain; they need to stick around
+ until the next call to symbol_file_command. *Then* we'll free
+ them. */
+ free_header_files ();
+ init_header_files ();
+
+ init_misc_functions ();
+ make_cleanup (discard_misc_bunches, 0);
+
+ free_pendings = 0;
+ pending_blocks = 0;
+ file_symbols = 0;
+ global_symbols = 0;
+ make_cleanup (really_free_pendings, 0);
+
+ /* Now that the symbol table data of the executable file are all in core,
+ process them and define symbols accordingly. Closes desc. */
+
+ read_dbx_symtab (desc, stringtab, buffer, NUMBER_OF_SYMBOLS, 0,
+ ADDR_OF_TEXT_SEGMENT, SIZE_OF_TEXT_SEGMENT);
+
+ /* Go over the misc functions and install them in vector. */
+
+ condense_misc_bunches (0);
+
+ /* Don't allow char * to have a typename (else would get caddr_t.) */
+
+ TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+
+ /* Make a default for file to list. */
+
+ symfile = savestring (name, strlen (name));
+
+ /* Call to select_source_symtab used to be here; it was using too
+ much time. I'll make sure that list_sources can handle the lack
+ of current_source_symtab */
+
+ do_cleanups (old_chain); /* Descriptor closed here */
+
+ /* Free the symtabs made by read_symsegs, but not their contents,
+ which have been copied into symtabs on symtab_list. */
+ while (symseg_chain)
+ {
+ register struct symtab *s = symseg_chain->next;
+ free (symseg_chain);
+ symseg_chain = s;
+ }
+
+ if (!partial_symtab_list)
+ printf ("\n(no debugging symbols found)...");
+
+ printf ("done.\n");
+ fflush (stdout);
+}
+
+/* Return name of file symbols were loaded from, or 0 if none.. */
+
+char *
+get_sym_file ()
+{
+ return symfile;
+}
+
+/* Buffer for reading the symbol table entries. */
+static struct nlist symbuf[4096];
+static int symbuf_idx;
+static int symbuf_end;
+
+/* I/O descriptor for reading the symbol table. */
+static int symtab_input_desc;
+
+/* The address of the string table
+ of the object file we are reading (as copied into core). */
+static char *stringtab_global;
+
+/* Refill the symbol table input buffer
+ and set the variables that control fetching entries from it.
+ Reports an error if no data available.
+ This function can read past the end of the symbol table
+ (into the string table) but this does no harm. */
+
+static int
+fill_symbuf ()
+{
+ int nbytes = myread (symtab_input_desc, symbuf, sizeof (symbuf));
+ if (nbytes <= 0)
+ error ("error or end of file reading symbol table");
+ symbuf_end = nbytes / sizeof (struct nlist);
+ symbuf_idx = 0;
+ return 1;
+}
+
+/* dbx allows the text of a symbol name to be continued into the
+ next symbol name! When such a continuation is encountered
+ (a \ at the end of the text of a name)
+ call this function to get the continuation. */
+
+static char *
+next_symbol_text ()
+{
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf ();
+ symnum++;
+ return symbuf[symbuf_idx++].n_un.n_strx + stringtab_global;
+}
+
+/*
+ * Initializes storage for all of the partial symbols that will be
+ * created by read_dbx_symtab and subsidiaries.
+ */
+void
+init_psymbol_list (total_symbols)
+ int total_symbols;
+{
+ /* Current best guess is that there are approximately a twentieth
+ of the total symbols (in a debugging file) are global or static
+ oriented symbols */
+ global_psymbols.size = total_symbols / 10;
+ static_psymbols.size = total_symbols / 10;
+ global_psymbols.next = global_psymbols.list = (struct partial_symbol *)
+ xmalloc (global_psymbols.size * sizeof (struct partial_symbol));
+ static_psymbols.next = static_psymbols.list = (struct partial_symbol *)
+ xmalloc (static_psymbols.size * sizeof (struct partial_symbol));
+}
+
+/*
+ * Initialize the list of bincls to contain none and have some
+ * allocated.
+ */
+static void
+init_bincl_list (number)
+ int number;
+{
+ bincls_allocated = number;
+ next_bincl = bincl_list = (struct header_file_location *)
+ xmalloc (bincls_allocated * sizeof(struct header_file_location));
+}
+
+/*
+ * Add a bincl to the list.
+ */
+static void
+add_bincl_to_list (pst, name, instance)
+ struct partial_symtab *pst;
+ char *name;
+ int instance;
+{
+ if (next_bincl >= bincl_list + bincls_allocated)
+ {
+ int offset = next_bincl - bincl_list;
+ bincls_allocated *= 2;
+ bincl_list = (struct header_file_location *)
+ xrealloc (bincl_list,
+ bincls_allocated * sizeof (struct header_file_location));
+ next_bincl = bincl_list + offset;
+ }
+ next_bincl->pst = pst;
+ next_bincl->instance = instance;
+ next_bincl++->name = name;
+}
+
+/*
+ * Given a name, value pair, find the corresponding
+ * bincl in the list. Return the partial symtab associated
+ * with that header_file_location.
+ */
+struct partial_symtab *
+find_corresponding_bincl_psymtab (name, instance)
+ char *name;
+ int instance;
+{
+ struct header_file_location *bincl;
+
+ for (bincl = bincl_list; bincl < next_bincl; bincl++)
+ if (bincl->instance == instance
+ && !strcmp (name, bincl->name))
+ return bincl->pst;
+
+ return (struct partial_symtab *) 0;
+}
+
+/*
+ * Free the storage allocated for the bincl list.
+ */
+static void
+free_bincl_list ()
+{
+ free (bincl_list);
+ bincls_allocated = 0;
+}
+
+static struct partial_symtab *start_psymtab ();
+static void add_psymtab_dependency ();
+static void end_psymtab();
+
+static int
+compare_psymbols (s1, s2)
+ register struct partial_symbol *s1, *s2;
+{
+ register char
+ *st1 = SYMBOL_NAME (s1),
+ *st2 = SYMBOL_NAME (s2);
+ register int i;
+
+ if (st1[0] - st2[0])
+ return (st1[0] - st2[0]);
+ if (st1[1] - st2[1])
+ return (st1[1] - st2[1]);
+ if (i = strcmp(st1, st2))
+ return (i);
+ /* Next comparison implements policy that used to be in lookup_symbol:
+ * it would search psymtabs in psymtab_list order (reverse order of
+ * declaration) & take first occurance of symbol it found. So, we
+ * collate duplicate names in reverse psymtab order. */
+ return (s2->pst - s1->pst);
+}
+
+/* Given pointers to an a.out symbol table in core containing dbx
+ style data, setup partial_symtab's describing each source file for
+ which debugging information is available. NLISTLEN is the number
+ of symbols in the symbol table. All symbol names are given as
+ offsets relative to STRINGTAB. STRINGTAB_SIZE is the size of
+ STRINGTAB.
+
+ I have no idea whether or not this routine should be setup to deal
+ with inclinks. It seems reasonable to me that they be dealt with
+ standardly, so I am not going to make a strong effort to deal with
+ them here.
+ */
+
+static void
+read_dbx_symtab (desc, stringtab, stringtab_size, nlistlen, inclink,
+ text_addr, text_size)
+ int desc;
+ register char *stringtab;
+ register long stringtab_size;
+ register int nlistlen;
+ int inclink;
+ unsigned text_addr;
+ int text_size;
+{
+ register struct nlist *bufp;
+ register char *namestring;
+ register struct partial_symbol *psym;
+ register struct psymbol_allocation_list *psymbol_struct;
+
+ int nsl;
+ int past_first_source_file = 0;
+ CORE_ADDR last_o_file_start = 0;
+ char *last_o_file_name = "*bogus*";
+ struct cleanup *old_chain;
+ char *p;
+ enum namespace ns;
+ enum address_class class;
+
+#ifdef PROFILE_TYPES
+ int i;
+ int profile_types [256];
+ int strcmp_called = 0;
+ int autovars = 0;
+ int global_funs = 0;
+#endif
+
+ /* Current partial symtab */
+ struct partial_symtab *pst;
+
+ /* List of current psymtab's include files */
+ char **psymtab_include_list;
+ int includes_allocated;
+ int includes_used;
+
+ /* Index within current psymtab dependency list */
+ struct partial_symtab **dependency_list;
+ int dependencies_used, dependencies_allocated;
+
+#ifdef PROFILE_TYPES
+ for (i = 0; i < 256; i++)
+ profile_types[i] = 0;
+#endif
+
+ stringtab_global = stringtab;
+
+ pst = (struct partial_symtab *) 0;
+
+ includes_allocated = 30;
+ includes_used = 0;
+ psymtab_include_list = (char **) alloca (includes_allocated *
+ sizeof (char *));
+
+ dependencies_allocated = 30;
+ dependencies_used = 0;
+ dependency_list =
+ (struct partial_symtab **) alloca (dependencies_allocated *
+ sizeof (struct partial_symtab *));
+
+ old_chain = make_cleanup (free_all_psymtabs, 0);
+
+ /* Init bincl list */
+ init_bincl_list (20);
+ make_cleanup (free_bincl_list, 0);
+
+ /* Setup global partial symbol list */
+ init_psymbol_list (nlistlen);
+
+ last_source_file = 0;
+
+#ifdef END_OF_TEXT_DEFAULT
+ end_of_text_addr = END_OF_TEXT_DEFAULT;
+#else
+ end_of_text_addr = text_addr + text_size;
+#endif
+
+ symtab_input_desc = desc; /* This is needed for fill_symbuf below */
+ symbuf_end = symbuf_idx = 0;
+
+ for (symnum = 0; symnum < nlistlen; symnum++)
+ {
+ /* Get the symbol for this run and pull out some info */
+ QUIT; /* allow this to be interruptable */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf ();
+ bufp = &symbuf[symbuf_idx++];
+
+#ifdef PROFILE_TYPES
+ profile_types[bufp->n_type]++;
+#endif
+
+ /*
+ * Special case to speed up readin.
+ */
+ if (bufp->n_type == N_SLINE) continue;
+
+ /* Ok. There is a lot of code duplicated in the rest of this
+ switch statiement (for efficiency reasons). Since I don't
+ like duplicating code, I will do my penance here, and
+ describe the code which is duplicated:
+
+ *) The assignment to namestring.
+ *) The call to index.
+ *) The addition of a partial symbol the the two partial
+ symbol lists. This last is a large section of code, so
+ I've imbedded it in the following macro.
+ */
+
+/* Set namestring based on bufp. */
+#define SET_NAMESTRING()\
+ if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size) \
+ error ("Invalid symbol data: bad string table offset: %d", \
+ bufp->n_un.n_strx); \
+ namestring = bufp->n_un.n_strx + stringtab
+
+#define ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE)\
+ do { \
+ if ((LIST).next >= \
+ (LIST).list + (LIST).size) \
+ { \
+ (LIST).list = (struct partial_symbol *) \
+ xrealloc ((LIST).list, \
+ ((LIST).size * 2 \
+ * sizeof (struct partial_symbol))); \
+ /* Next assumes we only went one over. Should be good if \
+ program works correctly */ \
+ (LIST).next = \
+ (LIST).list + (LIST).size; \
+ (LIST).size *= 2; \
+ } \
+ psym = (LIST).next++; \
+ \
+ SYMBOL_NAME (psym) = (char *) obstack_alloc (psymbol_obstack, \
+ (NAMELENGTH) + 1); \
+ strncpy (SYMBOL_NAME (psym), (NAME), (NAMELENGTH)); \
+ SYMBOL_NAME (psym)[(NAMELENGTH)] = '\0'; \
+ SYMBOL_NAMESPACE (psym) = (NAMESPACE); \
+ SYMBOL_CLASS (psym) = (CLASS); \
+ SYMBOL_VALUE (psym) = (VALUE); \
+ } while (0);
+
+
+ switch (bufp->n_type)
+ {
+ /*
+ * Standard, non-debugger, symbols
+ */
+
+ case N_TEXT | N_EXT:
+ /* Catch etext */
+
+ SET_NAMESTRING();
+
+ if (namestring[6] == '\0' && namestring[5] == 't'
+ && namestring[4] == 'x' && namestring[3] == 'e'
+ && namestring[2] == 't' && namestring[1] == 'e'
+ && namestring[0] == '_')
+ end_of_text_addr = bufp->n_value;
+
+ /* Figure out beginning and end of global linker symbol
+ section and put non-debugger specified symbols on
+ tmp_symchain */
+
+ last_global_sym = symnum;
+ if (!first_global_sym) first_global_sym = symnum;
+
+ record_misc_function (namestring, bufp->n_value,
+ bufp->n_type); /* Always */
+
+ continue;
+
+#ifdef N_NBTEXT
+ case N_NBTEXT | N_EXT:
+#endif
+#ifdef N_NBDATA
+ case N_NBDATA | N_EXT:
+#endif
+#ifdef N_NBBSS
+ case N_NBBSS | N_EXT:
+#endif
+#ifdef N_SETV
+ case N_SETV | N_EXT:
+#endif
+ case N_ABS | N_EXT:
+ case N_DATA | N_EXT:
+ case N_BSS | N_EXT:
+ /* Figure out beginning and end of global linker symbol
+ section and put non-debugger specified symbols on
+ tmp_symchain */
+
+ SET_NAMESTRING();
+
+ last_global_sym = symnum;
+ if (!first_global_sym) first_global_sym = symnum;
+
+ /* Not really a function here, but... */
+ record_misc_function (namestring, bufp->n_value,
+ bufp->n_type); /* Always */
+
+ continue;
+
+#ifdef N_NBTEXT
+ case N_NBTEXT:
+#endif
+
+ /* We need to be able to deal with both N_FN or N_TEXT,
+ because we have no way of knowing whether the sys-supplied ld
+ or GNU ld was used to make the executable. */
+#if ! (N_FN & N_EXT)
+ case N_FN:
+#endif
+ case N_FN | N_EXT:
+ case N_TEXT:
+ SET_NAMESTRING();
+ if ((namestring[0] == '-' && namestring[1] == 'l')
+ || (namestring [(nsl = strlen (namestring)) - 1] == 'o'
+ && namestring [nsl - 2] == '.'))
+ {
+ if (entry_point < bufp->n_value
+ && entry_point >= last_o_file_start)
+ {
+ startup_file_start = last_o_file_start;
+ startup_file_end = bufp->n_value;
+ }
+ if (past_first_source_file && pst)
+ {
+ end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum * sizeof (struct nlist), bufp->n_value,
+ dependency_list, dependencies_used,
+ global_psymbols.next, static_psymbols.next);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ else
+ past_first_source_file = 1;
+ last_o_file_start = bufp->n_value;
+ last_o_file_name = namestring;
+ nsl = strlen(namestring);
+ if (namestring[nsl-2] == '.' && namestring[nsl-1] == 'o')
+ namestring[nsl-2] = 0;
+ }
+ else if (strcmp(namestring, "gcc_compiled."))
+ {
+ if (*namestring == '_')
+ ++namestring;
+ namestring = obconcat(last_o_file_name, ":", namestring);
+ last_global_sym = symnum;
+ if (!first_global_sym)
+ first_global_sym = symnum;
+ record_misc_function(namestring, bufp->n_value, bufp->n_type);
+ }
+ continue;
+
+ case N_ABS:
+ case N_DATA:
+ case N_BSS:
+ SET_NAMESTRING();
+ if (*namestring == '_')
+ ++namestring;
+ namestring = obconcat(last_o_file_name, ":", namestring);
+ last_global_sym = symnum;
+ if (!first_global_sym)
+ first_global_sym = symnum;
+ record_misc_function(namestring, bufp->n_value, bufp->n_type);
+ continue;
+
+ case N_UNDF:
+ case N_UNDF | N_EXT:
+#ifdef N_NBDATA
+ case N_NBDATA:
+#endif
+#ifdef N_NBBSS
+ case N_NBBSS:
+#endif
+
+ /* Keep going . . .*/
+
+ /*
+ * Special symbol types for GNU
+ */
+#ifdef N_INDR
+ case N_INDR:
+ case N_INDR | N_EXT:
+#endif
+#ifdef N_SETA
+ case N_SETA:
+ case N_SETA | N_EXT:
+ case N_SETT:
+ case N_SETT | N_EXT:
+ case N_SETD:
+ case N_SETD | N_EXT:
+ case N_SETB:
+ case N_SETB | N_EXT:
+ case N_SETV:
+#endif
+ continue;
+
+ /*
+ * Debugger symbols
+ */
+
+ case N_SO:
+ /* End the current partial symtab and start a new one */
+
+ SET_NAMESTRING();
+
+ if (pst && past_first_source_file)
+ {
+ end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum * sizeof (struct nlist), bufp->n_value,
+ dependency_list, dependencies_used,
+ global_psymbols.next, static_psymbols.next);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ else
+ past_first_source_file = 1;
+
+ pst = start_psymtab (namestring, bufp->n_value,
+ symnum * sizeof (struct nlist),
+ global_psymbols.next, static_psymbols.next);
+
+ continue;
+
+#ifdef N_BINCL
+ case N_BINCL:
+ /* Add this bincl to the bincl_list for future EXCLs. No
+ need to save the string; it'll be around until
+ read_dbx_symtab function return */
+
+ SET_NAMESTRING();
+
+ add_bincl_to_list (pst, namestring, bufp->n_value);
+
+ /* Mark down an include file in the current psymtab */
+
+ psymtab_include_list[includes_used++] = namestring;
+ if (includes_used >= includes_allocated)
+ {
+ char **orig = psymtab_include_list;
+
+ psymtab_include_list = (char **)
+ alloca ((includes_allocated *= 2) *
+ sizeof (char *));
+ bcopy (orig, psymtab_include_list,
+ includes_used * sizeof (char *));
+ }
+
+ continue;
+#endif
+
+ case N_SOL:
+ /* Mark down an include file in the current psymtab */
+
+ SET_NAMESTRING();
+
+ /* In C++, one may expect the same filename to come round many
+ times, when code is coming alternately from the main file
+ and from inline functions in other files. So I check to see
+ if this is a file we've seen before.
+
+ This seems to be a lot of time to be spending on N_SOL, but
+ things like "break expread.y:435" need to work (I
+ suppose the psymtab_include_list could be hashed or put
+ in a binary tree, if profiling shows this is a major hog). */
+ {
+ register int i;
+ for (i = 0; i < includes_used; i++)
+ if (!strcmp (namestring, psymtab_include_list[i]))
+ {
+ i = -1;
+ break;
+ }
+ if (i == -1)
+ continue;
+ }
+
+ psymtab_include_list[includes_used++] = namestring;
+ if (includes_used >= includes_allocated)
+ {
+ char **orig = psymtab_include_list;
+
+ psymtab_include_list = (char **)
+ alloca ((includes_allocated *= 2) *
+ sizeof (char *));
+ bcopy (orig, psymtab_include_list,
+ includes_used * sizeof (char *));
+ }
+ continue;
+
+ case N_LSYM: /* Typedef or automatic variable. */
+ SET_NAMESTRING();
+
+ p = (char *) index (namestring, ':');
+
+ /* Skip if there is no :. */
+ if (!p) continue;
+
+ switch (p[1])
+ {
+ case 'T':
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ static_psymbols, bufp->n_value);
+ goto check_enum;
+ case 't':
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ static_psymbols, bufp->n_value);
+ check_enum:
+ /* If this is an enumerated type, we need to
+ add all the enum constants to the partial symbol
+ table. This does not cover enums without names, e.g.
+ "enum {a, b} c;" in C, but fortunately those are
+ rare. There is no way for GDB to find those from the
+ enum type without spending too much time on it. Thus
+ to solve this problem, the compiler needs to put out separate
+ constant symbols ('c' N_LSYMS) for enum constants in
+ enums without names. */
+
+ /* We are looking for something of the form
+ <name> ":" ("t" | "T") [<number> "="] "e"
+ {<constant> ":" <value> ","} ";". */
+
+ /* Skip over the colon and the 't' or 'T'. */
+ p += 2;
+ /* This type may be given a number. Skip over it. */
+ while ((*p >= '0' && *p <= '9')
+ || *p == '=')
+ p++;
+
+ if (*p++ == 'e')
+ {
+ /* We have found an enumerated type. */
+ /* According to comments in read_enum_type
+ a comma could end it instead of a semicolon.
+ I don't know where that happens.
+ Accept either. */
+ while (*p && *p != ';' && *p != ',')
+ {
+ char *q;
+
+ /* Check for and handle cretinous dbx symbol name
+ continuation! */
+ if (*p == '\\')
+ p = next_symbol_text ();
+
+ /* Point to the character after the name
+ of the enum constant. */
+ for (q = p; *q && *q != ':'; q++)
+ ;
+ /* Note that the value doesn't matter for
+ enum constants in psymtabs, just in symtabs. */
+ ADD_PSYMBOL_TO_LIST (p, q - p,
+ VAR_NAMESPACE, LOC_CONST,
+ static_psymbols, 0);
+ /* Point past the name. */
+ p = q;
+ /* Skip over the value. */
+ while (*p && *p != ',')
+ p++;
+ /* Advance past the comma. */
+ if (*p)
+ p++;
+ }
+ }
+
+ continue;
+ case 'c':
+ /* Constant, e.g. from "const" in Pascal. */
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_CONST,
+ static_psymbols, bufp->n_value);
+ continue;
+ default:
+#ifdef PROFILE_TYPES
+ if (isalpha(p[1]))
+ printf ("Funny...LSYM with a letter that isn't a type\n");
+ autovars++;
+#endif
+ /* Skip if the thing following the : is
+ not a letter (which indicates declaration of a local
+ variable, which we aren't interested in). */
+ continue;
+ }
+
+ case N_FUN:
+#if 0
+ /* This special-casing of N_FUN is just wrong; N_FUN
+ does not mean "function"; it means "text segment".
+ So N_FUN can go with 'V', etc. as well as 'f' or 'F'. */
+
+ SET_NAMESTRING();
+
+ p = (char *) index (namestring, ':');
+
+ if (!p || p[1] == 'F') continue;
+
+#ifdef PROFILE_TYPES
+ if (p[1] != 'f')
+ printf ("Funny...FUN with a letter that isn't 'F' or 'f'.\n");
+ global_funs++;
+#endif
+
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ static_psymbols, bufp->n_value);
+
+ continue;
+#endif /* 0 */
+ case N_GSYM: /* Global (extern) variable; can be
+ data or bss (sigh). */
+ case N_STSYM: /* Data seg var -- static */
+ case N_LCSYM: /* BSS " */
+
+ /* Following may probably be ignored; I'll leave them here
+ for now (until I do Pascal and Modula 2 extensions). */
+
+ case N_PC: /* I may or may not need this; I
+ suspect not. */
+#ifdef N_M2C
+ case N_M2C: /* I suspect that I can ignore this here. */
+ case N_SCOPE: /* Same. */
+#endif
+
+ SET_NAMESTRING();
+
+ p = (char *) index (namestring, ':');
+ if (!p)
+ continue; /* Not a debugging symbol. */
+
+ process_symbol_for_psymtab:
+
+ /* Main processing section for debugging symbols which
+ the initial read through the symbol tables needs to worry
+ about. If we reach this point, the symbol which we are
+ considering is definitely one we are interested in.
+ p must also contain the (valid) index into the namestring
+ which indicates the debugging type symbol. */
+
+ switch (p[1])
+ {
+ case 'c':
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_CONST,
+ static_psymbols, bufp->n_value);
+ continue;
+ case 'S':
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ static_psymbols, bufp->n_value);
+ continue;
+ case 'G':
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_EXTERNAL,
+ global_psymbols, bufp->n_value);
+ continue;
+
+ case 't':
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ global_psymbols, bufp->n_value);
+ continue;
+
+ case 'f':
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ static_psymbols, bufp->n_value);
+ continue;
+
+ /* Two things show up here (hopefully); static symbols of
+ local scope (static used inside braces) or extensions
+ of structure symbols. We can ignore both. */
+ case 'V':
+ case '(':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* Global functions are ignored here. I'm not
+ sure what psymtab they go into (or just the misc
+ function vector). */
+ case 'F':
+ continue;
+
+ default:
+ fatal ("Internal error: Unexpected debugging symbol type '%c' at symnum %d.\n",
+ p[1], symnum);
+ }
+
+#ifdef N_BINCL
+ case N_EXCL:
+
+ SET_NAMESTRING();
+
+ /* Find the corresponding bincl and mark that psymtab on the
+ psymtab dependency list */
+ {
+ struct partial_symtab *needed_pst =
+ find_corresponding_bincl_psymtab (namestring, bufp->n_value);
+
+ /* If this include file was defined earlier in this file,
+ leave it alone. */
+ if (needed_pst == pst) continue;
+
+ if (needed_pst)
+ {
+ int i;
+ int found = 0;
+
+ for (i = 0; i < dependencies_used; i++)
+ if (dependency_list[i] == needed_pst)
+ {
+ found = 1;
+ break;
+ }
+
+ /* If it's already in the list, skip the rest. */
+ if (found) continue;
+
+ dependency_list[dependencies_used++] = needed_pst;
+ if (dependencies_used >= dependencies_allocated)
+ {
+ struct partial_symtab **orig = dependency_list;
+ dependency_list =
+ (struct partial_symtab **)
+ alloca ((dependencies_allocated *= 2)
+ * sizeof (struct partial_symtab *));
+ bcopy (orig, dependency_list,
+ (dependencies_used
+ * sizeof (struct partial_symtab *)));
+#ifdef DEBUG_INFO
+ fprintf (stderr, "Had to reallocate dependency list.\n");
+ fprintf (stderr, "New dependencies allocated: %d\n",
+ dependencies_allocated);
+#endif
+ }
+ }
+ else
+ error ("Invalid symbol data: \"repeated\" header file not previously seen, at symtab pos %d.",
+ symnum);
+ }
+ continue;
+
+ case N_EINCL:
+#endif
+#ifdef N_DSLINE
+ case N_DSLINE:
+#endif
+#ifdef N_BSLINE
+ case N_BSLINE:
+#endif
+ case N_SSYM: /* Claim: Structure or union element.
+ Hopefully, I can ignore this. */
+ case N_ENTRY: /* Alternate entry point; can ignore. */
+#ifdef N_MAIN
+ case N_MAIN: /* Can definitely ignore this. */
+#endif
+ case N_LENG:
+ case N_BCOMM:
+ case N_ECOMM:
+ case N_ECOML:
+ case N_FNAME:
+ case N_SLINE:
+ case N_RSYM:
+ case N_PSYM:
+ case N_LBRAC:
+ case N_RBRAC:
+ /* These symbols aren't interesting; don't worry about them */
+
+ continue;
+
+ default:
+ /* If we haven't found it yet, we've got problems */
+
+ if (IGNORE_SYMBOL (bufp->n_type))
+ continue;
+
+ fatal ("Bad symbol type 0x%x encountered in gdb scan", bufp->n_type);
+ }
+ }
+
+ /* If there's stuff to be cleaned up, clean it up. */
+ if (entry_point < bufp->n_value
+ && entry_point >= last_o_file_start)
+ {
+ startup_file_start = last_o_file_start;
+ startup_file_end = bufp->n_value;
+ }
+
+ if (pst)
+ {
+ end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum * sizeof (struct nlist), end_of_text_addr,
+ dependency_list, dependencies_used,
+ global_psymbols.next, static_psymbols.next);
+ includes_used = 0;
+ dependencies_used = 0;
+ pst = (struct partial_symtab *) 0;
+ }
+
+ /* sort the global & static symtab list so we can binary search them */
+ qsort (global_psymbols.list, global_psymbols.next - global_psymbols.list,
+ sizeof (struct partial_symbol), compare_psymbols);
+ qsort (static_psymbols.list, static_psymbols.next - static_psymbols.list,
+ sizeof (struct partial_symbol), compare_psymbols);
+ free_bincl_list ();
+ discard_cleanups (old_chain);
+#ifdef PROFILE_TYPES
+ {
+ int i, j;
+#define __define_stab(SYM, NUMBER, NAME) {NUMBER, NAME},
+ static struct xyzzy {
+ unsigned char symnum;
+ char *name;
+ } tmp_list[] = {
+#include "stab.def"
+ {0x1, "eREF"},
+ {0x2, "ABS"},
+ {0x3, "eABS"},
+ {0x4, "TEXT"},
+ {0x5, "eTEXT"},
+ {0x6, "DATA"},
+ {0x7, "eDATA"},
+ {0x8, "BSS"},
+ {0x9, "eBSS"},
+ {0x12, "COMM"},
+ {0x13, "eCOMM"},
+ {0x1f, "FN"},
+ {0, "Unknown"},
+};
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0; j < (sizeof (tmp_list) / sizeof (struct xyzzy)) - 1; j++)
+ if (tmp_list[j].symnum == i)
+ break;
+ printf ("Symbol \"%s\" (0x%x) occured %d times.\n",
+ tmp_list[j].name, i, profile_types[i]);
+ }
+ printf ("Auto vars (under LSYM): %d\n", autovars);
+ printf ("Global funs (under FUN): %d\n", global_funs);
+ }
+#endif
+}
+
+/*
+ * Allocate and partially fill a partial symtab. It will be
+ * completely filled at the end of the symbol list.
+ */
+static struct partial_symtab *
+start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms)
+ char *filename;
+ int textlow;
+ int ldsymoff;
+ struct partial_symbol *global_syms;
+ struct partial_symbol *static_syms;
+{
+ struct partial_symtab *result =
+ (struct partial_symtab *) obstack_alloc (psymbol_obstack,
+ sizeof (struct partial_symtab));
+
+ result->filename =
+ (char *) obstack_alloc (psymbol_obstack,
+ strlen (filename) + 1);
+ strcpy (result->filename, filename);
+
+ result->textlow = textlow;
+ result->ldsymoff = ldsymoff;
+
+ result->readin = 0;
+
+ result->globals_offset = global_syms - global_psymbols.list;
+ result->statics_offset = static_syms - static_psymbols.list;
+
+ result->n_global_syms = 0;
+ result->n_static_syms = 0;
+
+ return result;
+}
+
+
+/* Close off the current usage of a partial_symbol table entry. This
+ involves setting the correct number of includes (with a realloc),
+ setting the high text mark, setting the symbol length in the
+ executable, and setting the length of the global and static lists
+ of psymbols.
+
+ The global symbols and static symbols are then seperately sorted.
+
+ Then the partial symtab is put on the global list.
+ *** List variables and peculiarities of same. ***
+ */
+static void
+end_psymtab (pst, include_list, num_includes, capping_symbol_offset,
+ capping_text, dependency_list, number_dependencies,
+ capping_global, capping_static)
+ struct partial_symtab *pst;
+ char **include_list;
+ int num_includes;
+ int capping_symbol_offset;
+ int capping_text;
+ struct partial_symtab **dependency_list;
+ int number_dependencies;
+ struct partial_symbol *capping_global, *capping_static;
+{
+ int i;
+ register struct partial_symbol *ps;
+
+ pst->ldsymlen = capping_symbol_offset - pst->ldsymoff;
+ pst->texthigh = capping_text;
+
+ pst->n_global_syms =
+ capping_global - (global_psymbols.list + pst->globals_offset);
+ pst->n_static_syms =
+ capping_static - (static_psymbols.list + pst->statics_offset);
+
+ pst->dependencies = (struct partial_symtab **)
+ obstack_alloc (psymbol_obstack,
+ number_dependencies * sizeof (struct partial_symtab *));
+ bcopy (dependency_list, pst->dependencies,
+ number_dependencies * sizeof (struct partial_symtab *));
+ pst->number_of_dependencies = number_dependencies;
+
+ for (i = 0; i < num_includes; i++)
+ {
+ /* Eventually, put this on obstack */
+ struct partial_symtab *subpst =
+ (struct partial_symtab *)
+ obstack_alloc (psymbol_obstack,
+ sizeof (struct partial_symtab));
+
+ subpst->filename =
+ (char *) obstack_alloc (psymbol_obstack,
+ strlen (include_list[i]) + 1);
+ strcpy (subpst->filename, include_list[i]);
+
+ subpst->ldsymoff =
+ subpst->ldsymlen =
+ subpst->textlow =
+ subpst->texthigh = 0;
+ subpst->readin = 0;
+
+ subpst->dependencies = (struct partial_symtab **)
+ obstack_alloc (psymbol_obstack,
+ sizeof (struct partial_symtab *));
+ subpst->dependencies[0] = pst;
+ subpst->number_of_dependencies = 1;
+
+ subpst->globals_offset =
+ subpst->n_global_syms =
+ subpst->statics_offset =
+ subpst->n_static_syms = 0;
+
+ subpst->next = partial_symtab_list;
+ partial_symtab_list = subpst;
+ }
+
+ for (ps = global_psymbols.list + pst->globals_offset;
+ ps < capping_global; ++ps)
+ ps->pst = pst;
+ for (ps = static_psymbols.list + pst->statics_offset;
+ ps < capping_static; ++ps)
+ ps->pst = pst;
+
+ /* Put the psymtab on the psymtab list */
+ pst->next = partial_symtab_list;
+ partial_symtab_list = pst;
+}
+
+
+/* Helper routines for psymtab_to_symtab. */
+static void scan_file_globals ();
+static void read_ofile_symtab ();
+
+static void
+psymtab_to_symtab_1 (pst, desc, stringtab, stringtab_size, sym_offset)
+ struct partial_symtab *pst;
+ int desc;
+ char *stringtab;
+ int stringtab_size;
+ int sym_offset;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ /* Read in all partial symbtabs on which this one is dependent */
+ for (i = 0; i < pst->number_of_dependencies; i++)
+ if (!pst->dependencies[i]->readin)
+ {
+ /* Inform about additional files that need to be read in. */
+ if (info_verbose)
+ {
+ printf_filtered (" and %s...", pst->dependencies[i]->filename);
+ fflush (stdout);
+ }
+ psymtab_to_symtab_1 (pst->dependencies[i], desc,
+ stringtab, stringtab_size, sym_offset);
+ }
+
+ if (pst->ldsymlen) /* Otherwise it's a dummy */
+ {
+ /* Init stuff necessary for reading in symbols */
+ free_pendings = 0;
+ pending_blocks = 0;
+ file_symbols = 0;
+ global_symbols = 0;
+ old_chain = make_cleanup (really_free_pendings, 0);
+
+ /* Read in this files symbols */
+ lseek (desc, sym_offset, L_SET);
+ read_ofile_symtab (desc, stringtab, stringtab_size,
+ pst->ldsymoff,
+ pst->ldsymlen, pst->textlow,
+ pst->texthigh - pst->textlow, 0);
+ sort_symtab_syms (symtab_list); /* At beginning since just added */
+
+ do_cleanups (old_chain);
+ }
+
+ pst->readin = 1;
+}
+
+/*
+ * Read in all of the symbols for a given psymtab for real. Return
+ * the value of the symtab you create. Do not free the storage
+ * allocated to the psymtab; it may have pointers to it.
+ */
+struct symtab *
+psymtab_to_symtab(pst)
+ struct partial_symtab *pst;
+{
+ int desc;
+ DECLARE_FILE_HEADERS;
+ char *stringtab;
+ struct partial_symtab **list_patch;
+ int stsize, val;
+ struct stat statbuf;
+ struct cleanup *old_chain;
+ extern void close ();
+ int i;
+ struct symtab *result;
+ char *name = symfile; /* Some of the macros require the */
+ /* variable "name" to be defined in */
+ /* the context in which they execute */
+ /* (Yech!) */
+
+ if (!pst)
+ return 0;
+
+ if (pst->readin)
+ {
+ fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return 0;
+ }
+
+ if (!name)
+ error("No symbol file currently specified; use command symbol-file");
+
+ if (pst->ldsymlen || pst->number_of_dependencies)
+ {
+ /* Print the message now, before reading the string table,
+ to avoid disconcerting pauses. */
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ fflush (stdout);
+ }
+
+ /* Open symbol file and read in string table */
+ if (stat (name, &statbuf) < 0)
+ perror_with_name (name);
+ desc = open(name, O_RDONLY, 0); /* symbol_file_command
+ guarrantees that the symbol file name
+ will be absolute, so there is no
+ need for openp */
+
+ old_chain = make_cleanup (close, desc);
+
+ if (desc < 0)
+ error("Symbol file not readable");
+
+ READ_FILE_HEADERS (desc, name);
+
+#if 0
+ /* Read in the string table */
+ lseek (desc, STRING_TABLE_OFFSET, L_SET);
+ READ_STRING_TABLE_SIZE (stsize);
+ if (stsize >= 0 && stsize < statbuf.st_size)
+ {
+#ifdef BROKEN_LARGE_ALLOCA
+ stringtab = (char *) xmalloc (stsize);
+ make_cleanup (free, stringtab);
+#else
+ stringtab = (char *) alloca (stsize);
+#endif
+ }
+ else
+ stringtab = NULL;
+ if (stringtab == NULL)
+ error ("ridiculous string table size: %d bytes", stsize);
+
+ /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
+ Occaisionally, it won't. */
+ val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = myread (desc, stringtab, stsize);
+ if (val < 0)
+ perror_with_name (name);
+#endif /* 0 */
+ stringtab = symfile_string_table;
+ stsize = symfile_string_table_size;
+
+ psymtab_to_symtab_1 (pst, desc, stringtab, stsize,
+ SYMBOL_TABLE_OFFSET);
+
+ /* Match with global symbols. This only needs to be done once,
+ after all of the symtabs and dependencies have been read in. */
+ scan_file_globals ();
+
+ do_cleanups (old_chain);
+
+ /* Finish up the debug error message. */
+ if (info_verbose)
+ printf_filtered ("done.\n");
+ }
+
+ /* Search through list for correct name. */
+ for (result = symtab_list; result; result = result->next)
+ if (!strcmp (result->filename, pst->filename))
+ return result;
+
+ return 0;
+}
+
+/*
+ * Scan through all of the global symbols defined in the object file,
+ * assigning values to the debugging symbols that need to be assigned
+ * to. Get these symbols from the misc function list.
+ */
+static void
+scan_file_globals ()
+{
+ int hash;
+ int mf;
+
+ for (mf = 0; mf < misc_function_count; mf++)
+ {
+ char *namestring = misc_function_vector[mf].name;
+ struct symbol *sym, *prev;
+
+ QUIT;
+
+ prev = (struct symbol *) 0;
+
+ /* Get the hash index and check all the symbols
+ under that hash index. */
+
+ hash = hashname (namestring);
+
+ for (sym = global_sym_chain[hash]; sym;)
+ {
+ if (*namestring == SYMBOL_NAME (sym)[0]
+ && !strcmp(namestring + 1, SYMBOL_NAME (sym) + 1))
+ {
+ /* Splice this symbol out of the hash chain and
+ assign the value we have to it. */
+ if (prev)
+ SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
+ else
+ global_sym_chain[hash]
+ = (struct symbol *) SYMBOL_VALUE (sym);
+
+ /* Check to see whether we need to fix up a common block. */
+ /* Note: this code might be executed several times for
+ the same symbol if there are multiple references. */
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ fix_common_block (sym, misc_function_vector[mf].address);
+ else
+ SYMBOL_VALUE (sym) = misc_function_vector[mf].address;
+
+ if (prev)
+ sym = (struct symbol *) SYMBOL_VALUE (prev);
+ else
+ sym = global_sym_chain[hash];
+ }
+ else
+ {
+ prev = sym;
+ sym = (struct symbol *) SYMBOL_VALUE (sym);
+ }
+ }
+ }
+}
+
+/*
+ * Read in a defined section of a specific object file's symbols.
+ *
+ * DESC is the file descriptor for the file, positioned at the
+ * beginning of the symtab
+ * STRINGTAB is a pointer to the files string
+ * table, already read in
+ * SYM_OFFSET is the offset within the file of
+ * the beginning of the symbols we want to read, NUM_SUMBOLS is the
+ * number of symbols to read
+ * TEXT_OFFSET is the offset to be added to
+ * all values of symbols coming in and
+ * TEXT_SIZE is the size of the text segment read in.
+ * OFFSET is a flag which indicates that the value of all of the
+ * symbols should be offset by TEXT_OFFSET (for the purposes of
+ * incremental linking).
+ */
+
+static void
+read_ofile_symtab (desc, stringtab, stringtab_size, sym_offset,
+ sym_size, text_offset, text_size, offset)
+ int desc;
+ register char *stringtab;
+ int sym_offset;
+ int sym_size;
+ int text_offset;
+ int text_size;
+ int offset;
+{
+ register char *namestring;
+ register struct symbol *sym, *prev;
+ int hash;
+ struct cleanup *old_chain;
+ struct nlist *bufp;
+ unsigned char type;
+#ifdef N_BINCL
+ subfile_stack = 0;
+#endif
+
+ stringtab_global = stringtab;
+ last_source_file = 0;
+
+ symtab_input_desc = desc;
+ symbuf_end = symbuf_idx = 0;
+
+ /* It is necessary to actually read one symbol *before* the start
+ of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
+ occurs before the N_SO symbol.
+
+ Detecting this in read_dbx_symtab
+ would slow down initial readin, so we look for it here instead. */
+ if (sym_offset >= sizeof (struct nlist))
+ {
+ lseek (desc, sym_offset - sizeof (struct nlist), L_INCR);
+ fill_symbuf ();
+ bufp = &symbuf[symbuf_idx++];
+
+ if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size)
+ error ("Invalid symbol data: bad string table offset: %d",
+ bufp->n_un.n_strx);
+ namestring = bufp->n_un.n_strx + stringtab;
+
+ processing_gcc_compilation =
+ (bufp->n_type == N_TEXT
+ && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL));
+ }
+ else
+ {
+ /* The N_SO starting this symtab is the first symbol, so we
+ better not check the symbol before it. I'm not this can
+ happen, but it doesn't hurt to check for it. */
+ lseek(desc, sym_offset, L_INCR);
+ processing_gcc_compilation = 0;
+ }
+
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf();
+ bufp = &symbuf[symbuf_idx];
+ if ((unsigned char) bufp->n_type != N_SO)
+ fatal("First symbol in segment of executable not a source symbol");
+
+ for (symnum = 0;
+ symnum < sym_size / sizeof(struct nlist);
+ symnum++)
+ {
+ QUIT; /* Allow this to be interruptable */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf();
+ bufp = &symbuf[symbuf_idx++];
+ type = bufp->n_type;
+
+ if (offset &&
+ (type == N_TEXT || type == N_DATA || type == N_BSS))
+ bufp->n_value += text_offset;
+
+ if (bufp->n_un.n_strx < 0 || bufp->n_un.n_strx >= stringtab_size)
+ error ("Invalid symbol data: bad string table offset: %d",
+ bufp->n_un.n_strx);
+ namestring = bufp->n_un.n_strx + stringtab;
+
+ if (type & N_STAB)
+ process_one_symbol(type, bufp->n_desc,
+ bufp->n_value, namestring);
+ /* We skip checking for a new .o or -l file; that should never
+ happen in this routine. */
+ else if (type == N_TEXT
+ && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL))
+ /* I don't think this code will ever be executed, because
+ the GCC_COMPILED_FLAG_SYMBOL usually is right before
+ the N_SO symbol which starts this source file.
+ However, there is no reason not to accept
+ the GCC_COMPILED_FLAG_SYMBOL anywhere. */
+ processing_gcc_compilation = 1;
+ else if (type & N_EXT || type == N_TEXT
+#ifdef N_NBTEXT
+ || type == N_NBTEXT
+#endif
+ )
+ /* Global symbol: see if we came across a dbx defintion for
+ a corresponding symbol. If so, store the value. Remove
+ syms from the chain when their values are stored, but
+ search the whole chain, as there may be several syms from
+ different files with the same name. */
+ /* This is probably not true. Since the files will be read
+ in one at a time, each reference to a global symbol will
+ be satisfied in each file as it appears. So we skip this
+ section. */
+ &stringtab_global; /* For debugger; am I right? */
+ }
+ end_symtab (text_offset + text_size);
+}
+
+static int
+hashname (name)
+ char *name;
+{
+ register char *p = name;
+ register int total = p[0];
+ register int c;
+
+ c = p[1];
+ total += c << 2;
+ if (c)
+ {
+ c = p[2];
+ total += c << 4;
+ if (c)
+ total += p[3] << 6;
+ }
+
+ /* Ensure result is positive. */
+ if (total < 0) total += (1000 << 6);
+ return total % HASHSIZE;
+}
+
+/* Put all appropriate global symbols in the symseg data
+ onto the hash chains so that their addresses will be stored
+ when seen later in loader global symbols. */
+
+static void
+hash_symsegs ()
+{
+ /* Look at each symbol in each block in each symseg symtab. */
+ struct symtab *s;
+ for (s = symseg_chain; s; s = s->next)
+ {
+ register int n;
+ for (n = BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)) - 1; n >= 0; n--)
+ {
+ register struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), n);
+ register int i;
+ for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
+ {
+ register struct symbol *sym = BLOCK_SYM (b, i);
+
+ /* Put the symbol on a chain if its value is an address
+ that is figured out by the loader. */
+
+ if (SYMBOL_CLASS (sym) == LOC_EXTERNAL)
+ {
+ register int hash = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE (sym) = (int) global_sym_chain[hash];
+ global_sym_chain[hash] = sym;
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ }
+ }
+ }
+ }
+}
+
+static void
+process_one_symbol (type, desc, value, name)
+ int type, desc;
+ CORE_ADDR value;
+ char *name;
+{
+ register struct context_stack *new;
+ char *colon_pos;
+
+ /* Something is wrong if we see real data before
+ seeing a source file name. */
+
+ if (last_source_file == 0 && type != N_SO)
+ {
+ /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines
+ where that code is defined. */
+ if (IGNORE_SYMBOL (type))
+ return;
+
+ error ("Invalid symbol data: does not start by identifying a source file.");
+ }
+
+ switch (type)
+ {
+ case N_FUN:
+ case N_FNAME:
+ /* Either of these types of symbols indicates the start of
+ a new function. We must process its "name" normally for dbx,
+ but also record the start of a new lexical context, and possibly
+ also the end of the lexical context for the previous function. */
+ /* This is not always true. This type of symbol may indicate a
+ text segment variable. */
+
+ colon_pos = index (name, ':');
+ if (!colon_pos++
+ || (*colon_pos != 'f' && *colon_pos != 'F'))
+ {
+ define_symbol (value, name, desc);
+ break;
+ }
+
+ within_function = 1;
+ if (context_stack_depth > 0)
+ {
+ new = &context_stack[--context_stack_depth];
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, value);
+ }
+ /* Stack must be empty now. */
+ if (context_stack_depth != 0)
+ error ("Invalid symbol data: unmatched N_LBRAC before symtab pos %d.",
+ symnum);
+
+ new = &context_stack[context_stack_depth++];
+ new->old_blocks = pending_blocks;
+ new->start_addr = value;
+ new->name = define_symbol (value, name, desc);
+ local_symbols = 0;
+ break;
+
+ case N_LBRAC:
+ /* This "symbol" just indicates the start of an inner lexical
+ context within a function. */
+
+ if (context_stack_depth == context_stack_size)
+ {
+ context_stack_size *= 2;
+ context_stack = (struct context_stack *)
+ xrealloc (context_stack,
+ (context_stack_size
+ * sizeof (struct context_stack)));
+ }
+
+ new = &context_stack[context_stack_depth++];
+ new->depth = desc;
+ new->locals = local_symbols;
+ new->old_blocks = pending_blocks;
+ new->start_addr = value;
+ new->name = 0;
+ local_symbols = 0;
+ break;
+
+ case N_RBRAC:
+ /* This "symbol" just indicates the end of an inner lexical
+ context that was started with N_LBRAC. */
+ new = &context_stack[--context_stack_depth];
+ if (desc != new->depth)
+ error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum);
+
+ /* Some native compilers put the variable decls inside of an
+ LBRAC/RBRAC block. This macro should be nonzero if this
+ is true. DESC is N_DESC from the N_RBRAC symbol. */
+#if !defined (VARIABLES_INSIDE_BLOCK)
+#define VARIABLES_INSIDE_BLOCK(desc) 0
+#endif
+
+ /* Can only use new->locals as local symbols here if we're in
+ gcc or on a machine that puts them before the lbrack. */
+ if (!VARIABLES_INSIDE_BLOCK(desc))
+ local_symbols = new->locals;
+
+ /* If this is not the outermost LBRAC...RBRAC pair in the
+ function, its local symbols preceded it, and are the ones
+ just recovered from the context stack. Defined the block for them.
+
+ If this is the outermost LBRAC...RBRAC pair, there is no
+ need to do anything; leave the symbols that preceded it
+ to be attached to the function's own block. However, if
+ it is so, we need to indicate that we just moved outside
+ of the function. */
+ if (local_symbols
+ && context_stack_depth > !VARIABLES_INSIDE_BLOCK(desc))
+ {
+ /* Muzzle a compiler bug that makes end < start. */
+ if (new->start_addr > value)
+ new->start_addr = value;
+ /* Make a block for the local symbols within. */
+ finish_block (0, &local_symbols, new->old_blocks,
+ new->start_addr + last_source_start_addr,
+ value + last_source_start_addr);
+ }
+ else
+ {
+ within_function = 0;
+ }
+ if (VARIABLES_INSIDE_BLOCK(desc))
+ /* Now pop locals of block just finished. */
+ local_symbols = new->locals;
+ break;
+
+ case N_FN | N_EXT:
+ /* This kind of symbol supposedly indicates the start
+ of an object file. In fact this type does not appear. */
+ break;
+
+ case N_SO:
+ /* This type of symbol indicates the start of data
+ for one source file.
+ Finish the symbol table of the previous source file
+ (if any) and start accumulating a new symbol table. */
+#ifdef PCC_SOL_BROKEN
+ /* pcc bug, occasionally puts out SO for SOL. */
+ if (context_stack_depth > 0)
+ {
+ start_subfile (name);
+ break;
+ }
+#endif
+ if (last_source_file)
+ end_symtab (value);
+ start_symtab (name, value);
+ break;
+
+ case N_SOL:
+ /* This type of symbol indicates the start of data for
+ a sub-source-file, one whose contents were copied or
+ included in the compilation of the main source file
+ (whose name was given in the N_SO symbol.) */
+ start_subfile (name);
+ break;
+
+#ifdef N_BINCL
+ case N_BINCL:
+ push_subfile ();
+ add_new_header_file (name, value);
+ start_subfile (name);
+ break;
+
+ case N_EINCL:
+ start_subfile (pop_subfile ());
+ break;
+
+ case N_EXCL:
+ add_old_header_file (name, value);
+ break;
+#endif /* have N_BINCL */
+
+ case N_SLINE:
+ /* This type of "symbol" really just records
+ one line-number -- core-address correspondence.
+ Enter it in the line list for this symbol table. */
+ record_line (desc, value);
+ break;
+
+ case N_BCOMM:
+ if (common_block)
+ error ("Invalid symbol data: common within common at symtab pos %d",
+ symnum);
+ common_block = local_symbols;
+ common_block_i = local_symbols ? local_symbols->nsyms : 0;
+ break;
+
+ case N_ECOMM:
+ /* Symbols declared since the BCOMM are to have the common block
+ start address added in when we know it. common_block points to
+ the first symbol after the BCOMM in the local_symbols list;
+ copy the list and hang it off the symbol for the common block name
+ for later fixup. */
+ {
+ int i;
+ struct pending *link = local_symbols;
+ struct symbol *sym =
+ (struct symbol *) xmalloc (sizeof (struct symbol));
+ bzero (sym, sizeof *sym);
+ SYMBOL_NAME (sym) = savestring (name, strlen (name));
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_NAMESPACE (sym) = (enum namespace)((long)
+ copy_pending (local_symbols, common_block_i, common_block));
+ i = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE (sym) = (int) global_sym_chain[i];
+ global_sym_chain[i] = sym;
+ common_block = 0;
+ break;
+ }
+
+ case N_ECOML:
+ case N_LENG:
+ break;
+
+ default:
+ if (name)
+ define_symbol (value, name, desc);
+ }
+}
+
+/* This function was added for C++ functionality. I presume that it
+ condenses the bunches formed by reading in an additional .o file
+ (incremental linking). */
+
+static void
+condense_addl_misc_bunches ()
+{
+ register int i, j;
+ register struct misc_bunch *bunch;
+#ifdef NAMES_HAVE_UNDERSCORE
+ int offset = 1;
+#else
+ int offset = 0;
+#endif
+
+ misc_function_vector
+ = (struct misc_function *) xrealloc (misc_function_vector,
+ (misc_count + misc_function_count) * sizeof (struct misc_function));
+
+ j = misc_function_count;
+ bunch = misc_bunch;
+ while (bunch)
+ {
+ for (i = 0; i < misc_bunch_index; i++)
+ {
+ misc_function_vector[j] = bunch->contents[i];
+ misc_function_vector[j].name
+ = concat (misc_function_vector[j].name
+ + (misc_function_vector[j].name[0] == '_' ? offset : 0),
+ "", "");
+ j++;
+ }
+ bunch = bunch->next;
+ misc_bunch_index = MISC_BUNCH_SIZE;
+ }
+
+ misc_function_count += misc_count;
+
+ /* Sort the misc functions by address. */
+
+ qsort (misc_function_vector, misc_function_count,
+ sizeof (struct misc_function), compare_misc_functions);
+}
+
+
+/* Read in another .o file and create a symtab entry for it.*/
+
+static void
+read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
+ int desc;
+ register char *stringtab;
+ register int nlistlen;
+ unsigned text_addr;
+ int text_size;
+{
+ FILE *stream = fdopen (desc, "r");
+ register char *namestring;
+ register struct symbol *sym, *prev;
+ int hash;
+
+#ifdef N_BINCL
+ subfile_stack = 0;
+#endif
+
+ last_source_file = 0;
+ bzero (global_sym_chain, sizeof global_sym_chain);
+ symtab_input_desc = desc;
+ stringtab_global = stringtab;
+ fill_symbuf ();
+
+ for (symnum = 0; symnum < nlistlen; symnum++)
+ {
+ struct nlist *bufp;
+ unsigned char type;
+
+ QUIT; /* allow this to be interruptable */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf ();
+ bufp = &symbuf[symbuf_idx++];
+ type = bufp->n_type & N_TYPE;
+ namestring = bufp->n_un.n_strx + stringtab;
+
+ if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) )
+ {
+ /* Relocate this file's symbol table information
+ to the address it has been loaded into. */
+ bufp->n_value += text_addr;
+ }
+
+ type = bufp->n_type;
+
+ if (type & N_STAB)
+ process_one_symbol (type, bufp->n_desc,
+ bufp->n_value, namestring);
+ /* A static text symbol whose name ends in ".o"
+ can only mean the start of another object file.
+ So end the symtab of the source file we have been processing.
+ This is how we avoid counting the libraries as part
+ or the last source file.
+ Also this way we find end of first object file (crt0). */
+ else if ((type == N_TEXT
+#ifdef N_NBTEXT
+ || type == N_NBTEXT
+#endif
+ )
+ && (!strcmp (namestring + strlen (namestring) - 2, ".o"))
+ || ! strncmp (namestring, "-l", 2))
+ {
+ if (last_source_file)
+ end_symtab (bufp->n_value);
+ }
+ else if (type & N_EXT || type == N_TEXT
+#ifdef N_NBTEXT
+ || type == N_NBTEXT
+#endif
+ )
+ {
+ int used_up = 0;
+
+ /* Record the location of _etext. */
+ if (type == (N_TEXT | N_EXT)
+ && !strcmp (namestring, "_etext"))
+ end_of_text_addr = bufp->n_value;
+
+#if 0
+ /* 25 Sep 89: The following seems to be stolen from
+ read_ofile_symtab, and is wrong here (i.e. there was no
+ first pass for add-file symbols). */
+ /* This shouldn't be necessary, as we now do all of this work
+ in scan_global syms and all misc functions should have been
+ recorded on the first pass. */
+ /* Global symbol: see if we came across a dbx definition
+ for a corresponding symbol. If so, store the value.
+ Remove syms from the chain when their values are stored,
+ but search the whole chain, as there may be several syms
+ from different files with the same name. */
+ if (type & N_EXT)
+ {
+ prev = 0;
+#ifdef NAMES_HAVE_UNDERSCORE
+ hash = hashname (namestring + 1);
+#else /* not NAMES_HAVE_UNDERSCORE */
+ hash = hashname (namestring);
+#endif /* not NAMES_HAVE_UNDERSCORE */
+ for (sym = global_sym_chain[hash];
+ sym;)
+ {
+ if (
+#ifdef NAMES_HAVE_UNDERSCORE
+ *namestring == '_'
+ && namestring[1] == SYMBOL_NAME (sym)[0]
+ &&
+ !strcmp (namestring + 2, SYMBOL_NAME (sym) + 1)
+#else /* NAMES_HAVE_UNDERSCORE */
+ namestring[0] == SYMBOL_NAME (sym)[0]
+ &&
+ !strcmp (namestring + 1, SYMBOL_NAME (sym) + 1)
+#endif /* NAMES_HAVE_UNDERSCORE */
+ )
+ {
+ if (prev)
+ SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
+ else
+ global_sym_chain[hash]
+ = (struct symbol *) SYMBOL_VALUE (sym);
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ fix_common_block (sym, bufp->n_value);
+ else
+ SYMBOL_VALUE (sym) = bufp->n_value;
+ if (prev)
+ sym = (struct symbol *) SYMBOL_VALUE (prev);
+ else
+ sym = global_sym_chain[hash];
+
+ used_up = 1;
+ }
+ else
+ {
+ prev = sym;
+ sym = (struct symbol *) SYMBOL_VALUE (sym);
+ }
+ }
+ }
+
+ /* Defined global or text symbol: record as a misc function
+ if it didn't give its address to a debugger symbol above. */
+ if (type <= (N_TYPE | N_EXT)
+ && type != N_EXT
+ && ! used_up)
+ record_misc_function (namestring, bufp->n_value,
+ bufp->n_type);
+#endif /* 0 */
+ }
+ }
+
+ if (last_source_file)
+ end_symtab (text_addr + text_size);
+
+ fclose (stream);
+}
+
+/* C++:
+ This function allows the addition of incrementally linked object files.
+ Since this has a fair amount of code in common with symbol_file_command,
+ it might be worthwhile to consolidate things, as was done with
+ read_dbx_symtab and condense_misc_bunches. */
+
+void
+add_file_command (arg_string)
+ char* arg_string;
+{
+ register int desc;
+ DECLARE_FILE_HEADERS;
+ struct nlist *nlist;
+ char *stringtab;
+ long buffer;
+ register int val;
+ extern void close ();
+ struct cleanup *old_chain;
+ struct symtab *symseg;
+ struct stat statbuf;
+ char *name;
+ unsigned text_addr;
+
+ if (arg_string == 0)
+ error ("add-file takes a file name and an address");
+
+ arg_string = tilde_expand (arg_string);
+ make_cleanup (free, arg_string);
+
+ for( ; *arg_string == ' '; arg_string++ );
+ name = arg_string;
+ for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
+ *arg_string++ = (char) 0;
+
+ if (name[0] == 0)
+ error ("add-file takes a file name and an address");
+
+ text_addr = parse_and_eval_address (arg_string);
+
+ dont_repeat ();
+
+ if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n",
+ name, text_addr))
+ error ("Not confirmed.");
+
+ desc = open (name, O_RDONLY);
+ if (desc < 0)
+ perror_with_name (name);
+
+ old_chain = make_cleanup (close, desc);
+
+ READ_FILE_HEADERS (desc, name);
+
+ if (NUMBER_OF_SYMBOLS == 0)
+ {
+ printf ("%s does not have a symbol-table.\n", name);
+ fflush (stdout);
+ return;
+ }
+
+ printf ("Reading symbol data from %s...", name);
+ fflush (stdout);
+
+ /* Now read the string table, all at once. */
+ val = lseek (desc, STRING_TABLE_OFFSET, 0);
+ if (val < 0)
+ perror_with_name (name);
+ if (stat (name, &statbuf) < 0)
+ perror_with_name (name);
+ READ_STRING_TABLE_SIZE (buffer);
+ if (buffer >= 0 && buffer < statbuf.st_size)
+ {
+#ifdef BROKEN_LARGE_ALLOCA
+ stringtab = (char *) xmalloc (buffer);
+ make_cleanup (free, stringtab);
+#else
+ stringtab = (char *) alloca (buffer);
+#endif
+ }
+ else
+ stringtab = NULL;
+ if (stringtab == NULL)
+ error ("ridiculous string table size: %d bytes", buffer);
+
+ /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
+ Occaisionally, it won't. */
+ val = lseek (desc, STRING_TABLE_OFFSET, 0);
+ if (val < 0)
+ perror_with_name (name);
+ val = myread (desc, stringtab, buffer);
+ if (val < 0)
+ perror_with_name (name);
+
+ /* Symsegs are no longer supported by GDB. Setting symseg_chain to
+ 0 is easier than finding all the symseg code and eliminating it. */
+ symseg_chain = 0;
+
+ /* Position to read the symbol table. Do not read it all at once. */
+ val = lseek (desc, SYMBOL_TABLE_OFFSET, 0);
+ if (val < 0)
+ perror_with_name (name);
+
+ init_misc_functions ();
+ make_cleanup (discard_misc_bunches, 0);
+ init_header_files ();
+ make_cleanup (free_header_files, 0);
+ free_pendings = 0;
+ pending_blocks = 0;
+ file_symbols = 0;
+ global_symbols = 0;
+ make_cleanup (really_free_pendings, 0);
+
+ read_addl_syms (desc, stringtab, NUMBER_OF_SYMBOLS, text_addr,
+ SIZE_OF_TEXT_SEGMENT);
+
+
+ /* Sort symbols alphabetically within each block. */
+
+ sort_syms ();
+
+ /* Go over the misc functions and install them in vector. */
+
+ condense_addl_misc_bunches (1);
+
+ /* Don't allow char * to have a typename (else would get caddr_t.) */
+
+ TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+
+ do_cleanups (old_chain);
+
+ /* Free the symtabs made by read_symsegs, but not their contents,
+ which have been copied into symtabs on symtab_list. */
+ while (symseg_chain)
+ {
+ register struct symtab *s = symseg_chain->next;
+ free (symseg_chain);
+ symseg_chain = s;
+ }
+
+ printf ("done.\n");
+ fflush (stdout);
+}
+
+/* Read a number by which a type is referred to in dbx data,
+ or perhaps read a pair (FILENUM, TYPENUM) in parentheses.
+ Just a single number N is equivalent to (0,N).
+ Return the two numbers by storing them in the vector TYPENUMS.
+ TYPENUMS will then be used as an argument to dbx_lookup_type. */
+
+static void
+read_type_number (pp, typenums)
+ register char **pp;
+ register int *typenums;
+{
+ if (**pp == '(')
+ {
+ (*pp)++;
+ typenums[0] = read_number (pp, ',');
+ typenums[1] = read_number (pp, ')');
+ }
+ else
+ {
+ typenums[0] = 0;
+ typenums[1] = read_number (pp, 0);
+ }
+}
+
+
+
+static struct symbol *
+define_symbol (value, string, desc)
+ int value;
+ char *string;
+ int desc;
+{
+ register struct symbol *sym
+ = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+ char *p = (char *) index (string, ':');
+ int deftype;
+ register int i;
+
+ /* Ignore syms with empty names. */
+ if (string[0] == 0)
+ return 0;
+
+ /* Ignore old-style symbols from cc -go */
+ if (p == 0)
+ return 0;
+
+ SYMBOL_NAME (sym)
+ = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1));
+ /* Open-coded bcopy--saves function call time. */
+ {
+ register char *p1 = string;
+ register char *p2 = SYMBOL_NAME (sym);
+ while (p1 != p)
+ *p2++ = *p1++;
+ *p2++ = '\0';
+ }
+ p++;
+ /* Determine the type of name being defined. */
+ if ((*p >= '0' && *p <= '9') || *p == '(')
+ deftype = 'l';
+ else
+ deftype = *p++;
+
+ /* c is a special case, not followed by a type-number.
+ SYMBOL:c=iVALUE for an integer constant symbol.
+ SYMBOL:c=rVALUE for a floating constant symbol.
+ SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ if (deftype == 'c')
+ {
+ if (*p++ != '=')
+ error ("Invalid symbol data at symtab pos %d.", symnum);
+ switch (*p++)
+ {
+ case 'r':
+ {
+ double d = atof (p);
+ char *value;
+
+ SYMBOL_TYPE (sym) = builtin_type_double;
+ value = (char *) obstack_alloc (symbol_obstack, sizeof (double));
+ bcopy (&d, value, sizeof (double));
+ SYMBOL_VALUE_BYTES (sym) = value;
+ SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ }
+ break;
+ case 'i':
+ {
+ SYMBOL_TYPE (sym) = builtin_type_int;
+ SYMBOL_VALUE (sym) = atoi (p);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ }
+ break;
+ case 'e':
+ /* SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ {
+ int typenums[2];
+
+ read_type_number (&p, typenums);
+ if (*p++ != ',')
+ error ("Invalid symbol data: no comma in enum const symbol");
+
+ SYMBOL_TYPE (sym) = *dbx_lookup_type (typenums);
+ SYMBOL_VALUE (sym) = atoi (p);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ }
+ break;
+ default:
+ error ("Invalid symbol data at symtab pos %d.", symnum);
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ return sym;
+ }
+
+ /* Now usually comes a number that says which data type,
+ and possibly more stuff to define the type
+ (all of which is handled by read_type) */
+
+ if (deftype == 'p' && *p == 'F')
+ /* pF is a two-letter code that means a function parameter in Fortran.
+ The type-number specifies the type of the return value.
+ Translate it into a pointer-to-function type. */
+ {
+ p++;
+ SYMBOL_TYPE (sym)
+ = lookup_pointer_type (lookup_function_type (read_type (&p)));
+ }
+ else
+ {
+ struct type *type = read_type (&p);
+
+ if ((deftype == 'F' || deftype == 'f')
+ && TYPE_CODE (type) != TYPE_CODE_FUNC)
+ SYMBOL_TYPE (sym) = lookup_function_type (type);
+ else
+ SYMBOL_TYPE (sym) = type;
+ }
+
+ switch (deftype)
+ {
+ case 'f':
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 'F':
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &global_symbols);
+ break;
+
+ case 'G':
+ /* For a class G (global) symbol, it appears that the
+ value is not correct. It is necessary to search for the
+ corresponding linker definition to find the value.
+ These definitions appear at the end of the namelist. */
+ i = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE (sym) = (int) global_sym_chain[i];
+ global_sym_chain[i] = sym;
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &global_symbols);
+ break;
+
+ /* This case is faked by a conditional above,
+ when there is no code letter in the dbx data.
+ Dbx data never actually contains 'l'. */
+ case 'l':
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'p':
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+
+ /* If it's gcc compiled, if it says `short', believe it. */
+ if (processing_gcc_compilation || BELIEVE_PCC_PROMOTION)
+ break;
+
+#if defined(BELIEVE_PCC_PROMOTION_TYPE)
+ /* This macro is defined on machines (e.g. sparc) where
+ we should believe the type of a PCC 'short' argument,
+ but shouldn't believe the address (the address is
+ the address of the corresponding int). Note that
+ this is only different from the BELIEVE_PCC_PROMOTION
+ case on big-endian machines.
+
+ My guess is that this correction, as opposed to changing
+ the parameter to an 'int' (as done below, for PCC
+ on most machines), is the right thing to do
+ on all machines, but I don't want to risk breaking
+ something that already works. On most PCC machines,
+ the sparc problem doesn't come up because the calling
+ function has to zero the top bytes (not knowing whether
+ the called function wants an int or a short), so there
+ is no practical difference between an int and a short
+ (except perhaps what happens when the GDB user types
+ "print short_arg = 0x10000;").
+ Hacked for SunOS 4.1 by gnu@cygnus.com. In 4.1, the compiler
+ actually produces the correct address (we don't need to fix it
+ up). I made this code adapt so that it will offset the symbol
+ if it was pointing at an int-aligned location and not
+ otherwise. This way you can use the same gdb for 4.0.x and
+ 4.1 systems. */
+
+ if (0 == SYMBOL_VALUE (sym) % sizeof (int))
+ {
+ if (SYMBOL_TYPE (sym) == builtin_type_char
+ || SYMBOL_TYPE (sym) == builtin_type_unsigned_char)
+ SYMBOL_VALUE (sym) += 3;
+ else if (SYMBOL_TYPE (sym) == builtin_type_short
+ || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
+ SYMBOL_VALUE (sym) += 2;
+ }
+ break;
+
+#else /* no BELIEVE_PCC_PROMOTION_TYPE. */
+
+ /* If PCC says a parameter is a short or a char,
+ it is really an int. */
+ if (SYMBOL_TYPE (sym) == builtin_type_char
+ || SYMBOL_TYPE (sym) == builtin_type_short)
+ SYMBOL_TYPE (sym) = builtin_type_int;
+ else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
+ || SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
+ SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
+ break;
+
+#endif /* no BELIEVE_PCC_PROMOTION_TYPE. */
+
+ case 'P':
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (value);
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'r':
+/* XXX */
+#ifdef sparc
+{
+ struct symbol *s0;
+
+ /*
+ * If we see a parm decl immediately followed by a reg decl of
+ * the same name (and in the same block), we change it to a single
+ * instance of a reg parm. Sun's cc will generate these.
+ */
+ if (local_symbols &&
+ (s0 = local_symbols->symbol[local_symbols->nsyms - 1]) &&
+ SYMBOL_CLASS(s0) == LOC_ARG &&
+ strcmp(SYMBOL_NAME(s0), SYMBOL_NAME(sym)) == 0) {
+ SYMBOL_CLASS (s0) = LOC_REGPARM;
+ SYMBOL_VALUE (s0) = STAB_REG_TO_REGNUM (value);
+ SYMBOL_NAMESPACE (s0) = VAR_NAMESPACE;
+ return s0;
+ }
+}
+#endif
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (value);
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'S':
+ /* Static symbol at top level of file */
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 't':
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
+ && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
+ TYPE_NAME (SYMBOL_TYPE (sym)) =
+ obsavestring (SYMBOL_NAME (sym),
+ strlen (SYMBOL_NAME (sym)));
+ /* C++ vagaries: we may have a type which is derived from
+ a base type which did not have its name defined when the
+ derived class was output. We fill in the derived class's
+ base part member's name here in that case. */
+ else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
+ && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
+ {
+ int i;
+ for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--)
+ if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) == 0)
+ TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) =
+ TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i));
+ }
+
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 'T':
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0
+ && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0)
+ TYPE_NAME (SYMBOL_TYPE (sym))
+ = obconcat ("",
+ (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM
+ ? "enum "
+ : (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+ ? "struct " : "union ")),
+ SYMBOL_NAME (sym));
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 'V':
+ /* Static symbol of local scope */
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'v':
+ /* Reference parameter */
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'X':
+ /* This is used by Sun FORTRAN for "function result value".
+ Sun claims ("dbx and dbxtool interfaces", 2nd ed)
+ that Pascal uses it too, but when I tried it Pascal used
+ "x:3" (local symbol) instead. */
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ default:
+ error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum);
+ }
+ return sym;
+}
+
+/* What about types defined as forward references inside of a small lexical
+ scope? */
+/* Add a type to the list of undefined types to be checked through
+ once this file has been read in. */
+static void
+add_undefined_type (type)
+ struct type *type;
+{
+ if (undef_types_length == undef_types_allocated)
+ {
+ undef_types_allocated *= 2;
+ undef_types = (struct type **)
+ xrealloc (undef_types,
+ undef_types_allocated * sizeof (struct type *));
+ }
+ undef_types[undef_types_length++] = type;
+}
+
+/* Add here something to go through each undefined type, see if it's
+ still undefined, and do a full lookup if so. */
+static void
+cleanup_undefined_types ()
+{
+ struct type **type, *ntype;
+ struct symbol *sym;
+
+ for (type = undef_types; type < undef_types + undef_types_length; type++)
+ {
+ struct type *ntype = 0;
+ /* Reasonable test to see if it's been defined since. */
+ if (TYPE_NFIELDS (*type) == 0)
+ {
+ struct pending *ppt;
+ int i;
+ /* Name of the type, without "struct" or "union" */
+ char *typename = TYPE_NAME (*type);
+
+ if (!strncmp (typename, "struct ", 7))
+ typename += 7;
+ if (!strncmp (typename, "union ", 6))
+ typename += 6;
+
+ for (ppt = file_symbols; ppt; ppt = ppt->next)
+ for (i = 0; i < ppt->nsyms; i++)
+ {
+ struct symbol *sym = ppt->symbol[i];
+
+ if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+ && (TYPE_CODE (SYMBOL_TYPE (sym)) ==
+ TYPE_CODE (*type))
+ && !strcmp (SYMBOL_NAME (sym), typename))
+ bcopy (SYMBOL_TYPE (sym), *type, sizeof (struct type));
+ }
+ }
+ else
+ /* It has been defined; don't mark it as a stub. */
+ TYPE_FLAGS (*type) &= ~TYPE_FLAG_STUB;
+ }
+ undef_types_length = 0;
+}
+
+
+
+/* Read a dbx type reference or definition;
+ return the type that is meant.
+ This can be just a number, in which case it references
+ a type already defined and placed in type_vector.
+ Or the number can be followed by an =, in which case
+ it means to define a new type according to the text that
+ follows the =. */
+
+static
+struct type *
+read_type (pp)
+ register char **pp;
+{
+ register struct type *type = 0;
+ register int n;
+ struct type *type1;
+ int typenums[2];
+ int xtypenums[2];
+ char *tmpc;
+
+ /* Read type number if present. The type number may be omitted.
+ for instance in a two-dimensional array declared with type
+ "ar1;1;10;ar1;1;10;4". */
+ if ((**pp >= '0' && **pp <= '9')
+ || **pp == '(')
+ {
+ read_type_number (pp, typenums);
+
+ /* Detect random reference to type not yet defined.
+ Allocate a type object but leave it zeroed. */
+ if (**pp != '=')
+ return dbx_alloc_type (typenums);
+
+ *pp += 2;
+ }
+ else
+ {
+ /* 'typenums=' not present, type is anonymous. Read and return
+ the definition, but don't put it in the type vector. */
+ typenums[0] = typenums[1] = -1;
+ *pp += 1;
+ }
+
+ switch ((*pp)[-1])
+ {
+ case 'x':
+ {
+ enum type_code code;
+
+ /* Used to index through file_symbols. */
+ struct pending *ppt;
+ int i;
+
+ /* Name including "struct", etc. */
+ char *type_name;
+
+ /* Name without "struct", etc. */
+ char *type_name_only;
+
+ {
+ char *prefix;
+ char *from, *to;
+
+ /* Set the type code according to the following letter. */
+ switch ((*pp)[0])
+ {
+ case 's':
+ code = TYPE_CODE_STRUCT;
+ prefix = "struct ";
+ break;
+ case 'u':
+ code = TYPE_CODE_UNION;
+ prefix = "union ";
+ break;
+ case 'e':
+ code = TYPE_CODE_ENUM;
+ prefix = "enum ";
+ break;
+ default:
+ error ("Bad type cross reference at symnum: %d.", symnum);
+ }
+
+ to = type_name = (char *)
+ obstack_alloc (symbol_obstack,
+ (strlen (prefix) +
+ ((char *) index (*pp, ':') - (*pp)) + 1));
+
+ /* Copy the prefix. */
+ from = prefix;
+ while (*to++ = *from++)
+ ;
+ to--;
+
+ type_name_only = to;
+
+ /* Copy the name. */
+ from = *pp + 1;
+ while ((*to++ = *from++) != ':')
+ ;
+ *--to = '\0';
+
+ /* Set the pointer ahead of the name which we just read. */
+ *pp = from;
+
+#if 0
+ /* The following hack is clearly wrong, because it doesn't
+ check whether we are in a baseclass. I tried to reproduce
+ the case that it is trying to fix, but I couldn't get
+ g++ to put out a cross reference to a basetype. Perhaps
+ it doesn't do it anymore. */
+ /* Note: for C++, the cross reference may be to a base type which
+ has not yet been seen. In this case, we skip to the comma,
+ which will mark the end of the base class name. (The ':'
+ at the end of the base class name will be skipped as well.)
+ But sometimes (ie. when the cross ref is the last thing on
+ the line) there will be no ','. */
+ from = (char *) index (*pp, ',');
+ if (from)
+ *pp = from;
+#endif /* 0 */
+ }
+
+ /* Now check to see whether the type has already been declared. */
+ /* This is necessary at least in the case where the
+ program says something like
+ struct foo bar[5];
+ The compiler puts out a cross-reference; we better find
+ set the length of the structure correctly so we can
+ set the length of the array. */
+ for (ppt = file_symbols; ppt; ppt = ppt->next)
+ for (i = 0; i < ppt->nsyms; i++)
+ {
+ struct symbol *sym = ppt->symbol[i];
+
+ if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+ && (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
+ && !strcmp (SYMBOL_NAME (sym), type_name_only))
+ {
+ obstack_free (symbol_obstack, type_name);
+ type = SYMBOL_TYPE (sym);
+ return type;
+ }
+ }
+
+ /* Didn't find the type to which this refers, so we must
+ be dealing with a forward reference. Allocate a type
+ structure for it, and keep track of it so we can
+ fill in the rest of the fields when we get the full
+ type. */
+ type = dbx_alloc_type (typenums);
+ TYPE_CODE (type) = code;
+ TYPE_NAME (type) = type_name;
+
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+
+ add_undefined_type (type);
+ return type;
+ }
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '(':
+ (*pp)--;
+ read_type_number (pp, xtypenums);
+ type = *dbx_lookup_type (xtypenums);
+ if (type == 0)
+ type = builtin_type_void;
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case '*':
+ type1 = read_type (pp);
+ if (TYPE_POINTER_TYPE (type1))
+ {
+ type = TYPE_POINTER_TYPE (type1);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ }
+ else
+ {
+ type = dbx_alloc_type (typenums);
+ smash_to_pointer_type (type, type1);
+ }
+ break;
+
+ case '@':
+ {
+ struct type *domain = read_type (pp);
+ char c;
+ struct type *memtype;
+
+ if (*(*pp)++ != ',')
+ error ("invalid member type data format, at symtab pos %d.",
+ symnum);
+
+ memtype = read_type (pp);
+ type = dbx_alloc_type (typenums);
+ smash_to_member_type (type, domain, memtype);
+ }
+ break;
+
+ case '#':
+ {
+ struct type *domain = read_type (pp);
+ char c;
+ struct type *return_type;
+ struct type **args;
+
+ if (*(*pp)++ != ',')
+ error ("invalid member type data format, at symtab pos %d.",
+ symnum);
+
+ return_type = read_type (pp);
+ args = read_args (pp, ';');
+ type = dbx_alloc_type (typenums);
+ smash_to_method_type (type, domain, return_type, args);
+ }
+ break;
+
+ case '&':
+ type1 = read_type (pp);
+ if (TYPE_REFERENCE_TYPE (type1))
+ {
+ type = TYPE_REFERENCE_TYPE (type1);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ }
+ else
+ {
+ type = dbx_alloc_type (typenums);
+ smash_to_reference_type (type, type1);
+ }
+ break;
+
+ case 'f':
+ type1 = read_type (pp);
+ if (TYPE_FUNCTION_TYPE (type1))
+ {
+ type = TYPE_FUNCTION_TYPE (type1);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ }
+ else
+ {
+ type = dbx_alloc_type (typenums);
+ smash_to_function_type (type, type1);
+ }
+ break;
+
+ case 'r':
+ type = read_range_type (pp, typenums);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 'e':
+ type = dbx_alloc_type (typenums);
+ type = read_enum_type (pp, type);
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 's':
+ type = dbx_alloc_type (typenums);
+ type = read_struct_type (pp, type);
+ break;
+
+ case 'u':
+ type = dbx_alloc_type (typenums);
+ type = read_struct_type (pp, type);
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ break;
+
+ case 'a':
+ if (*(*pp)++ != 'r')
+ error ("Invalid symbol data: unrecognized type-code `a%c' %s %d.",
+ (*pp)[-1], "at symtab position", symnum);
+
+ type = dbx_alloc_type (typenums);
+ type = read_array_type (pp, type);
+ break;
+
+ default:
+ error ("Invalid symbol data: unrecognized type-code `%c' at symtab pos %d.",
+ (*pp)[-1], symnum);
+ }
+
+ if (type == 0)
+ abort ();
+
+#if 0
+ /* If this is an overriding temporary alteration for a header file's
+ contents, and this type number is unknown in the global definition,
+ put this type into the global definition at this type number. */
+ if (header_file_prev_index >= 0)
+ {
+ register struct type **tp
+ = explicit_lookup_type (header_file_prev_index, typenums[1]);
+ if (*tp == 0)
+ *tp = type;
+ }
+#endif
+ return type;
+}
+
+/* This page contains subroutines of read_type. */
+
+/* Read the description of a structure (or union type)
+ and return an object describing the type. */
+
+static struct type *
+read_struct_type (pp, type)
+ char **pp;
+ register struct type *type;
+{
+ struct nextfield
+ {
+ struct nextfield *next;
+ int visibility;
+ struct field field;
+ };
+
+ struct next_fnfield
+ {
+ struct next_fnfield *next;
+ int visibility;
+ struct fn_field fn_field;
+ };
+
+ struct next_fnfieldlist
+ {
+ struct next_fnfieldlist *next;
+ struct fn_fieldlist fn_fieldlist;
+ };
+
+ register struct nextfield *list = 0;
+ struct nextfield *new;
+ int totalsize;
+ char *name;
+ register char *p;
+ int nfields = 0;
+ register int n;
+
+ register struct next_fnfieldlist *mainlist = 0;
+ int nfn_fields = 0;
+ int read_possible_virtual_info = 0;
+
+ if (TYPE_MAIN_VARIANT (type) == 0)
+ {
+ TYPE_MAIN_VARIANT (type) = type;
+ }
+
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+ /* First comes the total size in bytes. */
+
+ TYPE_LENGTH (type) = read_number (pp, 0);
+
+ /* C++: Now, if the class is a derived class, then the next character
+ will be a '!', followed by the number of base classes derived from.
+ Each element in the list contains visibility information,
+ the offset of this base class in the derived structure,
+ and then the base type. */
+ if (**pp == '!')
+ {
+ int i, n_baseclasses, offset;
+ struct type **baseclass_vec;
+ struct type *baseclass;
+ int via_public;
+
+ /* Nonzero if it is a virtual baseclass, i.e.,
+
+ struct A{};
+ struct B{};
+ struct C : public B, public virtual A {};
+
+ B is a baseclass of C; A is a virtual baseclass for C. This is a C++
+ 2.0 language feature. */
+ int via_virtual;
+
+ *pp += 1;
+
+ n_baseclasses = read_number (pp, ',');
+ baseclass_vec = (struct type **)
+ obstack_alloc (symbol_obstack,
+ (n_baseclasses) * sizeof (struct type **)) - 1;
+
+ for (i = 1; i <= n_baseclasses; i++)
+ {
+ if (**pp == '\\')
+ *pp = next_symbol_text ();
+
+ switch (*(*pp)++)
+ {
+ case '0':
+ via_virtual = 0;
+ break;
+ case '1':
+ via_virtual = 1;
+ break;
+ default:
+ error ("Invalid symbol data: bad visibility format at symtab pos %d",
+ symnum);
+ }
+
+ switch (*(*pp)++)
+ {
+ case '0':
+ via_public = 0;
+ break;
+ case '2':
+ via_public = 1;
+ break;
+ default:
+ error ("Invalid symbol data: bad visibility format at symtab pos %d.",
+ symnum);
+ }
+
+ /* Offset of the portion of the object corresponding to
+ this baseclass. Always zero in the absence of
+ multiple inheritance. */
+ offset = read_number (pp, ',');
+ baseclass = read_type (pp);
+ *pp += 1; /* skip trailing ';' */
+
+ if (offset != 0)
+ {
+ static int error_printed = 0;
+
+ if (!error_printed)
+ {
+ fprintf (stderr,
+"\nWarning: GDB has limited understanding of multiple inheritance...");
+ error_printed = 1;
+ }
+ offset = 0;
+ }
+
+ baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public);
+
+ /* Since lookup_basetype_type can copy the type,
+ it might copy a stub type (complete with stub flag).
+ If so, we need to add it to the list of undefined types
+ to clean up later. Even if lookup_basetype_type
+ didn't copy the type, adding it to the undefined list
+ will not do any harm. */
+ if (TYPE_FLAGS(baseclass_vec[i]) & TYPE_FLAG_STUB)
+ add_undefined_type (baseclass_vec[i]);
+
+ /* Make this baseclass visible for structure-printing purposes. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+ list->field.type = baseclass_vec[i];
+ list->field.name = TYPE_NAME (baseclass_vec[i]);
+ list->field.bitpos = offset;
+ list->field.bitsize = 0; /* this should be an unpacked field! */
+ nfields++;
+ }
+ TYPE_N_BASECLASSES (type) = n_baseclasses;
+ TYPE_BASECLASSES (type) = baseclass_vec;
+ }
+
+ /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one.
+ At the end, we see a semicolon instead of a field.
+
+ In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
+ a static field.
+
+ The `?' is a placeholder for one of '+' (public visibility),
+ '0' (protected visibility), and '-' (private visibility). */
+
+ /* We better set p right now, in case there are no fields at all... */
+ p = *pp;
+
+ while (**pp != ';')
+ {
+ int visibility;
+
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if (**pp == '\\') *pp = next_symbol_text ();
+
+ /* Get space to record the next field's data. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ /* Get the field name. */
+ p = *pp;
+ while (*p != ':') p++;
+ list->field.name = obsavestring (*pp, p - *pp);
+
+ /* C++: Check to see if we have hit the methods yet. */
+ if (p[1] == ':')
+ break;
+
+ *pp = p + 1;
+
+ /* This means we have a visibility for a field coming. */
+ if (**pp == '/')
+ {
+ switch (*++*pp)
+ {
+ case '0':
+ visibility = 0;
+ *pp += 1;
+ break;
+
+ case '1':
+ visibility = 1;
+ *pp += 1;
+ break;
+
+ case '2':
+ visibility = 2;
+ *pp += 1;
+ break;
+ }
+ }
+ /* else normal dbx-style format. */
+
+ list->field.type = read_type (pp);
+ if (**pp == ':')
+ {
+ list->field.bitpos = (long)-1;
+ p = ++(*pp);
+ while (*p != ';') p++;
+ list->field.bitsize = (long) savestring (*pp, p - *pp);
+ *pp = p + 1;
+ nfields++;
+ continue;
+ }
+ else if (**pp != ',')
+ error ("Invalid symbol data: bad structure-type format at symtab pos %d.",
+ symnum);
+ (*pp)++; /* Skip the comma. */
+ list->field.bitpos = read_number (pp, ',');
+ list->field.bitsize = read_number (pp, ';');
+
+#if 0
+ /* This is wrong because this is identical to the symbols
+ produced for GCC 0-size arrays. For example:
+ typedef union {
+ int num;
+ char str[0];
+ } foo;
+ The code which dumped core in such circumstances should be
+ fixed not to dump core. */
+
+ /* g++ -g0 can put out bitpos & bitsize zero for a static
+ field. This does not give us any way of getting its
+ class, so we can't know its name. But we can just
+ ignore the field so we don't dump core and other nasty
+ stuff. */
+ if (list->field.bitpos == 0
+ && list->field.bitsize == 0)
+ {
+ /* Have we given the warning yet? */
+ static int warning_given = 0;
+
+ /* Only give the warning once, no matter how many class
+ variables there are. */
+ if (!warning_given)
+ {
+ warning_given = 1;
+ fprintf_filtered (stderr, "\n\
+Warning: DBX-style class variable debugging information encountered.\n\
+You seem to have compiled your program with \
+\"g++ -g0\" instead of \"g++ -g\".\n\
+Therefore GDB will not know about your class variables.\n\
+");
+ }
+
+ /* Ignore this field. */
+ list = list->next;
+ }
+ else
+#endif /* 0 */
+ {
+ /* Detect an unpacked field and mark it as such.
+ dbx gives a bit size for all fields.
+ Note that forward refs cannot be packed,
+ and treat enums as if they had the width of ints. */
+ if (TYPE_CODE (list->field.type) != TYPE_CODE_INT
+ && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM)
+ list->field.bitsize = 0;
+ if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type)
+ || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM
+ && (list->field.bitsize
+ == 8 * TYPE_LENGTH (builtin_type_int))
+ )
+ )
+ &&
+ list->field.bitpos % 8 == 0)
+ list->field.bitsize = 0;
+ nfields++;
+ }
+ }
+
+ /* Now come the method fields, as NAME::methods
+ where each method is of the form TYPENUM,ARGS,...:PHYSNAME;
+ At the end, we see a semicolon instead of a field.
+
+ For the case of overloaded operators, the format is
+ OPERATOR::*.methods, where OPERATOR is the string "operator",
+ `*' holds the place for an operator name (such as `+=')
+ and `.' marks the end of the operator name. */
+ if (p[1] == ':')
+ {
+ /* Now, read in the methods. To simplify matters, we
+ "unread" the name that has been read, so that we can
+ start from the top. */
+
+ p = *pp;
+
+ /* chill the list of fields: the last entry (at the head)
+ is a partially constructed entry which we now scrub. */
+ list = list->next;
+
+ /* For each list of method lists... */
+ do
+ {
+ int i;
+ struct next_fnfield *sublist = 0;
+ struct fn_field *fn_fields = 0;
+ int length = 0;
+ struct next_fnfieldlist *new_mainlist =
+ (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist));
+
+ /* read in the name. */
+ while (*p != ':') p++;
+ if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$')
+ {
+ static char opname[] = "operator";
+ char *o = opname + strlen(opname);
+
+ /* Skip past '::'. */
+ p += 2;
+ while (*p != '.')
+ *o++ = *p++;
+ new_mainlist->fn_fieldlist.name = savestring (opname, o - opname);
+ /* Skip past '.' */
+ *pp = p + 1;
+ }
+ else
+ {
+ i = 0;
+ new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp);
+ /* Skip past '::'. */
+ *pp = p + 2;
+ }
+
+ do
+ {
+ struct next_fnfield *new_sublist =
+ (struct next_fnfield *)alloca (sizeof (struct next_fnfield));
+
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if (**pp == '\\') *pp = next_symbol_text ();
+
+ new_sublist->fn_field.type = read_type (pp);
+ if (**pp != ':')
+ error ("invalid symtab info for method at symbol number %d.",
+ symnum);
+ *pp += 1;
+ new_sublist->fn_field.args =
+ TYPE_ARG_TYPES (new_sublist->fn_field.type);
+ p = *pp;
+ while (*p != ';') p++;
+ new_sublist->fn_field.physname = savestring (*pp, p - *pp);
+ *pp = p + 1;
+ new_sublist->visibility = *(*pp)++ - '0';
+ if (**pp == '\\') *pp = next_symbol_text ();
+
+ switch (*(*pp)++)
+ {
+ case '*':
+ /* virtual member function, followed by index. */
+ new_sublist->fn_field.voffset = read_number (pp, ';') + 1;
+ break;
+ case '?':
+ /* static member function. */
+ new_sublist->fn_field.voffset = 1;
+ break;
+ default:
+ /* **pp == '.'. */
+ /* normal member function. */
+ new_sublist->fn_field.voffset = 0;
+ break;
+ }
+
+ new_sublist->next = sublist;
+ sublist = new_sublist;
+ length++;
+ }
+ while (**pp != ';');
+
+ *pp += 1;
+
+ new_mainlist->fn_fieldlist.fn_fields =
+ (struct fn_field *) obstack_alloc (symbol_obstack,
+ sizeof (struct fn_field) * length);
+ TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) =
+ (int *) obstack_alloc (symbol_obstack,
+ sizeof (int) * (1 + (length >> 5)));
+
+ TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) =
+ (int *) obstack_alloc (symbol_obstack,
+ sizeof (int) * (1 + (length >> 5)));
+
+ for (i = length; sublist; sublist = sublist->next)
+ {
+ new_mainlist->fn_fieldlist.fn_fields[--i] = sublist->fn_field;
+ if (sublist->visibility == 0)
+ B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i);
+ else if (sublist->visibility == 1)
+ B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i);
+ }
+
+ new_mainlist->fn_fieldlist.length = length;
+ new_mainlist->next = mainlist;
+ mainlist = new_mainlist;
+ nfn_fields++;
+ }
+ while (**pp != ';');
+ }
+
+ *pp += 1;
+
+ /* Now create the vector of fields, and record how big it is. */
+
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack,
+ sizeof (struct field) * nfields);
+ TYPE_FIELD_PRIVATE_BITS (type) =
+ (int *) obstack_alloc (symbol_obstack,
+ sizeof (int) * (1 + (nfields >> 5)));
+ TYPE_FIELD_PROTECTED_BITS (type) =
+ (int *) obstack_alloc (symbol_obstack,
+ sizeof (int) * (1 + (nfields >> 5)));
+
+ TYPE_NFN_FIELDS (type) = nfn_fields;
+ TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields;
+
+ {
+ int i;
+ for (i = 1; i <= TYPE_N_BASECLASSES (type); ++i)
+ TYPE_NFN_FIELDS_TOTAL (type) +=
+ TYPE_NFN_FIELDS_TOTAL (TYPE_BASECLASS (type, i));
+ }
+
+ TYPE_FN_FIELDLISTS (type) =
+ (struct fn_fieldlist *) obstack_alloc (symbol_obstack,
+ sizeof (struct fn_fieldlist) * nfn_fields);
+
+ /* Copy the saved-up fields into the field vector. */
+
+ for (n = nfields; list; list = list->next)
+ {
+ TYPE_FIELD (type, --n) = list->field;
+ if (list->visibility == 0)
+ SET_TYPE_FIELD_PRIVATE (type, n);
+ else if (list->visibility == 1)
+ SET_TYPE_FIELD_PROTECTED (type, n);
+ }
+
+ for (n = nfn_fields; mainlist; mainlist = mainlist->next)
+ TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist;
+
+ if (**pp == '~')
+ {
+ *pp += 1;
+
+ if (**pp == '=')
+ {
+ TYPE_FLAGS (type)
+ |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR;
+ *pp += 1;
+ }
+ else if (**pp == '+')
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR;
+ *pp += 1;
+ }
+ else if (**pp == '-')
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR;
+ *pp += 1;
+ }
+
+ /* Read either a '%' or the final ';'. */
+ if (*(*pp)++ == '%')
+ {
+ /* Now we must record the virtual function table pointer's
+ field information. */
+
+ struct type *t;
+ int i;
+
+ t = read_type (pp);
+ p = (*pp)++;
+ while (*p != ';') p++;
+ TYPE_VPTR_BASETYPE (type) = t;
+ if (type == t)
+ {
+ if (TYPE_FIELD_NAME (t, 0) == 0)
+ TYPE_VPTR_FIELDNO (type) = i = 0;
+ else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i)
+ if (! strncmp (TYPE_FIELD_NAME (t, i), *pp,
+ strlen (TYPE_FIELD_NAME (t, i))))
+ {
+ TYPE_VPTR_FIELDNO (type) = i;
+ break;
+ }
+ if (i < 0)
+ error ("virtual function table field not found");
+ }
+ else
+ TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, 1));
+ *pp = p + 1;
+ }
+ else
+ {
+ TYPE_VPTR_BASETYPE (type) = 0;
+ TYPE_VPTR_FIELDNO (type) = -1;
+ }
+ }
+ else
+ {
+ TYPE_VPTR_BASETYPE (type) = 0;
+ TYPE_VPTR_FIELDNO (type) = -1;
+ }
+
+ return type;
+}
+
+/* Read a definition of an array type,
+ and create and return a suitable type object.
+ Also creates a range type which represents the bounds of that
+ array. */
+static struct type *
+read_array_type (pp, type)
+ register char **pp;
+ register struct type *type;
+{
+ struct type *index_type, *element_type, *range_type;
+ int lower, upper;
+ int adjustable = 0;
+
+ /* Format of an array type:
+ "ar<index type>;lower;upper;<array_contents_type>". Put code in
+ to handle this.
+
+ Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+ for these, produce a type like float[][]. */
+
+ index_type = read_type (pp);
+ if (*(*pp)++ != ';')
+ error ("Invalid symbol data; improper format of array type decl.");
+
+ if (!(**pp >= '0' && **pp <= '9'))
+ {
+ *pp += 1;
+ adjustable = 1;
+ }
+ lower = read_number (pp, ';');
+
+ if (!(**pp >= '0' && **pp <= '9'))
+ {
+ *pp += 1;
+ adjustable = 1;
+ }
+ upper = read_number (pp, ';');
+
+ element_type = read_type (pp);
+
+ if (adjustable)
+ {
+ lower = 0;
+ upper = -1;
+ }
+
+ {
+ /* Create range type. */
+ range_type = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+ TYPE_CODE (range_type) = TYPE_CODE_RANGE;
+ TYPE_TARGET_TYPE (range_type) = index_type;
+
+ /* This should never be needed. */
+ TYPE_LENGTH (range_type) = sizeof (int);
+
+ TYPE_NFIELDS (range_type) = 2;
+ TYPE_FIELDS (range_type) =
+ (struct field *) obstack_alloc (symbol_obstack,
+ 2 * sizeof (struct field));
+ TYPE_FIELD_BITPOS (range_type, 0) = lower;
+ TYPE_FIELD_BITPOS (range_type, 1) = upper;
+ }
+
+ TYPE_CODE (type) = TYPE_CODE_ARRAY;
+ TYPE_TARGET_TYPE (type) = element_type;
+ TYPE_LENGTH (type) = (upper - lower + 1) * TYPE_LENGTH (element_type);
+ TYPE_NFIELDS (type) = 1;
+ TYPE_FIELDS (type) =
+ (struct field *) obstack_alloc (symbol_obstack,
+ sizeof (struct field));
+ TYPE_FIELD_TYPE (type, 0) = range_type;
+
+ return type;
+}
+
+
+/* Read a definition of an enumeration type,
+ and create and return a suitable type object.
+ Also defines the symbols that represent the values of the type. */
+
+static struct type *
+read_enum_type (pp, type)
+ register char **pp;
+ register struct type *type;
+{
+ register char *p;
+ char *name;
+ register long n;
+ register struct symbol *sym;
+ int nsyms = 0;
+ struct pending **symlist;
+ struct pending *osyms, *syms;
+ int o_nsyms;
+
+ if (within_function)
+ symlist = &local_symbols;
+ else
+ symlist = &file_symbols;
+ osyms = *symlist;
+ o_nsyms = osyms ? osyms->nsyms : 0;
+
+ /* Read the value-names and their values.
+ The input syntax is NAME:VALUE,NAME:VALUE, and so on.
+ A semicolon or comman instead of a NAME means the end. */
+ while (**pp && **pp != ';' && **pp != ',')
+ {
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if (**pp == '\\') *pp = next_symbol_text ();
+
+ p = *pp;
+ while (*p != ':') p++;
+ name = obsavestring (*pp, p - *pp);
+ *pp = p + 1;
+ n = read_number (pp, ',');
+
+ sym = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+ bzero (sym, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = name;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE (sym) = n;
+ add_symbol_to_list (sym, symlist);
+ nsyms++;
+ }
+
+ if (**pp == ';')
+ (*pp)++; /* Skip the semicolon. */
+
+ /* Now fill in the fields of the type-structure. */
+
+ TYPE_LENGTH (type) = sizeof (int);
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms);
+
+ /* Find the symbols for the values and put them into the type.
+ The symbols can be found in the symlist that we put them on
+ to cause them to be defined. osyms contains the old value
+ of that symlist; everything up to there was defined by us. */
+ /* Note that we preserve the order of the enum constants, so
+ that in something like "enum {FOO, LAST_THING=FOO}" we print
+ FOO, not LAST_THING. */
+
+ for (syms = *symlist, n = 0; syms; syms = syms->next)
+ {
+ int j = 0;
+ if (syms == osyms)
+ j = o_nsyms;
+ for (; j < syms->nsyms; j++)
+ {
+ struct symbol *sym = syms->symbol[j];
+ SYMBOL_TYPE (sym) = type;
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (sym);
+ TYPE_FIELD_VALUE (type, n) = 0;
+ TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (sym);
+ TYPE_FIELD_BITSIZE (type, n++) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+ return type;
+}
+
+#define MAX_OF_TYPE(t) ((1 << (sizeof (t) - 1)) - 1)
+#define MIN_OF_TYPE(t) (-(1 << (sizeof (t) - 1)))
+
+static struct type *
+read_range_type (pp, typenums)
+ char **pp;
+ int typenums[2];
+{
+ int rangenums[2];
+ long n2, n3;
+ int n2bits, n3bits;
+ int self_subrange;
+ struct type *result_type;
+ struct type *index_type;
+
+ /* First comes a type we are a subrange of.
+ In C it is usually 0, 1 or the type being defined. */
+ read_type_number (pp, rangenums);
+ self_subrange = (rangenums[0] == typenums[0] &&
+ rangenums[1] == typenums[1]);
+
+ /* A semicolon should now follow; skip it. */
+ if (**pp == ';')
+ (*pp)++;
+
+ /* The remaining two operands are usually lower and upper bounds
+ of the range. But in some special cases they mean something else. */
+ read_huge_number (pp, ';', &n2, &n2bits);
+ read_huge_number (pp, ';', &n3, &n3bits);
+
+ if (n2bits == -1 || n3bits == -1)
+ error ("Unrecognized type range %s.", pp);
+
+ if (n2bits != 0 || n3bits != 0)
+#ifdef LONG_LONG
+ {
+ char got_signed = 0;
+ char got_unsigned = 0;
+ /* Number of bits in the type. */
+ int nbits;
+
+ /* Range from 0 to <large number> is an unsigned large integral type. */
+ if ((n2bits == 0 && n2 == 0) && n3bits != 0)
+ {
+ got_unsigned = 1;
+ nbits = n3bits;
+ }
+ /* Range fro <large number> to <large number>-1 is a large signed
+ integral type. */
+ else if (n2bits != 0 && n3bits != 0 && n2bits == n3bits + 1)
+ {
+ got_signed = 1;
+ nbits = n2bits;
+ }
+
+ /* Check for "long long". */
+ if (got_signed && nbits == CHAR_BIT * sizeof (long long))
+ return builtin_type_long_long;
+ if (got_unsigned && nbits == CHAR_BIT * sizeof (long long))
+ return builtin_type_unsigned_long_long;
+
+ error ("Large type isn't a long long.");
+ }
+#else /* LONG_LONG */
+ error ("Type long long not supported on this machine.");
+#endif
+
+ /* A type defined as a subrange of itself, with bounds both 0, is void. */
+ if (self_subrange && n2 == 0 && n3 == 0)
+ return builtin_type_void;
+
+ /* If n3 is zero and n2 is not, we want a floating type,
+ and n2 is the width in bytes.
+
+ Fortran programs appear to use this for complex types also,
+ and they give no way to distinguish between double and single-complex!
+ We don't have complex types, so we would lose on all fortran files!
+ So return type `double' for all of those. It won't work right
+ for the complex values, but at least it makes the file loadable. */
+
+ if (n3 == 0 && n2 > 0)
+ {
+ if (n2 == sizeof (float))
+ return builtin_type_float;
+ return builtin_type_double;
+ }
+
+ /* If the upper bound is -1, it must really be an unsigned int. */
+
+ else if (n2 == 0 && n3 == -1)
+ {
+ if (sizeof (int) == sizeof (long))
+ return builtin_type_unsigned_int;
+ else
+ return builtin_type_unsigned_long;
+ }
+
+ /* Special case: char is defined (Who knows why) as a subrange of
+ itself with range 0-127. */
+ else if (self_subrange && n2 == 0 && n3 == 127)
+ return builtin_type_char;
+
+ /* Assumptions made here: Subrange of self is equivalent to subrange
+ of int. */
+ else if (n2 == 0
+ && (self_subrange ||
+ *dbx_lookup_type (rangenums) == builtin_type_int))
+ {
+ /* an unsigned type */
+ if (n3 == UINT_MAX)
+ return builtin_type_unsigned_int;
+ if (n3 == ULONG_MAX)
+ return builtin_type_unsigned_long;
+ if (n3 == USHRT_MAX)
+ return builtin_type_unsigned_short;
+ if (n3 == UCHAR_MAX)
+ return builtin_type_unsigned_char;
+ }
+#ifdef LONG_LONG
+ else if (n3 == 0 && n2 == -sizeof (long long))
+ return builtin_type_long_long;
+#endif
+ else if (n2 == -n3 -1)
+ {
+ /* a signed type */
+ if (n3 == INT_MAX)
+ return builtin_type_int;
+ if (n3 == LONG_MAX)
+ return builtin_type_long;
+ if (n3 == SHRT_MAX)
+ return builtin_type_short;
+ if (n3 == CHAR_MAX)
+ return builtin_type_char;
+ }
+
+ /* We have a real range type on our hands. Allocate space and
+ return a real pointer. */
+
+ /* At this point I don't have the faintest idea how to deal with
+ a self_subrange type; I'm going to assume that this is used
+ as an idiom, and that all of them are special cases. So . . . */
+ if (self_subrange)
+ error ("Type defined as subrange of itself: %s.", pp);
+
+ result_type = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+ bzero (result_type, sizeof (struct type));
+
+ TYPE_TARGET_TYPE (result_type) = (self_subrange ?
+ builtin_type_int :
+ *dbx_lookup_type(rangenums));
+
+ /* We have to figure out how many bytes it takes to hold this
+ range type. I'm going to assume that anything that is pushing
+ the bounds of a long was taken care of above. */
+ if (n2 >= MIN_OF_TYPE(char) && n3 <= MAX_OF_TYPE(char))
+ TYPE_LENGTH (result_type) = 1;
+ else if (n2 >= MIN_OF_TYPE(short) && n3 <= MAX_OF_TYPE(short))
+ TYPE_LENGTH (result_type) = sizeof (short);
+ else if (n2 >= MIN_OF_TYPE(int) && n3 <= MAX_OF_TYPE(int))
+ TYPE_LENGTH (result_type) = sizeof (int);
+ else if (n2 >= MIN_OF_TYPE(long) && n3 <= MAX_OF_TYPE(long))
+ TYPE_LENGTH (result_type) = sizeof (long);
+ else
+ error ("Ranged type doesn't fit within known sizes.");
+
+ TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type));
+ TYPE_CODE (result_type) = TYPE_CODE_RANGE;
+ TYPE_NFIELDS (result_type) = 2;
+ TYPE_FIELDS (result_type) =
+ (struct field *) obstack_alloc (symbol_obstack,
+ 2 * sizeof (struct field));
+ bzero (TYPE_FIELDS (result_type), 2 * sizeof (struct field));
+ TYPE_FIELD_BITPOS (result_type, 0) = n2;
+ TYPE_FIELD_BITPOS (result_type, 1) = n3;
+
+ return result_type;
+}
+
+/* Read a number from the string pointed to by *PP.
+ The value of *PP is advanced over the number.
+ If END is nonzero, the character that ends the
+ number must match END, or an error happens;
+ and that character is skipped if it does match.
+ If END is zero, *PP is left pointing to that character. */
+
+static long
+read_number (pp, end)
+ char **pp;
+ int end;
+{
+ register char *p = *pp;
+ register long n = 0;
+ register int c;
+ int sign = 1;
+
+ /* Handle an optional leading minus sign. */
+
+ if (*p == '-')
+ {
+ sign = -1;
+ p++;
+ }
+
+ /* Read the digits, as far as they go. */
+
+ while ((c = *p++) >= '0' && c <= '9')
+ {
+ n *= 10;
+ n += c - '0';
+ }
+ if (end)
+ {
+ if (c && c != end)
+ error ("Invalid symbol data: invalid character \\%03o at symbol pos %d.", c, symnum);
+ }
+ else
+ --p;
+
+ *pp = p;
+ return n * sign;
+}
+
+static void
+read_huge_number (pp, end, valu, bits)
+ char **pp;
+ int end;
+ long *valu;
+ int *bits;
+{
+ char *p = *pp;
+ int sign = 1;
+ long n = 0;
+ int radix = 10;
+ char overflow = 0;
+ int nbits = 0;
+ int c;
+ long upper_limit;
+
+ /* Handle an optional leading minus sign. */
+
+ if (*p == '-')
+ {
+ sign = -1;
+ p++;
+ }
+
+ /* Leading zero means octal. GCC uses this to output values larger
+ than an int (because that would be hard in decimal). */
+ if (*p == '0')
+ {
+ radix = 8;
+ p++;
+ }
+
+ upper_limit = LONG_MAX / radix;
+ while ((c = *p++) >= '0' && c <= '9')
+ {
+ if (n <= upper_limit)
+ {
+ n *= radix;
+ n += c - '0';
+ }
+ else
+ overflow = 1;
+
+ /* This depends on large values being output in octal, which is
+ what GCC does. */
+ if (radix == 8)
+ {
+ if (nbits == 0)
+ {
+ if (c == '0')
+ /* Ignore leading zeroes. */
+ ;
+ else if (c == '1')
+ nbits = 1;
+ else if (c == '2' || c == '3')
+ nbits = 2;
+ else
+ nbits = 3;
+ }
+ else
+ nbits += 3;
+ }
+ }
+ if (end)
+ {
+ if (c && c != end)
+ {
+ if (bits != NULL)
+ *bits = -1;
+ return;
+ }
+ }
+ else
+ --p;
+
+ *pp = p;
+ if (overflow)
+ {
+ if (nbits == 0)
+ {
+ /* Large decimal constants are an error (because it is hard to
+ count how many bits are in them). */
+ if (bits != NULL)
+ *bits = -1;
+ return;
+ }
+
+ /* -0x7f is the same as 0x80. So deal with it by adding one to
+ the number of bits. */
+ if (sign == -1)
+ ++nbits;
+ if (bits)
+ *bits = nbits;
+ }
+ else
+ {
+ if (valu)
+ *valu = n * sign;
+ if (bits)
+ *bits = 0;
+ }
+}
+
+/* Read in an argument list. This is a list of types. It is terminated with
+ a ':', FYI. Return the list of types read in. */
+static struct type **
+read_args (pp, end)
+ char **pp;
+ int end;
+{
+ struct type *types[1024], **rval; /* allow for fns of 1023 parameters */
+ int n = 0;
+
+ while (**pp != end)
+ {
+ if (**pp != ',')
+ error ("Invalid argument list: no ',', at symtab pos %d", symnum);
+ *pp += 1;
+
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if (**pp == '\\')
+ *pp = next_symbol_text ();
+
+ types[n++] = read_type (pp);
+ }
+ *pp += 1; /* get past `end' (the ':' character) */
+
+ if (n == 1)
+ {
+ rval = (struct type **) xmalloc (2 * sizeof (struct type *));
+ }
+ else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID)
+ {
+ rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *));
+ bzero (rval + n, sizeof (struct type *));
+ }
+ else
+ {
+ rval = (struct type **) xmalloc (n * sizeof (struct type *));
+ }
+ bcopy (types, rval, n * sizeof (struct type *));
+ return rval;
+}
+
+/* This function is really horrible, but to avoid it, there would need
+ to be more filling in of forward references. THIS SHOULD BE MOVED OUT
+ OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE SHARED */
+int
+fill_in_vptr_fieldno (type)
+ struct type *type;
+{
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ TYPE_VPTR_FIELDNO (type) =
+ fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1));
+ return TYPE_VPTR_FIELDNO (type);
+}
+
+/* Copy a pending list, used to record the contents of a common
+ block for later fixup. BUG FIX by rde@topexpress.co.uk */
+static struct pending *
+copy_pending (beg, begi, end)
+ struct pending *beg, *end;
+ int begi;
+{
+ struct pending *new = 0;
+ struct pending *next;
+
+ /* rde note: `begi' is an offset in block `end', NOT `beg' */
+ for (next = beg; next != 0; next = next->next)
+ {
+ register int j;
+ for (j = next == end ? begi : 0; j < next->nsyms; j++)
+ add_symbol_to_list (next->symbol[j], &new);
+
+ if (next == end)
+ break;
+ }
+ return new;
+}
+
+/* Add a common block's start address to the offset of each symbol
+ declared to be in it (by being between a BCOMM/ECOMM pair that uses
+ the common block name). */
+
+static void
+fix_common_block (sym, value)
+ struct symbol *sym;
+ int value;
+{
+ struct pending *next = (struct pending *) SYMBOL_NAMESPACE (sym);
+ for ( ; next; next = next->next)
+ {
+ register int j;
+ for (j = next->nsyms - 1; j >= 0; j--)
+ SYMBOL_VALUE (next->symbol[j]) += value;
+ }
+}
+
+void
+_initialize_dbxread ()
+{
+ symfile = 0;
+ header_files = (struct header_file *) 0;
+ this_object_header_files = (int *) 0;
+
+ undef_types_allocated = 20;
+ undef_types_length = 0;
+ undef_types = (struct type **) xmalloc (undef_types_allocated *
+ sizeof (struct type *));
+
+ add_com ("symbol-file", class_files, symbol_file_command,
+ "Load symbol table (in dbx format) from executable file FILE.");
+
+ add_com ("add-file", class_files, add_file_command,
+ "Load the symbols from FILE, assuming its code is at TEXT_START.") ;
+}
+
+#endif /* READ_DBX_FORMAT */
diff --git a/gnu/usr.bin/kgdb/defs.h b/gnu/usr.bin/kgdb/defs.h
new file mode 100644
index 000000000000..de744fce78a6
--- /dev/null
+++ b/gnu/usr.bin/kgdb/defs.h
@@ -0,0 +1,122 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ *
+ * @(#)defs.h 6.3 (Berkeley) 5/8/91
+ */
+
+/* Basic definitions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define CORE_ADDR unsigned int
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+extern char *savestring ();
+extern char *concat ();
+extern char *xmalloc (), *xrealloc ();
+extern int parse_escape ();
+extern char *reg_names[];
+
+/* Various possibilities for alloca. */
+#ifdef sparc
+#include <alloca.h>
+#else
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+extern char *alloca ();
+#endif
+#endif
+
+extern int quit_flag;
+
+extern int immediate_quit;
+
+#define QUIT { if (quit_flag) quit (); }
+
+/* Notes on classes: class_alias is for alias commands which are not
+ abbreviations of the original command. */
+
+enum command_class
+{
+ no_class = -1, class_run = 0, class_vars, class_stack,
+ class_files, class_support, class_info, class_breakpoint,
+ class_alias, class_obscure, class_user,
+};
+
+/* the cleanup list records things that have to be undone
+ if an error happens (descriptors to be closed, memory to be freed, etc.)
+ Each link in the chain records a function to call and an
+ argument to give it.
+
+ Use make_cleanup to add an element to the cleanup chain.
+ Use do_cleanups to do all cleanup actions back to a given
+ point in the chain. Use discard_cleanups to remove cleanups
+ from the chain back to a given point, not doing them. */
+
+struct cleanup
+{
+ struct cleanup *next;
+ void (*function) ();
+ int arg;
+};
+
+extern void do_cleanups ();
+extern void discard_cleanups ();
+extern struct cleanup *make_cleanup ();
+extern struct cleanup *save_cleanups ();
+extern void restore_cleanups ();
+extern void free_current_contents ();
+extern void reinitialize_more_filter ();
+extern void fputs_filtered ();
+extern void fprintf_filtered ();
+extern void printf_filtered ();
+extern void print_spaces_filtered ();
+extern char *tilde_expand ();
+
+/* Structure for saved commands lines
+ (for breakpoints, defined commands, etc). */
+
+struct command_line
+{
+ struct command_line *next;
+ char *line;
+ int type; /* statement type */
+#define CL_END 0
+#define CL_NORMAL 1
+#define CL_WHILE 2
+#define CL_IF 3
+#define CL_EXITLOOP 4
+#define CL_NOP 5
+ struct command_line *body; /* body of loop for while, body of if */
+ struct command_line *elsebody; /* body of else part of if */
+};
+
+extern struct command_line *read_command_lines ();
+extern void do_command_lines();
+
+/* String containing the current directory (what getwd would return). */
+
+char *current_directory;
+
diff --git a/gnu/usr.bin/kgdb/environ.c b/gnu/usr.bin/kgdb/environ.c
new file mode 100644
index 000000000000..022016631331
--- /dev/null
+++ b/gnu/usr.bin/kgdb/environ.c
@@ -0,0 +1,185 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)environ.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* environ.c -- library for manipulating environments for GNU.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#include "environ.h"
+
+/* Return a new environment object. */
+
+struct environ *
+make_environ ()
+{
+ register struct environ *e;
+
+ e = (struct environ *) xmalloc (sizeof (struct environ));
+
+ e->allocated = 10;
+ e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
+ e->vector[0] = 0;
+ return e;
+}
+
+/* Free an environment and all the strings in it. */
+
+void
+free_environ (e)
+ register struct environ *e;
+{
+ register char **vector = e->vector;
+
+ while (*vector)
+ free (*vector++);
+
+ free (e);
+}
+
+/* Copy the environment given to this process into E.
+ Also copies all the strings in it, so we can be sure
+ that all strings in these environments are safe to free. */
+
+void
+init_environ (e)
+ register struct environ *e;
+{
+ extern char **environ;
+ register int i;
+
+ for (i = 0; environ[i]; i++);
+
+ if (e->allocated < i)
+ {
+ e->allocated = max (i, e->allocated + 10);
+ e->vector = (char **) xrealloc (e->vector,
+ (e->allocated + 1) * sizeof (char *));
+ }
+
+ bcopy (environ, e->vector, (i + 1) * sizeof (char *));
+
+ while (--i >= 0)
+ {
+ register int len = strlen (e->vector[i]) + 1;
+ register char *new = (char *) xmalloc (len);
+ bcopy (e->vector[i], new, len);
+ e->vector[i] = new;
+ }
+}
+
+/* Return the vector of environment E.
+ This is used to get something to pass to execve. */
+
+char **
+environ_vector (e)
+ struct environ *e;
+{
+ return e->vector;
+}
+
+/* Return the value in environment E of variable VAR. */
+
+char *
+get_in_environ (e, var)
+ struct environ *e;
+ char *var;
+{
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (; s = *vector; vector++)
+ if (!strncmp (s, var, len)
+ && s[len] == '=')
+ return &s[len + 1];
+
+ return 0;
+}
+
+/* Store the value in E of VAR as VALUE. */
+
+void
+set_in_environ (e, var, value)
+ struct environ *e;
+ char *var;
+ char *value;
+{
+ register int i;
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (i = 0; s = vector[i]; i++)
+ if (!strncmp (s, var, len)
+ && s[len] == '=')
+ break;
+
+ if (s == 0)
+ {
+ if (i == e->allocated)
+ {
+ e->allocated += 10;
+ vector = (char **) xrealloc (vector,
+ (e->allocated + 1) * sizeof (char *));
+ e->vector = vector;
+ }
+ vector[i + 1] = 0;
+ }
+ else
+ free (s);
+
+ s = (char *) xmalloc (len + strlen (value) + 2);
+ strcpy (s, var);
+ strcat (s, "=");
+ strcat (s, value);
+ vector[i] = s;
+ return;
+}
+
+/* Remove the setting for variable VAR from environment E. */
+
+void
+unset_in_environ (e, var)
+ struct environ *e;
+ char *var;
+{
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (; s = *vector; vector++)
+ if (!strncmp (s, var, len)
+ && s[len] == '=')
+ {
+ free (s);
+ bcopy (vector + 1, vector,
+ (e->allocated - (vector - e->vector)) * sizeof (char *));
+ e->vector[e->allocated - 1] = 0;
+ return;
+ }
+}
diff --git a/gnu/usr.bin/kgdb/environ.h b/gnu/usr.bin/kgdb/environ.h
new file mode 100644
index 000000000000..13f31f470a5e
--- /dev/null
+++ b/gnu/usr.bin/kgdb/environ.h
@@ -0,0 +1,39 @@
+/* Header for environment manipulation library.
+ Copyright (C) 1989, Free Software Foundation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* We manipulate environments represented as these structures. */
+
+struct environ
+{
+ /* Number of usable slots allocated in VECTOR.
+ VECTOR always has one slot not counted here,
+ to hold the terminating zero. */
+ int allocated;
+ /* A vector of slots, ALLOCATED + 1 of them.
+ The first few slots contain strings "VAR=VALUE"
+ and the next one contains zero.
+ Then come some unused slots. */
+ char **vector;
+};
+
+struct environ *make_environ ();
+void free_environ ();
+void init_environ ();
+char *get_in_environ ();
+void set_in_environ ();
+void unset_in_environ ();
+char **environ_vector ();
diff --git a/gnu/usr.bin/kgdb/eval.c b/gnu/usr.bin/kgdb/eval.c
new file mode 100644
index 000000000000..60779e688ff4
--- /dev/null
+++ b/gnu/usr.bin/kgdb/eval.c
@@ -0,0 +1,1065 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)eval.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Evaluate expressions for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "expression.h"
+
+
+/* Parse the string EXP as a C expression, evaluate it,
+ and return the result as a number. */
+
+CORE_ADDR
+parse_and_eval_address (exp)
+ char *exp;
+{
+ struct expression *expr = parse_c_expression (exp);
+ register CORE_ADDR addr;
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+
+ addr = (CORE_ADDR) value_as_long (evaluate_expression (expr));
+ do_cleanups (old_chain);
+ return addr;
+}
+
+/* Like parse_and_eval_address but takes a pointer to a char * variable
+ and advanced that variable across the characters parsed. */
+
+CORE_ADDR
+parse_and_eval_address_1 (expptr)
+ char **expptr;
+{
+ struct expression *expr = parse_c_1 (expptr, 0, 0);
+ register CORE_ADDR addr;
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+
+ addr = value_as_long (evaluate_expression (expr));
+ do_cleanups (old_chain);
+ return addr;
+}
+
+value
+parse_and_eval (exp)
+ char *exp;
+{
+ struct expression *expr = parse_c_expression (exp);
+ register value val;
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+ do_cleanups (old_chain);
+ return val;
+}
+
+/* Parse up to a comma (or to a closeparen)
+ in the string EXPP as an expression, evaluate it, and return the value.
+ EXPP is advanced to point to the comma. */
+
+value
+parse_to_comma_and_eval (expp)
+ char **expp;
+{
+ struct expression *expr = parse_c_1 (expp, 0, 1);
+ register value val;
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+ do_cleanups (old_chain);
+ return val;
+}
+
+/* Evaluate an expression in internal prefix form
+ such as is constructed by expread.y.
+
+ See expression.h for info on the format of an expression. */
+
+static value evaluate_subexp ();
+static value evaluate_subexp_for_address ();
+static value evaluate_subexp_for_sizeof ();
+static value evaluate_subexp_with_coercion ();
+
+/* return true if 'var' has an address in inferior's memory. */
+static int
+value_has_lval(var)
+ register struct symbol *var;
+{
+ switch (SYMBOL_CLASS(var))
+ {
+ case LOC_STATIC:
+ case LOC_LABEL:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_LOCAL:
+ case LOC_BLOCK:
+ return (1);
+ }
+ return (0);
+}
+
+/* Values of NOSIDE argument to eval_subexp. */
+enum noside
+{ EVAL_NORMAL,
+ EVAL_SKIP, /* Only effect is to increment pos. */
+ EVAL_AVOID_SIDE_EFFECTS, /* Don't modify any variables or
+ call any functions. The value
+ returned will have the correct
+ type, and will have an
+ approximately correct lvalue
+ type (inaccuracy: anything that is
+ listed as being in a register in
+ the function in which it was
+ declared will be lval_register). */
+};
+
+value
+evaluate_expression (exp)
+ struct expression *exp;
+{
+ int pc = 0;
+ return evaluate_subexp (0, exp, &pc, EVAL_NORMAL);
+}
+
+/* Evaluate an expression, avoiding all memory references
+ and getting a value whose type alone is correct. */
+
+value
+evaluate_type (exp)
+ struct expression *exp;
+{
+ int pc = 0;
+ return evaluate_subexp (0, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+}
+
+static value
+evaluate_subexp (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op;
+ int tem;
+ register int pc, pc2, oldpos;
+ register value arg1, arg2, arg3;
+ int nargs;
+ value *argvec;
+
+ pc = (*pos)++;
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case OP_SCOPE:
+ tem = strlen (&exp->elts[pc + 2].string);
+ (*pos) += 3 + ((tem + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ return value_static_field (exp->elts[pc + 1].type,
+ &exp->elts[pc + 2].string, -1);
+
+ case OP_LONG:
+ (*pos) += 3;
+ return value_from_long (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].longconst);
+
+ case OP_DOUBLE:
+ (*pos) += 3;
+ return value_from_double (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].doubleconst);
+
+ case OP_VAR_VALUE:
+ (*pos) += 2;
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct symbol * sym = exp->elts[pc + 1].symbol;
+ enum lval_type lv;
+
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_CONST:
+ case LOC_LABEL:
+ case LOC_CONST_BYTES:
+ lv = not_lval;
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ lv = lval_register;
+ default:
+ lv = lval_memory;
+ }
+
+ return value_zero (SYMBOL_TYPE (sym), lv);
+ }
+ else
+ return value_of_variable (exp->elts[pc + 1].symbol);
+
+ case OP_LAST:
+ (*pos) += 2;
+ return access_value_history ((int) exp->elts[pc + 1].longconst);
+
+ case OP_REGISTER:
+ (*pos) += 2;
+ return value_of_register ((int) exp->elts[pc + 1].longconst);
+
+ case OP_INTERNALVAR:
+ (*pos) += 2;
+ return value_of_internalvar (exp->elts[pc + 1].internalvar);
+
+ case OP_STRING:
+ tem = strlen (&exp->elts[pc + 1].string);
+ (*pos) += 2 + ((tem + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_string (&exp->elts[pc + 1].string, tem);
+
+ case TERNOP_COND:
+ /* Skip third and second args to evaluate the first one. */
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ if (value_zerop (arg1))
+ {
+ evaluate_subexp (0, exp, pos, EVAL_SKIP);
+ return evaluate_subexp (0, exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ evaluate_subexp (0, exp, pos, EVAL_SKIP);
+ return arg2;
+ }
+
+ case OP_FUNCALL:
+ (*pos) += 2;
+ op = exp->elts[*pos].opcode;
+ if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ int fnptr;
+ int tem2;
+
+ nargs = (int) exp->elts[pc + 1].longconst + 1;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (op == STRUCTOP_MEMBER)
+ {
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ }
+
+ /* If the function is a virtual function, then the
+ aggregate value (providing the structure) plays
+ its part by providing the vtable. Otherwise,
+ it is just along for the ride: call the function
+ directly. */
+
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+
+ fnptr = (int) value_as_long (arg1);
+ if (fnptr < 128)
+ {
+ struct type *basetype;
+ int i, j;
+ basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
+ basetype = TYPE_VPTR_BASETYPE (basetype);
+ for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
+ /* If one is virtual, then all are virtual. */
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
+ for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
+ if (TYPE_FN_FIELD_VOFFSET (f, j) == fnptr)
+ {
+ value vtbl;
+ value base = value_ind (arg2);
+ struct type *fntype = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+
+ if (TYPE_VPTR_FIELDNO (basetype) < 0)
+ TYPE_VPTR_FIELDNO (basetype)
+ = fill_in_vptr_fieldno (basetype);
+
+ VALUE_TYPE (base) = basetype;
+ vtbl = value_field (base, TYPE_VPTR_FIELDNO (basetype));
+ VALUE_TYPE (vtbl) = lookup_pointer_type (fntype);
+ VALUE_TYPE (arg1) = builtin_type_int;
+ arg1 = value_subscript (vtbl, arg1);
+ VALUE_TYPE (arg1) = fntype;
+ goto got_it;
+ }
+ }
+ if (i < 0)
+ error ("virtual function at index %d not found", fnptr);
+ }
+ else
+ {
+ VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
+ }
+ got_it:
+
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ /* Hair for method invocations */
+ int tem2;
+
+ nargs = (int) exp->elts[pc + 1].longconst + 1;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+ tem2 = strlen (&exp->elts[pc2 + 1].string);
+ *pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (op == STRUCTOP_STRUCT)
+ {
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ }
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else
+ {
+ nargs = (int) exp->elts[pc + 1].longconst;
+ tem = 0;
+ }
+ argvec = (value *) alloca (sizeof (value) * (nargs + 2));
+ for (; tem <= nargs; tem++)
+ /* Ensure that array expressions are coerced into pointer objects. */
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ /* signal end of arglist */
+ argvec[tem] = 0;
+
+ if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ int static_memfuncp;
+
+ argvec[1] = arg2;
+ argvec[0] =
+ value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string,
+ &static_memfuncp,
+ op == STRUCTOP_STRUCT
+ ? "structure" : "structure pointer");
+ if (static_memfuncp)
+ {
+ argvec[1] = argvec[0];
+ nargs--;
+ argvec++;
+ }
+ }
+ else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ argvec[1] = arg2;
+ argvec[0] = arg1;
+ }
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type, call an
+ error. This can happen if somebody tries to turn a variable into
+ a function call. This is here because people often want to
+ call, eg, strcmp, which gdb doesn't know is a function. If
+ gdb isn't asked for it's opinion (ie. through "whatis"),
+ it won't offer it. */
+
+ struct type *ftype =
+ TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0]));
+
+ if (ftype)
+ return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
+ else
+ error ("Expression of type other than \"Function returning ...\" used as function");
+ }
+ return call_function (argvec[0], nargs, argvec + 1);
+
+ case STRUCTOP_STRUCT:
+ tem = strlen (&exp->elts[pc + 1].string);
+ (*pos) += 2 + ((tem + sizeof (union exp_element))
+ / sizeof (union exp_element));
+
+ /* Try to convert "foo.bar" into "(&foo)->bar" so we won't copy
+ * the entire contents of a large struct just to extract one
+ * value from it. */
+ if (noside == EVAL_NORMAL && exp->elts[*pos].opcode == OP_VAR_VALUE
+ && value_has_lval(exp->elts[*pos + 1].symbol))
+ arg1 = evaluate_subexp_for_address(exp, pos, noside);
+ else
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ register struct type *type = VALUE_TYPE (arg1);
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ return value_zero (lookup_struct_elt_type (type,
+ &exp->elts[pc + 1].string),
+ lval_memory);
+ }
+ else
+ return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0,
+ "structure");
+
+ case STRUCTOP_PTR:
+ tem = strlen (&exp->elts[pc + 1].string);
+ (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE
+ (VALUE_TYPE (arg1)),
+ &exp->elts[pc + 1].string),
+ lval_memory);
+ else
+ return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0,
+ "structure pointer");
+
+ case STRUCTOP_MEMBER:
+ arg1 = evaluate_subexp_for_address (exp, pos, noside);
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ /* Now, convert these values to an address. */
+ if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
+ || ((TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
+ != TYPE_CODE_MEMBER)
+ && (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
+ != TYPE_CODE_METHOD)))
+ error ("non-pointer-to-member value used in pointer-to-member construct");
+ arg3 = value_from_long (builtin_type_long,
+ value_as_long (arg1) + value_as_long (arg2));
+ VALUE_TYPE (arg3) =
+ lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
+ return value_ind (arg3);
+
+ case STRUCTOP_MPTR:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ /* Now, convert these values to an address. */
+ if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
+ || (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_MEMBER
+ && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_METHOD))
+ error ("non-pointer-to-member value used in pointer-to-member construct");
+ arg3 = value_from_long (builtin_type_long,
+ value_as_long (arg1) + value_as_long (arg2));
+ VALUE_TYPE (arg3) =
+ lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
+ return value_ind (arg3);
+
+ case BINOP_ASSIGN:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, 0);
+ else
+ return value_assign (arg1, arg2);
+
+ case BINOP_ASSIGN_MODIFY:
+ (*pos) += 2;
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ op = exp->elts[pc + 1].opcode;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op);
+ else if (op == BINOP_ADD)
+ arg2 = value_add (arg1, arg2);
+ else if (op == BINOP_SUB)
+ arg2 = value_sub (arg1, arg2);
+ else
+ arg2 = value_binop (arg1, arg2, op);
+ return value_assign (arg1, arg2);
+
+ case BINOP_ADD:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, 0);
+ else
+ return value_add (arg1, arg2);
+
+ case BINOP_SUB:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, 0);
+ else
+ return value_sub (arg1, arg2);
+
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_REM:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ case BINOP_LOGAND:
+ case BINOP_LOGIOR:
+ case BINOP_LOGXOR:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, 0);
+ else
+ if (noside == EVAL_AVOID_SIDE_EFFECTS
+ && op == BINOP_DIV)
+ return value_zero (VALUE_TYPE (arg1), not_lval);
+ else
+ return value_binop (arg1, arg2, op);
+
+ case BINOP_SUBSCRIPT:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+ VALUE_LVAL (arg1));
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, 0);
+ else
+ return value_subscript (arg1, arg2);
+
+ case BINOP_AND:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ {
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ goto nosideret;
+ }
+
+ oldpos = *pos;
+ arg2 = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ *pos = oldpos;
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_zerop (arg1);
+ arg2 = evaluate_subexp (0, exp, pos,
+ (tem ? EVAL_SKIP : noside));
+ return value_from_long (builtin_type_int,
+ (LONGEST) (!tem && !value_zerop (arg2)));
+ }
+
+ case BINOP_OR:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ {
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ goto nosideret;
+ }
+
+ oldpos = *pos;
+ arg2 = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ *pos = oldpos;
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_zerop (arg1);
+ arg2 = evaluate_subexp (0, exp, pos,
+ (!tem ? EVAL_SKIP : noside));
+ return value_from_long (builtin_type_int,
+ (LONGEST) (!tem || !value_zerop (arg2)));
+ }
+
+ case BINOP_EQUAL:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_equal (arg1, arg2);
+ return value_from_long (builtin_type_int, (LONGEST) tem);
+ }
+
+ case BINOP_NOTEQUAL:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_equal (arg1, arg2);
+ return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ }
+
+ case BINOP_LESS:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_less (arg1, arg2);
+ return value_from_long (builtin_type_int, (LONGEST) tem);
+ }
+
+ case BINOP_GTR:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_less (arg2, arg1);
+ return value_from_long (builtin_type_int, (LONGEST) tem);
+ }
+
+ case BINOP_GEQ:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_less (arg1, arg2);
+ return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ }
+
+ case BINOP_LEQ:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, 0);
+ }
+ else
+ {
+ tem = value_less (arg2, arg1);
+ return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ }
+
+ case BINOP_REPEAT:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT)
+ error ("Non-integral right operand for \"@\" operator.");
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return allocate_repeat_value (VALUE_TYPE (arg1),
+ (int) value_as_long (arg2));
+ else
+ return value_repeat (arg1, (int) value_as_long (arg2));
+
+ case BINOP_COMMA:
+ evaluate_subexp (0, exp, pos, noside);
+ return evaluate_subexp (0, exp, pos, noside);
+
+ case UNOP_NEG:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op);
+ else
+ return value_neg (arg1);
+
+ case UNOP_LOGNOT:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op);
+ else
+ return value_lognot (arg1);
+
+ case UNOP_ZEROP:
+ arg1 = evaluate_subexp (0, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op);
+ else
+ return value_from_long (builtin_type_int,
+ (LONGEST) value_zerop (arg1));
+
+ case UNOP_IND:
+ if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
+ expect_type = TYPE_TARGET_TYPE (expect_type);
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+ || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
+ /* In C you can dereference an array to get the 1st elt. */
+ || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY
+ )
+ return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+ lval_memory);
+ else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
+ /* GDB allows dereferencing an int. */
+ return value_zero (builtin_type_int, lval_memory);
+ else
+ error ("Attempt to take contents of a non-pointer value.");
+ }
+ return value_ind (arg1);
+
+ case UNOP_ADDR:
+ /* C++: check for and handle pointer to members. */
+
+ op = exp->elts[*pos].opcode;
+
+ if (noside == EVAL_SKIP)
+ {
+ if (op == OP_SCOPE)
+ {
+ char *name = &exp->elts[pc+3].string;
+ int tem = strlen (name);
+ (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ }
+ else
+ evaluate_subexp (expect_type, exp, pos, EVAL_SKIP);
+ goto nosideret;
+ }
+
+ if (op == OP_SCOPE)
+ {
+ char *name = &exp->elts[pc+3].string;
+ int tem = strlen (name);
+ struct type *domain = exp->elts[pc+2].type;
+ (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ arg1 = value_struct_elt_for_address (domain, expect_type, name);
+ if (arg1)
+ return arg1;
+ error ("no field `%s' in structure", name);
+ }
+ else
+ return evaluate_subexp_for_address (exp, pos, noside);
+
+ case UNOP_SIZEOF:
+ if (noside == EVAL_SKIP)
+ {
+ evaluate_subexp (0, exp, pos, EVAL_SKIP);
+ goto nosideret;
+ }
+ return evaluate_subexp_for_sizeof (exp, pos);
+
+ case UNOP_CAST:
+ (*pos) += 2;
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_cast (exp->elts[pc + 1].type, arg1);
+
+ case UNOP_MEMVAL:
+ (*pos) += 2;
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (exp->elts[pc + 1].type, lval_memory);
+ else
+ return value_at (exp->elts[pc + 1].type,
+ (CORE_ADDR) value_as_long (arg1));
+
+ case UNOP_PREINCREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_add (arg1, value_from_long (builtin_type_char,
+ (LONGEST) 1));
+ return value_assign (arg1, arg2);
+ }
+
+ case UNOP_PREDECREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_sub (arg1, value_from_long (builtin_type_char,
+ (LONGEST) 1));
+ return value_assign (arg1, arg2);
+ }
+
+ case UNOP_POSTINCREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_add (arg1, value_from_long (builtin_type_char,
+ (LONGEST) 1));
+ value_assign (arg1, arg2);
+ return arg1;
+ }
+
+ case UNOP_POSTDECREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_sub (arg1, value_from_long (builtin_type_char,
+ (LONGEST) 1));
+ value_assign (arg1, arg2);
+ return arg1;
+ }
+
+ case OP_THIS:
+ (*pos) += 1;
+ return value_of_this (1);
+
+ default:
+ error ("internal error: I do not know how to evaluate what you gave me");
+ }
+
+ nosideret:
+ return value_from_long (builtin_type_long, (LONGEST) 1);
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+ and return the address of that subexpression.
+ Advance *POS over the subexpression.
+ If the subexpression isn't an lvalue, get an error.
+ NOSIDE may be EVAL_AVOID_SIDE_EFFECTS;
+ then only the type of the result need be correct. */
+
+static value
+evaluate_subexp_for_address (exp, pos, noside)
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op;
+ register int pc;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case UNOP_IND:
+ (*pos)++;
+ return evaluate_subexp (0, exp, pos, noside);
+
+ case UNOP_MEMVAL:
+ (*pos) += 3;
+ return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
+ evaluate_subexp (0, exp, pos, noside));
+
+ case OP_VAR_VALUE:
+ (*pos) += 3;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct type *type =
+ lookup_pointer_type (SYMBOL_TYPE (exp->elts[pc + 1].symbol));
+ enum address_class sym_class =
+ SYMBOL_CLASS (exp->elts[pc + 1].symbol);
+
+ if (sym_class == LOC_CONST
+ || sym_class == LOC_CONST_BYTES
+ || sym_class == LOC_REGISTER
+ || sym_class == LOC_REGPARM)
+ error ("Attempt to take address of register or constant.");
+
+ return
+ value_zero (type, not_lval);
+ }
+ else
+ return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+
+ default:
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ value x = evaluate_subexp (0, exp, pos, noside);
+ if (VALUE_LVAL (x) == lval_memory)
+ return value_zero (TYPE_POINTER_TYPE (VALUE_TYPE (x)),
+ not_lval);
+ else
+ error ("Attempt to take address of non-lval");
+ }
+ return value_addr (evaluate_subexp (0, exp, pos, noside));
+ }
+}
+
+/* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
+ When used in contexts where arrays will be coerced anyway,
+ this is equivalent to `evaluate_subexp'
+ but much faster because it avoids actually fetching array contents. */
+
+static value
+evaluate_subexp_with_coercion (exp, pos, noside)
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ register enum exp_opcode op;
+ register int pc;
+ register value val;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case OP_VAR_VALUE:
+ if (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 1].symbol)) == TYPE_CODE_ARRAY)
+ {
+ (*pos) += 3;
+ val = locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+ return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (exp->elts[pc + 1].symbol))),
+ val);
+ }
+ }
+
+ return evaluate_subexp (0, exp, pos, noside);
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+ and return a value for the size of that subexpression.
+ Advance *POS over the subexpression. */
+
+static value
+evaluate_subexp_for_sizeof (exp, pos)
+ register struct expression *exp;
+ register int *pos;
+{
+ enum exp_opcode op;
+ register int pc;
+ value val;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ /* This case is handled specially
+ so that we avoid creating a value for the result type.
+ If the result type is very big, it's desirable not to
+ create a value unnecessarily. */
+ case UNOP_IND:
+ (*pos)++;
+ val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ return value_from_long (builtin_type_int, (LONGEST)
+ TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
+
+ case UNOP_MEMVAL:
+ (*pos) += 3;
+ return value_from_long (builtin_type_int,
+ (LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type));
+
+ case OP_VAR_VALUE:
+ (*pos) += 3;
+ return value_from_long (builtin_type_int,
+ (LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
+
+ default:
+ val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ return value_from_long (builtin_type_int,
+ (LONGEST) TYPE_LENGTH (VALUE_TYPE (val)));
+ }
+}
diff --git a/gnu/usr.bin/kgdb/expprint.c b/gnu/usr.bin/kgdb/expprint.c
new file mode 100644
index 000000000000..2c63cf8928cb
--- /dev/null
+++ b/gnu/usr.bin/kgdb/expprint.c
@@ -0,0 +1,324 @@
+/* Print in infix form a struct expression.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "expression.h"
+#include "value.h"
+
+
+/* These codes indicate operator precedences, least tightly binding first. */
+/* Adding 1 to a precedence value is done for binary operators,
+ on the operand which is more tightly bound, so that operators
+ of equal precedence within that operand will get parentheses. */
+/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
+ they are used as the "surrounding precedence" to force
+ various kinds of things to be parenthesized. */
+enum precedence
+{ PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
+ PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
+ PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
+ PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+
+struct op_print
+{
+ char *string;
+ enum exp_opcode opcode;
+ /* Precedence of operator. These values are used only by comparisons. */
+ enum precedence precedence;
+ int right_assoc;
+};
+
+static struct op_print op_print_tab[] =
+ {
+ {",", BINOP_COMMA, PREC_COMMA, 0},
+ {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"||", BINOP_OR, PREC_OR, 0},
+ {"&&", BINOP_AND, PREC_AND, 0},
+ {"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
+ {"&", BINOP_LOGAND, PREC_LOGAND, 0},
+ {"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
+ {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+ {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+ {"<=", BINOP_LEQ, PREC_ORDER, 0},
+ {">=", BINOP_GEQ, PREC_ORDER, 0},
+ {">", BINOP_GTR, PREC_ORDER, 0},
+ {"<", BINOP_LESS, PREC_ORDER, 0},
+ {">>", BINOP_RSH, PREC_SHIFT, 0},
+ {"<<", BINOP_LSH, PREC_SHIFT, 0},
+ {"+", BINOP_ADD, PREC_ADD, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"%", BINOP_REM, PREC_MUL, 0},
+ {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"!", UNOP_ZEROP, PREC_PREFIX, 0},
+ {"~", UNOP_LOGNOT, PREC_PREFIX, 0},
+ {"*", UNOP_IND, PREC_PREFIX, 0},
+ {"&", UNOP_ADDR, PREC_PREFIX, 0},
+ {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+ {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+ {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+ /* C++ */
+ {"::", BINOP_SCOPE, PREC_PREFIX, 0},
+ };
+
+static void print_subexp ();
+
+void
+print_expression (exp, stream)
+ struct expression *exp;
+ FILE *stream;
+{
+ int pc = 0;
+ print_subexp (exp, &pc, stream, PREC_NULL);
+}
+
+/* Print the subexpression of EXP that starts in position POS, on STREAM.
+ PREC is the precedence of the surrounding operator;
+ if the precedence of the main operator of this subexpression is less,
+ parentheses are needed here. */
+
+static void
+print_subexp (exp, pos, stream, prec)
+ register struct expression *exp;
+ register int *pos;
+ FILE *stream;
+ enum precedence prec;
+{
+ register int tem;
+ register int pc;
+ int nargs;
+ register char *op_str;
+ int assign_modify = 0;
+ enum exp_opcode opcode;
+ enum precedence myprec;
+ /* Set to 1 for a right-associative operator. */
+ int assoc;
+
+ pc = (*pos)++;
+ opcode = exp->elts[pc].opcode;
+ switch (opcode)
+ {
+ case OP_SCOPE:
+ myprec = PREC_PREFIX;
+ assoc = 0;
+ (*pos) += 2;
+ print_subexp (exp, pos, stream, (int) myprec + assoc);
+ fprintf (stream, " :: ");
+ nargs = strlen (&exp->elts[pc + 2].string);
+ (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
+
+ fprintf (stream, &exp->elts[pc + 2].string);
+ return;
+
+ case OP_LONG:
+ (*pos) += 3;
+ value_print (value_from_long (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].longconst),
+ stream, 0, Val_no_prettyprint);
+ return;
+
+ case OP_DOUBLE:
+ (*pos) += 3;
+ value_print (value_from_double (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].doubleconst),
+ stream, 0, Val_no_prettyprint);
+ return;
+
+ case OP_VAR_VALUE:
+ (*pos) += 2;
+ fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
+ return;
+
+ case OP_LAST:
+ (*pos) += 2;
+ fprintf (stream, "$%d", (int) exp->elts[pc + 1].longconst);
+ return;
+
+ case OP_REGISTER:
+ (*pos) += 2;
+ fprintf (stream, "$%s", reg_names[exp->elts[pc + 1].longconst]);
+ return;
+
+ case OP_INTERNALVAR:
+ (*pos) += 2;
+ fprintf (stream, "$%s",
+ internalvar_name (exp->elts[pc + 1].internalvar));
+ return;
+
+ case OP_FUNCALL:
+ (*pos) += 2;
+ nargs = exp->elts[pc + 1].longconst;
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fprintf (stream, " (");
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem > 0)
+ fprintf (stream, ", ");
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fprintf (stream, ")");
+ return;
+
+ case OP_STRING:
+ nargs = strlen (&exp->elts[pc + 1].string);
+ (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
+ fprintf (stream, "\"");
+ for (tem = 0; tem < nargs; tem++)
+ printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
+ fprintf (stream, "\"");
+ return;
+
+ case TERNOP_COND:
+ if ((int) prec > (int) PREC_COMMA)
+ fprintf (stream, "(");
+ /* Print the subexpressions, forcing parentheses
+ around any binary operations within them.
+ This is more parentheses than are strictly necessary,
+ but it looks clearer. */
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ fprintf (stream, " ? ");
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ fprintf (stream, " : ");
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ if ((int) prec > (int) PREC_COMMA)
+ fprintf (stream, ")");
+ return;
+
+ case STRUCTOP_STRUCT:
+ tem = strlen (&exp->elts[pc + 1].string);
+ (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fprintf (stream, ".%s", &exp->elts[pc + 1].string);
+ return;
+
+ case STRUCTOP_PTR:
+ tem = strlen (&exp->elts[pc + 1].string);
+ (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fprintf (stream, "->%s", &exp->elts[pc + 1].string);
+ return;
+
+ case BINOP_SUBSCRIPT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fprintf (stream, "[");
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ fprintf (stream, "]");
+ return;
+
+ case UNOP_POSTINCREMENT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fprintf (stream, "++");
+ return;
+
+ case UNOP_POSTDECREMENT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fprintf (stream, "--");
+ return;
+
+ case UNOP_CAST:
+ (*pos) += 2;
+ if ((int) prec > (int) PREC_PREFIX)
+ fprintf (stream, "(");
+ fprintf (stream, "(");
+ type_print (exp->elts[pc + 1].type, "", stream, 0);
+ fprintf (stream, ") ");
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ if ((int) prec > (int) PREC_PREFIX)
+ fprintf (stream, ")");
+ return;
+
+ case UNOP_MEMVAL:
+ (*pos) += 2;
+ if ((int) prec > (int) PREC_PREFIX)
+ fprintf (stream, "(");
+ fprintf (stream, "{");
+ type_print (exp->elts[pc + 1].type, "", stream, 0);
+ fprintf (stream, "} ");
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ if ((int) prec > (int) PREC_PREFIX)
+ fprintf (stream, ")");
+ return;
+
+ case BINOP_ASSIGN_MODIFY:
+ opcode = exp->elts[pc + 1].opcode;
+ (*pos) += 2;
+ myprec = PREC_ASSIGN;
+ assoc = 1;
+ assign_modify = 1;
+ for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
+ if (op_print_tab[tem].opcode == opcode)
+ {
+ op_str = op_print_tab[tem].string;
+ break;
+ }
+
+ case OP_THIS:
+ ++(*pos);
+ fprintf (stream, "this");
+ return;
+
+ default:
+ for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
+ if (op_print_tab[tem].opcode == opcode)
+ {
+ op_str = op_print_tab[tem].string;
+ myprec = op_print_tab[tem].precedence;
+ assoc = op_print_tab[tem].right_assoc;
+ break;
+ }
+ }
+
+ if ((int) myprec < (int) prec)
+ fprintf (stream, "(");
+ if ((int) opcode > (int) BINOP_END)
+ {
+ /* Unary prefix operator. */
+ fprintf (stream, "%s", op_str);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ }
+ else
+ {
+ /* Binary operator. */
+ /* Print left operand.
+ If operator is right-associative,
+ increment precedence for this operand. */
+ print_subexp (exp, pos, stream, (int) myprec + assoc);
+ /* Print the operator itself. */
+ if (assign_modify)
+ fprintf (stream, " %s= ", op_str);
+ else if (op_str[0] == ',')
+ fprintf (stream, "%s ", op_str);
+ else
+ fprintf (stream, " %s ", op_str);
+ /* Print right operand.
+ If operator is left-associative,
+ increment precedence for this operand. */
+ print_subexp (exp, pos, stream, (int) myprec + !assoc);
+ }
+ if ((int) myprec < (int) prec)
+ fprintf (stream, ")");
+}
diff --git a/gnu/usr.bin/kgdb/expread.y b/gnu/usr.bin/kgdb/expread.y
new file mode 100644
index 000000000000..96a12c48c064
--- /dev/null
+++ b/gnu/usr.bin/kgdb/expread.y
@@ -0,0 +1,1782 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+/* Parse C expressions for GDB.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Parse a C expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result. */
+
+%{
+#ifndef lint
+static char sccsid[] = "@(#)expread.y 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "expression.h"
+
+#include <a.out.h>
+
+static struct expression *expout;
+static int expout_size;
+static int expout_ptr;
+
+static int yylex ();
+static void yyerror ();
+static void write_exp_elt ();
+static void write_exp_elt_opcode ();
+static void write_exp_elt_sym ();
+static void write_exp_elt_longcst ();
+static void write_exp_elt_dblcst ();
+static void write_exp_elt_type ();
+static void write_exp_elt_intern ();
+static void write_exp_string ();
+static void start_arglist ();
+static int end_arglist ();
+static void free_funcalls ();
+static char *copy_name ();
+
+/* If this is nonzero, this block is used as the lexical context
+ for symbol names. */
+
+static struct block *expression_context_block;
+
+/* The innermost context required by the stack and register variables
+ we've encountered so far. */
+struct block *innermost_block;
+
+/* The block in which the most recently discovered symbol was found. */
+struct block *block_found;
+
+/* Number of arguments seen so far in innermost function call. */
+static int arglist_len;
+
+/* Data structure for saving values of arglist_len
+ for function calls whose arguments contain other function calls. */
+
+struct funcall
+ {
+ struct funcall *next;
+ int arglist_len;
+ };
+
+struct funcall *funcall_chain;
+
+/* This kind of datum is used to represent the name
+ of a symbol token. */
+
+struct stoken
+ {
+ char *ptr;
+ int length;
+ };
+
+/* For parsing of complicated types.
+ An array should be preceded in the list by the size of the array. */
+enum type_pieces
+ {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function};
+static enum type_pieces *type_stack;
+static int type_stack_depth, type_stack_size;
+
+static void push_type ();
+static enum type_pieces pop_type ();
+
+/* Allow debugging of parsing. */
+#define YYDEBUG 1
+%}
+
+/* Although the yacc "value" of an expression is not used,
+ since the result is stored in the structure being created,
+ other node types do have values. */
+
+%union
+ {
+ LONGEST lval;
+ unsigned LONGEST ulval;
+ double dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ }
+
+%type <voidval> exp exp1 start variable
+%type <tval> type typebase
+%type <tvec> nonempty_typelist
+%type <bval> block
+
+/* Fancy type parsing. */
+%type <voidval> func_mod direct_abs_decl abs_decl
+%type <tval> ptype
+%type <lval> array_mod
+
+%token <lval> INT CHAR
+%token <ulval> UINT
+%token <dval> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+ and both convey their data as strings.
+ But a TYPENAME is a string that happens to be defined as a typedef
+ or builtin type name (such as int or char)
+ and a NAME is any other symbol.
+
+ Contexts where this distinction is not important can use the
+ nonterminal "name", which matches either NAME or TYPENAME. */
+
+%token <sval> NAME TYPENAME BLOCKNAME STRING
+%type <sval> name name_not_typename typename
+
+%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token SIGNED LONG SHORT INT_KEYWORD
+
+%token <lval> LAST REGNAME
+
+%token <ivar> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+/* C++ */
+%token THIS
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY INCREMENT DECREMENT
+%right ARROW '.' '[' '('
+%left COLONCOLON
+
+%%
+
+start : exp1
+ ;
+
+/* Expressions, including the comma operator. */
+exp1 : exp
+ | exp1 ',' exp
+ { write_exp_elt_opcode (BINOP_COMMA); }
+ ;
+
+/* Expressions, not including the comma operator. */
+exp : '*' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_IND); }
+
+exp : '&' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_ADDR); }
+
+exp : '-' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_NEG); }
+ ;
+
+exp : '!' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_ZEROP); }
+ ;
+
+exp : '~' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGNOT); }
+ ;
+
+exp : INCREMENT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_PREINCREMENT); }
+ ;
+
+exp : DECREMENT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_PREDECREMENT); }
+ ;
+
+exp : exp INCREMENT %prec UNARY
+ { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
+ ;
+
+exp : exp DECREMENT %prec UNARY
+ { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
+ ;
+
+exp : SIZEOF exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+exp : exp ARROW name
+ { write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_PTR); }
+ ;
+
+exp : exp ARROW '*' exp
+ { write_exp_elt_opcode (STRUCTOP_MPTR); }
+ ;
+
+exp : exp '.' name
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
+exp : exp '.' '*' exp
+ { write_exp_elt_opcode (STRUCTOP_MEMBER); }
+ ;
+
+exp : exp '[' exp1 ']'
+ { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+ ;
+
+exp : exp '('
+ /* This is to save the value of arglist_len
+ being accumulated by an outer function call. */
+ { start_arglist (); }
+ arglist ')' %prec ARROW
+ { write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+exp : '{' type '}' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_MEMVAL); }
+ ;
+
+exp : '(' type ')' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+exp : '(' exp1 ')'
+ { }
+ ;
+
+/* Binary operators in order of decreasing precedence. */
+
+exp : exp '@' exp
+ { write_exp_elt_opcode (BINOP_REPEAT); }
+ ;
+
+exp : exp '*' exp
+ { write_exp_elt_opcode (BINOP_MUL); }
+ ;
+
+exp : exp '/' exp
+ { write_exp_elt_opcode (BINOP_DIV); }
+ ;
+
+exp : exp '%' exp
+ { write_exp_elt_opcode (BINOP_REM); }
+ ;
+
+exp : exp '+' exp
+ { write_exp_elt_opcode (BINOP_ADD); }
+ ;
+
+exp : exp '-' exp
+ { write_exp_elt_opcode (BINOP_SUB); }
+ ;
+
+exp : exp LSH exp
+ { write_exp_elt_opcode (BINOP_LSH); }
+ ;
+
+exp : exp RSH exp
+ { write_exp_elt_opcode (BINOP_RSH); }
+ ;
+
+exp : exp EQUAL exp
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+ ;
+
+exp : exp NOTEQUAL exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ ;
+
+exp : exp LEQ exp
+ { write_exp_elt_opcode (BINOP_LEQ); }
+ ;
+
+exp : exp GEQ exp
+ { write_exp_elt_opcode (BINOP_GEQ); }
+ ;
+
+exp : exp '<' exp
+ { write_exp_elt_opcode (BINOP_LESS); }
+ ;
+
+exp : exp '>' exp
+ { write_exp_elt_opcode (BINOP_GTR); }
+ ;
+
+exp : exp '&' exp
+ { write_exp_elt_opcode (BINOP_LOGAND); }
+ ;
+
+exp : exp '^' exp
+ { write_exp_elt_opcode (BINOP_LOGXOR); }
+ ;
+
+exp : exp '|' exp
+ { write_exp_elt_opcode (BINOP_LOGIOR); }
+ ;
+
+exp : exp AND exp
+ { write_exp_elt_opcode (BINOP_AND); }
+ ;
+
+exp : exp OR exp
+ { write_exp_elt_opcode (BINOP_OR); }
+ ;
+
+exp : exp '?' exp ':' exp %prec '?'
+ { write_exp_elt_opcode (TERNOP_COND); }
+ ;
+
+exp : exp '=' exp
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+ ;
+
+exp : exp ASSIGN_MODIFY exp
+ { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode ($2);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : INT
+ { write_exp_elt_opcode (OP_LONG);
+ if ($1 == (int) $1 || $1 == (unsigned int) $1)
+ write_exp_elt_type (builtin_type_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : UINT
+ {
+ write_exp_elt_opcode (OP_LONG);
+ if ($1 == (unsigned int) $1)
+ write_exp_elt_type (builtin_type_unsigned_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+exp : CHAR
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : FLOAT
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_double);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : LAST
+ { write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LAST); }
+ ;
+
+exp : REGNAME
+ { write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_REGISTER); }
+ ;
+
+exp : VARIABLE
+ { write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern ($1);
+ write_exp_elt_opcode (OP_INTERNALVAR); }
+ ;
+
+exp : SIZEOF '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : STRING
+ { write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING); }
+ ;
+
+/* C++. */
+exp : THIS
+ { write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS); }
+ ;
+
+/* end of C++. */
+
+block : BLOCKNAME
+ {
+ struct symtab *tem = lookup_symtab (copy_name ($1));
+ struct symbol *sym;
+
+ if (tem)
+ $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1);
+ else
+ {
+ sym = lookup_symbol (copy_name ($1),
+ expression_context_block,
+ VAR_NAMESPACE, 0);
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ $$ = SYMBOL_BLOCK_VALUE (sym);
+ else
+ error ("No file or function \"%s\".",
+ copy_name ($1));
+ }
+ }
+ ;
+
+block : block COLONCOLON name
+ { struct symbol *tem
+ = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE, 0);
+ if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+ error ("No function \"%s\" in specified context.",
+ copy_name ($3));
+ $$ = SYMBOL_BLOCK_VALUE (tem); }
+ ;
+
+variable: block COLONCOLON name
+ { struct symbol *sym;
+ sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE, 0);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name ($3));
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+variable: typebase COLONCOLON name
+ {
+ struct type *type = $1;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string ($3);
+ write_exp_elt_opcode (OP_SCOPE);
+ }
+ | COLONCOLON name
+ {
+ char *name = copy_name ($2);
+ struct symbol *sym;
+ int i;
+
+ sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0);
+ if (sym)
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, name))
+ break;
+
+ if (i < misc_function_count)
+ {
+ enum misc_function_type mft =
+ (enum misc_function_type)
+ misc_function_vector[i].type;
+
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (mft == mf_data || mft == mf_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (mft == mf_text)
+ write_exp_elt_type (lookup_function_type (builtin_type_int));
+ else
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ }
+ else
+ if (symtab_list == 0
+ && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.", name);
+ }
+ ;
+
+variable: name_not_typename
+ { struct symbol *sym;
+ int is_a_field_of_this;
+
+ sym = lookup_symbol (copy_name ($1),
+ expression_context_block,
+ VAR_NAMESPACE,
+ &is_a_field_of_this);
+ if (sym)
+ {
+ switch (sym->class)
+ {
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_LOCAL:
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else if (is_a_field_of_this)
+ {
+ /* C++: it hangs off of `this'. Must
+ not inadvertently convert from a method call
+ to data ref. */
+ if (innermost_block == 0 ||
+ contained_in (block_found, innermost_block))
+ innermost_block = block_found;
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string ($1);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ }
+ else
+ {
+ register int i;
+ register char *arg = copy_name ($1);
+
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, arg))
+ break;
+
+ if (i < misc_function_count)
+ {
+ enum misc_function_type mft =
+ (enum misc_function_type)
+ misc_function_vector[i].type;
+
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (mft == mf_data || mft == mf_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (mft == mf_text)
+ write_exp_elt_type (lookup_function_type (builtin_type_int));
+ else
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ }
+ else if (symtab_list == 0
+ && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1));
+ }
+ }
+ ;
+
+
+ptype : typebase
+ | typebase abs_decl
+ {
+ /* This is where the interesting stuff happens. */
+ int done = 0;
+ int array_size;
+ struct type *follow_type = $1;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = (int) pop_type ();
+ if (array_size != -1)
+ follow_type = create_array_type (follow_type,
+ array_size);
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ $$ = follow_type;
+ }
+ ;
+
+abs_decl: '*'
+ { push_type (tp_pointer); $$ = 0; }
+ | '*' abs_decl
+ { push_type (tp_pointer); $$ = $2; }
+ | direct_abs_decl
+ ;
+
+direct_abs_decl: '(' abs_decl ')'
+ { $$ = $2; }
+ | direct_abs_decl array_mod
+ {
+ push_type ((enum type_pieces) $2);
+ push_type (tp_array);
+ }
+ | array_mod
+ {
+ push_type ((enum type_pieces) $1);
+ push_type (tp_array);
+ $$ = 0;
+ }
+ | direct_abs_decl func_mod
+ { push_type (tp_function); }
+ | func_mod
+ { push_type (tp_function); }
+ ;
+
+array_mod: '[' ']'
+ { $$ = -1; }
+ | '[' INT ']'
+ { $$ = $2; }
+ ;
+
+func_mod: '(' ')'
+ { $$ = 0; }
+ ;
+
+type : ptype
+ | typebase COLONCOLON '*'
+ { $$ = lookup_member_type (builtin_type_int, $1); }
+ | type '(' typebase COLONCOLON '*' ')'
+ { $$ = lookup_member_type ($1, $3); }
+ | type '(' typebase COLONCOLON '*' ')' '(' ')'
+ { $$ = lookup_member_type
+ (lookup_function_type ($1), $3); }
+ | type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
+ { $$ = lookup_member_type
+ (lookup_function_type ($1), $3);
+ free ($8); }
+ ;
+
+typebase
+ : TYPENAME
+ { $$ = lookup_typename (copy_name ($1),
+ expression_context_block, 0); }
+ | INT_KEYWORD
+ { $$ = builtin_type_int; }
+ | LONG
+ { $$ = builtin_type_long; }
+ | SHORT
+ { $$ = builtin_type_short; }
+ | LONG INT_KEYWORD
+ { $$ = builtin_type_long; }
+ | UNSIGNED LONG INT_KEYWORD
+ { $$ = builtin_type_unsigned_long; }
+ | SHORT INT_KEYWORD
+ { $$ = builtin_type_short; }
+ | UNSIGNED SHORT INT_KEYWORD
+ { $$ = builtin_type_unsigned_short; }
+ | STRUCT name
+ { $$ = lookup_struct (copy_name ($2),
+ expression_context_block); }
+ | UNION name
+ { $$ = lookup_union (copy_name ($2),
+ expression_context_block); }
+ | ENUM name
+ { $$ = lookup_enum (copy_name ($2),
+ expression_context_block); }
+ | UNSIGNED typename
+ { $$ = lookup_unsigned_typename (copy_name ($2)); }
+ | UNSIGNED
+ { $$ = builtin_type_unsigned_int; }
+ | SIGNED typename
+ { $$ = lookup_typename (copy_name ($2),
+ expression_context_block, 0); }
+ | SIGNED
+ { $$ = builtin_type_int; }
+ ;
+
+typename: TYPENAME
+ | INT_KEYWORD
+ {
+ $$.ptr = "int";
+ $$.length = 3;
+ }
+ | LONG
+ {
+ $$.ptr = "long";
+ $$.length = 4;
+ }
+ | SHORT
+ {
+ $$.ptr = "short";
+ $$.length = 5;
+ }
+ ;
+
+nonempty_typelist
+ : type
+ { $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
+ $$[0] = (struct type *)0;
+ $$[1] = $1;
+ }
+ | nonempty_typelist ',' type
+ { int len = sizeof (struct type *) * ++($<ivec>1[0]);
+ $$ = (struct type **)xrealloc ($1, len);
+ $$[$<ivec>$[0]] = $3;
+ }
+ ;
+
+name : NAME
+ | BLOCKNAME
+ | TYPENAME
+ ;
+
+name_not_typename : NAME
+ | BLOCKNAME
+ ;
+
+%%
+
+/* Begin counting arguments for a function call,
+ saving the data about any containing call. */
+
+static void
+start_arglist ()
+{
+ register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+
+ new->next = funcall_chain;
+ new->arglist_len = arglist_len;
+ arglist_len = 0;
+ funcall_chain = new;
+}
+
+/* Return the number of arguments in a function call just terminated,
+ and restore the data for the containing function call. */
+
+static int
+end_arglist ()
+{
+ register int val = arglist_len;
+ register struct funcall *call = funcall_chain;
+ funcall_chain = call->next;
+ arglist_len = call->arglist_len;
+ free (call);
+ return val;
+}
+
+/* Free everything in the funcall chain.
+ Used when there is an error inside parsing. */
+
+static void
+free_funcalls ()
+{
+ register struct funcall *call, *next;
+
+ for (call = funcall_chain; call; call = next)
+ {
+ next = call->next;
+ free (call);
+ }
+}
+
+/* This page contains the functions for adding data to the struct expression
+ being constructed. */
+
+/* Add one element to the end of the expression. */
+
+/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
+ a register through here */
+
+static void
+write_exp_elt (expelt)
+ union exp_element expelt;
+{
+ if (expout_ptr >= expout_size)
+ {
+ expout_size *= 2;
+ expout = (struct expression *) xrealloc (expout,
+ sizeof (struct expression)
+ + expout_size * sizeof (union exp_element));
+ }
+ expout->elts[expout_ptr++] = expelt;
+}
+
+static void
+write_exp_elt_opcode (expelt)
+ enum exp_opcode expelt;
+{
+ union exp_element tmp;
+
+ tmp.opcode = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_sym (expelt)
+ struct symbol *expelt;
+{
+ union exp_element tmp;
+
+ tmp.symbol = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_longcst (expelt)
+ LONGEST expelt;
+{
+ union exp_element tmp;
+
+ tmp.longconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_dblcst (expelt)
+ double expelt;
+{
+ union exp_element tmp;
+
+ tmp.doubleconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_type (expelt)
+ struct type *expelt;
+{
+ union exp_element tmp;
+
+ tmp.type = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_intern (expelt)
+ struct internalvar *expelt;
+{
+ union exp_element tmp;
+
+ tmp.internalvar = expelt;
+
+ write_exp_elt (tmp);
+}
+
+/* Add a string constant to the end of the expression.
+ Follow it by its length in bytes, as a separate exp_element. */
+
+static void
+write_exp_string (str)
+ struct stoken str;
+{
+ register int len = str.length;
+ register int lenelt
+ = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+
+ expout_ptr += lenelt;
+
+ if (expout_ptr >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + 10);
+ expout = (struct expression *)
+ xrealloc (expout, (sizeof (struct expression)
+ + (expout_size * sizeof (union exp_element))));
+ }
+ bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
+ ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+ write_exp_elt_longcst ((LONGEST) len);
+}
+
+/* During parsing of a C expression, the pointer to the next character
+ is in this variable. */
+
+static char *lexptr;
+
+/* Tokens that refer to names do so with explicit pointer and length,
+ so they can share the storage that lexptr is parsing.
+
+ When it is necessary to pass a name to a function that expects
+ a null-terminated string, the substring is copied out
+ into a block of storage that namecopy points to.
+
+ namecopy is allocated once, guaranteed big enough, for each parsing. */
+
+static char *namecopy;
+
+/* Current depth in parentheses within the expression. */
+
+static int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses). */
+
+static int comma_terminates;
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (olen)
+ int olen;
+{
+ register char *p = lexptr;
+ register LONGEST n = 0;
+ register int c;
+ register int base = 10;
+ register int len = olen;
+ char *err_copy;
+ int unsigned_p = 0;
+
+ extern double atof ();
+
+ for (c = 0; c < len; c++)
+ if (p[c] == '.')
+ {
+ /* It's a float since it contains a point. */
+ yylval.dval = atof (p);
+ lexptr += len;
+ return FLOAT;
+ }
+
+ if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2)))
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ else if (*p == '0')
+ base = 8;
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ n += c - '0';
+ else
+ {
+ if (base == 16 && c >= 'a' && c <= 'f')
+ n += c - 'a' + 10;
+ else if (len == 0 && c == 'l')
+ ;
+ else if (len == 0 && c == 'u')
+ unsigned_p = 1;
+ else if (base == 10 && len != 0 && (c == 'e' || c == 'E'))
+ {
+ /* Scientific notation, where we are unlucky enough not
+ to have a '.' in the string. */
+ yylval.dval = atof (lexptr);
+ lexptr += olen;
+ return FLOAT;
+ }
+ else
+ {
+ err_copy = (char *) alloca (olen + 1);
+ bcopy (lexptr, err_copy, olen);
+ err_copy[olen] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ }
+ }
+
+ lexptr = p;
+ if (unsigned_p)
+ {
+ yylval.ulval = n;
+ return UINT;
+ }
+ else
+ {
+ yylval.lval = n;
+ return INT;
+ }
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static struct token tokentab3[] =
+ {
+ {">>=", ASSIGN_MODIFY, BINOP_RSH},
+ {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+ };
+
+static struct token tokentab2[] =
+ {
+ {"+=", ASSIGN_MODIFY, BINOP_ADD},
+ {"-=", ASSIGN_MODIFY, BINOP_SUB},
+ {"*=", ASSIGN_MODIFY, BINOP_MUL},
+ {"/=", ASSIGN_MODIFY, BINOP_DIV},
+ {"%=", ASSIGN_MODIFY, BINOP_REM},
+ {"|=", ASSIGN_MODIFY, BINOP_LOGIOR},
+ {"&=", ASSIGN_MODIFY, BINOP_LOGAND},
+ {"^=", ASSIGN_MODIFY, BINOP_LOGXOR},
+ {"++", INCREMENT, BINOP_END},
+ {"--", DECREMENT, BINOP_END},
+ {"->", ARROW, BINOP_END},
+ {"&&", AND, BINOP_END},
+ {"||", OR, BINOP_END},
+ {"::", COLONCOLON, BINOP_END},
+ {"<<", LSH, BINOP_END},
+ {">>", RSH, BINOP_END},
+ {"==", EQUAL, BINOP_END},
+ {"!=", NOTEQUAL, BINOP_END},
+ {"<=", LEQ, BINOP_END},
+ {">=", GEQ, BINOP_END}
+ };
+
+/* assign machine-independent names to certain registers
+ * (unless overridden by the REGISTER_NAMES table)
+ */
+struct std_regs {
+ char *name;
+ int regnum;
+} std_regs[] = {
+#ifdef PC_REGNUM
+ { "pc", PC_REGNUM },
+#endif
+#ifdef FP_REGNUM
+ { "fp", FP_REGNUM },
+#endif
+#ifdef SP_REGNUM
+ { "sp", SP_REGNUM },
+#endif
+#ifdef PS_REGNUM
+ { "ps", PS_REGNUM },
+#endif
+};
+
+#define NUM_STD_REGS (sizeof std_regs / sizeof std_regs[0])
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ register int c;
+ register int namelen;
+ register int i;
+ register char *tokstart;
+
+ retry:
+
+ tokstart = lexptr;
+ /* See if it is a special token of length 3. */
+ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+ if (!strncmp (tokstart, tokentab3[i].operator, 3))
+ {
+ lexptr += 3;
+ yylval.opcode = tokentab3[i].opcode;
+ return tokentab3[i].token;
+ }
+
+ /* See if it is a special token of length 2. */
+ for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+ if (!strncmp (tokstart, tokentab2[i].operator, 2))
+ {
+ lexptr += 2;
+ yylval.opcode = tokentab2[i].opcode;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ lexptr++;
+ c = *lexptr++;
+ if (c == '\\')
+ c = parse_escape (&lexptr);
+ yylval.lval = c;
+ c = *lexptr++;
+ if (c != '\'')
+ error ("Invalid character constant.");
+ return CHAR;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] >= '0' && lexptr[1] <= '9')
+ break; /* Falls into number code. */
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ lexptr++;
+ return c;
+
+ case '"':
+ for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++)
+ if (c == '\\')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ c = tokstart[++namelen];
+ }
+ }
+ yylval.sval.ptr = tokstart + 1;
+ yylval.sval.length = namelen - 1;
+ lexptr += namelen + 1;
+ return STRING;
+ }
+
+ /* Is it a number? */
+ /* Note: We have already dealt with the case of the token '.'.
+ See case '.' above. */
+ if ((c >= '0' && c <= '9') || c == '.')
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0;
+ register char *p = tokstart;
+ int hex = c == '0' && (p[1] == 'x' || p[1] == 'X');
+ if (hex)
+ p += 2;
+ for (;; ++p)
+ {
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!hex && !got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ else if (!got_dot && !got_e && (*p=='l'||*p=='L')){
+ ++p; break;
+ }
+ else if (!got_dot && !got_e && !hex && (*p=='u'||*p=='U')){
+ ++p; break;
+ }
+ else if (*p < '0' || *p > '9'
+ && (!hex || ((*p < 'a' || *p > 'f')
+ && (*p < 'A' || *p > 'F'))))
+ break;
+ }
+ return parse_number (p - tokstart);
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen])
+ ;
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ lexptr += namelen;
+
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that).
+ Make token type LAST, and put the number (the digits) in yylval. */
+
+ if (*tokstart == '$')
+ {
+ register int negate = 0;
+ c = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (namelen >= 2 && tokstart[1] == '$')
+ {
+ negate = 1;
+ c = 2;
+ }
+ if (c == namelen)
+ {
+ /* Just dollars (one or two) */
+ yylval.lval = - negate;
+ return LAST;
+ }
+ /* Is the rest of the token digits? */
+ for (; c < namelen; c++)
+ if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
+ break;
+ if (c == namelen)
+ {
+ yylval.lval = atoi (tokstart + 1 + negate);
+ if (negate)
+ yylval.lval = - yylval.lval;
+ return LAST;
+ }
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+
+ if (*tokstart == '$') {
+ for (c = 0; c < NUM_REGS; c++)
+ if (namelen - 1 == strlen (reg_names[c])
+ && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+ {
+ yylval.lval = c;
+ return REGNAME;
+ }
+ for (c = 0; c < NUM_STD_REGS; c++)
+ if (namelen - 1 == strlen (std_regs[c].name)
+ && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+ {
+ yylval.lval = std_regs[c].regnum;
+ return REGNAME;
+ }
+ }
+ /* Catch specific keywords. Should be done with a data structure. */
+ switch (namelen)
+ {
+ case 8:
+ if (!strncmp (tokstart, "unsigned", 8))
+ return UNSIGNED;
+ break;
+ case 6:
+ if (!strncmp (tokstart, "struct", 6))
+ return STRUCT;
+ if (!strncmp (tokstart, "signed", 6))
+ return SIGNED;
+ if (!strncmp (tokstart, "sizeof", 6))
+ return SIZEOF;
+ break;
+ case 5:
+ if (!strncmp (tokstart, "union", 5))
+ return UNION;
+ if (!strncmp (tokstart, "short", 5))
+ return SHORT;
+ break;
+ case 4:
+ if (!strncmp (tokstart, "enum", 4))
+ return ENUM;
+ if (!strncmp (tokstart, "long", 4))
+ return LONG;
+ if (!strncmp (tokstart, "this", 4)
+ && lookup_symbol ("$this", expression_context_block,
+ VAR_NAMESPACE, 0))
+ return THIS;
+ break;
+ case 3:
+ if (!strncmp (tokstart, "int", 3))
+ return INT_KEYWORD;
+ break;
+ default:
+ break;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ if (*tokstart == '$')
+ {
+ yylval.ivar = (struct internalvar *) lookup_internalvar (copy_name (yylval.sval) + 1);
+ return VARIABLE;
+ }
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions or symtabs. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+
+ if (lookup_partial_symtab (tmp))
+ return BLOCKNAME;
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, 0);
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ return BLOCKNAME;
+ if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1))
+ return TYPENAME;
+ return NAME;
+ }
+}
+
+static void
+yyerror ()
+{
+ error ("Invalid syntax in expression.");
+}
+
+/* Return a null-terminated temporary copy of the name
+ of a string token. */
+
+static char *
+copy_name (token)
+ struct stoken token;
+{
+ bcopy (token.ptr, namecopy, token.length);
+ namecopy[token.length] = 0;
+ return namecopy;
+}
+
+/* Reverse an expression from suffix form (in which it is constructed)
+ to prefix form (in which we can conveniently print or execute it). */
+
+static void prefixify_subexp ();
+
+static void
+prefixify_expression (expr)
+ register struct expression *expr;
+{
+ register int len = sizeof (struct expression) +
+ expr->nelts * sizeof (union exp_element);
+ register struct expression *temp;
+ register int inpos = expr->nelts, outpos = 0;
+
+ temp = (struct expression *) alloca (len);
+
+ /* Copy the original expression into temp. */
+ bcopy (expr, temp, len);
+
+ prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the subexpression of EXPR
+ whose last exp_element is at index ENDPOS - 1 in EXPR. */
+
+static int
+length_of_subexp (expr, endpos)
+ register struct expression *expr;
+ register int endpos;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+
+ if (endpos < 0)
+ error ("?error in length_of_subexp");
+
+ i = (int) expr->elts[endpos - 1].opcode;
+
+ switch (i)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((expr->elts[endpos - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ oplen = 4;
+ break;
+
+ case OP_VAR_VALUE:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + expr->elts[endpos - 2].longconst;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ case OP_STRING:
+ oplen = 3 + ((expr->elts[endpos - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + (i < (int) BINOP_END);
+ }
+
+ while (args > 0)
+ {
+ oplen += length_of_subexp (expr, endpos - oplen);
+ args--;
+ }
+
+ return oplen;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+ into OUTEXPR, starting at index OUTBEG.
+ In the process, convert it from suffix to prefix form. */
+
+static void
+prefixify_subexp (inexpr, outexpr, inend, outbeg)
+ register struct expression *inexpr;
+ struct expression *outexpr;
+ register int inend;
+ int outbeg;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+ int *arglens;
+ enum exp_opcode opcode;
+
+ /* Compute how long the last operation is (in OPLEN),
+ and also how many preceding subexpressions serve as
+ arguments for it (in ARGS). */
+
+ opcode = inexpr->elts[inend - 1].opcode;
+ switch (opcode)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((inexpr->elts[inend - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ oplen = 4;
+ break;
+
+ case OP_VAR_VALUE:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + inexpr->elts[inend - 2].longconst;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ case OP_STRING:
+ oplen = 3 + ((inexpr->elts[inend - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + ((int) opcode < (int) BINOP_END);
+ }
+
+ /* Copy the final operator itself, from the end of the input
+ to the beginning of the output. */
+ inend -= oplen;
+ bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg],
+ oplen * sizeof (union exp_element));
+ outbeg += oplen;
+
+ /* Find the lengths of the arg subexpressions. */
+ arglens = (int *) alloca (args * sizeof (int));
+ for (i = args - 1; i >= 0; i--)
+ {
+ oplen = length_of_subexp (inexpr, inend);
+ arglens[i] = oplen;
+ inend -= oplen;
+ }
+
+ /* Now copy each subexpression, preserving the order of
+ the subexpressions, but prefixifying each one.
+ In this loop, inend starts at the beginning of
+ the expression this level is working on
+ and marches forward over the arguments.
+ outbeg does similarly in the output. */
+ for (i = 0; i < args; i++)
+ {
+ oplen = arglens[i];
+ inend += oplen;
+ prefixify_subexp (inexpr, outexpr, inend, outbeg);
+ outbeg += oplen;
+ }
+}
+
+/* This page contains the two entry points to this file. */
+
+/* Read a C expression from the string *STRINGPTR points to,
+ parse it, and return a pointer to a struct expression that we malloc.
+ Use block BLOCK as the lexical context for variable names;
+ if BLOCK is zero, use the block of the selected stack frame.
+ Meanwhile, advance *STRINGPTR to point after the expression,
+ at the first nonwhite character that is not part of the expression
+ (possibly a null character).
+
+ If COMMA is nonzero, stop if a comma is reached. */
+
+struct expression *
+parse_c_1 (stringptr, block, comma)
+ char **stringptr;
+ struct block *block;
+{
+ struct cleanup *old_chain;
+
+ lexptr = *stringptr;
+
+ paren_depth = 0;
+ type_stack_depth = 0;
+
+ comma_terminates = comma;
+
+ if (lexptr == 0 || *lexptr == 0)
+ error_no_arg ("expression to compute");
+
+ old_chain = make_cleanup (free_funcalls, 0);
+ funcall_chain = 0;
+
+ expression_context_block = block ? block : get_selected_block ();
+
+ namecopy = (char *) alloca (strlen (lexptr) + 1);
+ expout_size = 10;
+ expout_ptr = 0;
+ expout = (struct expression *)
+ xmalloc (sizeof (struct expression)
+ + expout_size * sizeof (union exp_element));
+ make_cleanup (free_current_contents, &expout);
+ if (yyparse ())
+ yyerror ();
+ discard_cleanups (old_chain);
+ expout->nelts = expout_ptr;
+ expout = (struct expression *)
+ xrealloc (expout,
+ sizeof (struct expression)
+ + expout_ptr * sizeof (union exp_element));
+ prefixify_expression (expout);
+ *stringptr = lexptr;
+ return expout;
+}
+
+/* Parse STRING as an expression, and complain if this fails
+ to use up all of the contents of STRING. */
+
+struct expression *
+parse_c_expression (string)
+ char *string;
+{
+ register struct expression *exp;
+ exp = parse_c_1 (&string, 0, 0);
+ if (*string)
+ error ("Junk after end of expression.");
+ return exp;
+}
+
+static void
+push_type (tp)
+ enum type_pieces tp;
+{
+ if (type_stack_depth == type_stack_size)
+ {
+ type_stack_size *= 2;
+ type_stack = (enum type_pieces *)
+ xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces));
+ }
+ type_stack[type_stack_depth++] = tp;
+}
+
+static enum type_pieces
+pop_type ()
+{
+ if (type_stack_depth)
+ return type_stack[--type_stack_depth];
+ return tp_end;
+}
+
+void
+_initialize_expread ()
+{
+ type_stack_size = 80;
+ type_stack_depth = 0;
+ type_stack = (enum type_pieces *)
+ xmalloc (type_stack_size * sizeof (enum type_pieces));
+}
diff --git a/gnu/usr.bin/kgdb/expression.h b/gnu/usr.bin/kgdb/expression.h
new file mode 100644
index 000000000000..5a5e20e0606c
--- /dev/null
+++ b/gnu/usr.bin/kgdb/expression.h
@@ -0,0 +1,191 @@
+/* Definitions for expressions stored in reversed prefix form, for GDB.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Definitions for saved C expressions. */
+
+/* An expression is represented as a vector of union exp_element's.
+ Each exp_element is an opcode, except that some opcodes cause
+ the following exp_element to be treated as a long or double constant
+ or as a variable. The opcodes are obeyed, using a stack for temporaries.
+ The value is left on the temporary stack at the end. */
+
+/* When it is necessary to include a string,
+ it can occupy as many exp_elements as it needs.
+ We find the length of the string using strlen,
+ divide to find out how many exp_elements are used up,
+ and skip that many. Strings, like numbers, are indicated
+ by the preceding opcode. */
+
+enum exp_opcode
+{
+/* BINOP_... operate on two values computed by following subexpressions,
+ replacing them by one result value. They take no immediate arguments. */
+ BINOP_ADD, /* + */
+ BINOP_SUB, /* - */
+ BINOP_MUL, /* * */
+ BINOP_DIV, /* / */
+ BINOP_REM, /* % */
+ BINOP_LSH, /* << */
+ BINOP_RSH, /* >> */
+ BINOP_AND, /* && */
+ BINOP_OR, /* || */
+ BINOP_LOGAND, /* & */
+ BINOP_LOGIOR, /* | */
+ BINOP_LOGXOR, /* ^ */
+ BINOP_EQUAL, /* == */
+ BINOP_NOTEQUAL, /* != */
+ BINOP_LESS, /* < */
+ BINOP_GTR, /* > */
+ BINOP_LEQ, /* <= */
+ BINOP_GEQ, /* >= */
+ BINOP_REPEAT, /* @ */
+ BINOP_ASSIGN, /* = */
+ BINOP_COMMA, /* , */
+ BINOP_SUBSCRIPT, /* x[y] */
+ BINOP_EXP, /* Exponentiation */
+
+/* C++. */
+ BINOP_MIN, /* <? */
+ BINOP_MAX, /* >? */
+ BINOP_SCOPE, /* :: */
+
+ /* STRUCTOP_MEMBER is used for pointer-to-member constructs.
+ X . * Y translates into X STRUCTOP_MEMBER Y. */
+ STRUCTOP_MEMBER,
+ /* STRUCTOP_MPTR is used for pointer-to-member constructs
+ when X is a pointer instead of an aggregate. */
+ STRUCTOP_MPTR,
+/* end of C++. */
+
+ BINOP_END,
+
+ BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
+ The following exp_element is another opcode,
+ a BINOP_, saying how to modify.
+ Then comes another BINOP_ASSIGN_MODIFY,
+ making three exp_elements in total. */
+
+/* Operates on three values computed by following subexpressions. */
+ TERNOP_COND, /* ?: */
+
+/* The OP_... series take immediate following arguments.
+ After the arguments come another OP_... (the same one)
+ so that the grouping can be recognized from the end. */
+
+/* OP_LONG is followed by a type pointer in the next exp_element
+ and the long constant value in the following exp_element.
+ Then comes another OP_LONG.
+ Thus, the operation occupies four exp_elements. */
+
+ OP_LONG,
+/* OP_DOUBLE is similar but takes a double constant instead of a long one. */
+ OP_DOUBLE,
+/* OP_VAR_VALUE takes one struct symbol * in the following exp_element,
+ followed by another OP_VAR_VALUE, making three exp_elements. */
+ OP_VAR_VALUE,
+/* OP_LAST is followed by an integer in the next exp_element.
+ The integer is zero for the last value printed,
+ or it is the absolute number of a history element.
+ With another OP_LAST at the end, this makes three exp_elements. */
+ OP_LAST,
+/* OP_REGISTER is followed by an integer in the next exp_element.
+ This is the number of a register to fetch (as an int).
+ With another OP_REGISTER at the end, this makes three exp_elements. */
+ OP_REGISTER,
+/* OP_INTERNALVAR is followed by an internalvar ptr in the next exp_element.
+ With another OP_INTERNALVAR at the end, this makes three exp_elements. */
+ OP_INTERNALVAR,
+/* OP_FUNCALL is followed by an integer in the next exp_element.
+ The integer is the number of args to the function call.
+ That many plus one values from following subexpressions
+ are used, the first one being the function.
+ The integer is followed by a repeat of OP_FUNCALL,
+ making three exp_elements. */
+ OP_FUNCALL,
+/* OP_STRING represents a string constant.
+ Its format is the same as that of a STRUCTOP, but the string
+ data is just made into a string constant when the operation
+ is executed. */
+ OP_STRING,
+
+/* UNOP_CAST is followed by a type pointer in the next exp_element.
+ With another UNOP_CAST at the end, this makes three exp_elements.
+ It casts the value of the following subexpression. */
+ UNOP_CAST,
+/* UNOP_MEMVAL is followed by a type pointer in the next exp_element
+ With another UNOP_MEMVAL at the end, this makes three exp_elements.
+ It casts the contents of the word addressed by the value of the
+ following subexpression. */
+ UNOP_MEMVAL,
+/* UNOP_... operate on one value from a following subexpression
+ and replace it with a result. They take no immediate arguments. */
+ UNOP_NEG, /* Unary - */
+ UNOP_ZEROP, /* Unary ! */
+ UNOP_LOGNOT, /* Unary ~ */
+ UNOP_IND, /* Unary * */
+ UNOP_ADDR, /* Unary & */
+ UNOP_PREINCREMENT, /* ++ before an expression */
+ UNOP_POSTINCREMENT, /* ++ after an expression */
+ UNOP_PREDECREMENT, /* -- before an expression */
+ UNOP_POSTDECREMENT, /* -- after an expression */
+ UNOP_SIZEOF, /* Unary sizeof (followed by expression) */
+
+/* STRUCTOP_... operate on a value from a following subexpression
+ by extracting a structure component specified by a string
+ that appears in the following exp_elements (as many as needed).
+ STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->".
+ They differ only in the error message given in case the value is
+ not suitable or the structure component specified is not found.
+
+ The length of the string follows in the next exp_element,
+ (after the string), followed by another STRUCTOP_... code. */
+ STRUCTOP_STRUCT,
+ STRUCTOP_PTR,
+
+/* C++ */
+ /* OP_THIS is just a placeholder for the class instance variable.
+ It just comes in a tight (OP_THIS, OP_THIS) pair. */
+ OP_THIS,
+
+ /* OP_SCOPE surrounds a type name and a field name. The type
+ name is encoded as one element, but the field name stays as
+ a string, which, of course, is variable length. */
+ OP_SCOPE,
+
+};
+
+union exp_element
+{
+ enum exp_opcode opcode;
+ struct symbol *symbol;
+ LONGEST longconst;
+ double doubleconst;
+ char string;
+ struct type *type;
+ struct internalvar *internalvar;
+};
+
+struct expression
+{
+ int nelts;
+ union exp_element elts[1];
+};
+
+struct expression *parse_c_expression ();
+struct expression *parse_c_1 ();
diff --git a/gnu/usr.bin/kgdb/findvar.c b/gnu/usr.bin/kgdb/findvar.c
new file mode 100644
index 000000000000..0157d101e9a4
--- /dev/null
+++ b/gnu/usr.bin/kgdb/findvar.c
@@ -0,0 +1,579 @@
+/* Find a variable's value in memory, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "value.h"
+
+CORE_ADDR read_register ();
+
+/* Return the address in which frame FRAME's value of register REGNUM
+ has been saved in memory. Or return zero if it has not been saved.
+ If REGNUM specifies the SP, the value we return is actually
+ the SP value, not an address where it was saved. */
+
+CORE_ADDR
+find_saved_register (frame, regnum)
+ FRAME frame;
+ int regnum;
+{
+ struct frame_info *fi;
+ struct frame_saved_regs saved_regs;
+
+ register FRAME frame1 = 0;
+ register CORE_ADDR addr = 0;
+
+#ifdef HAVE_REGISTER_WINDOWS
+ /* We assume that a register in a register window will only be saved
+ in one place (since the name changes and disappears as you go
+ towards inner frames), so we only call get_frame_saved_regs on
+ the current frame. This is directly in contradiction to the
+ usage below, which assumes that registers used in a frame must be
+ saved in a lower (more interior) frame. This change is a result
+ of working on a register window machine; get_frame_saved_regs
+ always returns the registers saved within a frame, within the
+ context (register namespace) of that frame. */
+
+ /* However, note that we don't want this to return anything if
+ nothing is saved (if there's a frame inside of this one). Also,
+ callers to this routine asking for the stack pointer want the
+ stack pointer saved for *this* frame; this is returned from the
+ next frame. */
+
+
+ if (REGISTER_IN_WINDOW_P(regnum))
+ {
+ frame1 = get_next_frame (frame);
+ if (!frame1) return 0; /* Registers of this frame are
+ active. */
+
+ /* Get the SP from the next frame in; it will be this
+ current frame. */
+ if (regnum != SP_REGNUM)
+ frame1 = frame;
+
+ fi = get_frame_info (frame1);
+ get_frame_saved_regs (fi, &saved_regs);
+ return (saved_regs.regs[regnum] ?
+ saved_regs.regs[regnum] : 0);
+ }
+#endif /* HAVE_REGISTER_WINDOWS */
+
+ /* Note that this next routine assumes that registers used in
+ frame x will be saved only in the frame that x calls and
+ frames interior to it. This is not true on the sparc, but the
+ above macro takes care of it, so we should be all right. */
+ while (1)
+ {
+ QUIT;
+ frame1 = get_prev_frame (frame1);
+ if (frame1 == 0 || frame1 == frame)
+ break;
+ fi = get_frame_info (frame1);
+ get_frame_saved_regs (fi, &saved_regs);
+ if (saved_regs.regs[regnum])
+ addr = saved_regs.regs[regnum];
+ }
+
+ return addr;
+}
+
+/* Copy the bytes of register REGNUM, relative to the current stack frame,
+ into our memory at MYADDR.
+ The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). */
+
+void
+read_relative_register_raw_bytes (regnum, myaddr)
+ int regnum;
+ char *myaddr;
+{
+ register CORE_ADDR addr;
+
+ if (regnum == FP_REGNUM)
+ {
+ bcopy (&FRAME_FP(selected_frame), myaddr, sizeof (CORE_ADDR));
+ return;
+ }
+
+ addr = find_saved_register (selected_frame, regnum);
+
+ if (addr)
+ {
+ if (regnum == SP_REGNUM)
+ {
+ CORE_ADDR buffer = addr;
+ bcopy (&buffer, myaddr, sizeof (CORE_ADDR));
+ }
+ else
+ read_memory (addr, myaddr, REGISTER_RAW_SIZE (regnum));
+ return;
+ }
+ read_register_bytes (REGISTER_BYTE (regnum),
+ myaddr, REGISTER_RAW_SIZE (regnum));
+}
+
+/* Return a `value' with the contents of register REGNUM
+ in its virtual format, with the type specified by
+ REGISTER_VIRTUAL_TYPE. */
+
+value
+value_of_register (regnum)
+ int regnum;
+{
+ register CORE_ADDR addr;
+ register value val;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+ if (! (have_inferior_p () || have_core_file_p ()))
+ error ("Can't get value of register without inferior or core file");
+
+ addr = find_saved_register (selected_frame, regnum);
+ if (addr)
+ {
+ if (regnum == SP_REGNUM)
+ return value_from_long (builtin_type_int, (LONGEST) addr);
+ read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
+ }
+ else
+ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer,
+ REGISTER_RAW_SIZE (regnum));
+
+ REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
+ val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+ bcopy (virtual_buffer, VALUE_CONTENTS (val), REGISTER_VIRTUAL_SIZE (regnum));
+ VALUE_LVAL (val) = addr ? lval_memory : lval_register;
+ VALUE_ADDRESS (val) = addr ? addr : REGISTER_BYTE (regnum);
+ VALUE_REGNO (val) = regnum;
+ return val;
+}
+
+/* Low level examining and depositing of registers.
+
+ Note that you must call `fetch_registers' once
+ before examining or depositing any registers. */
+
+char registers[REGISTER_BYTES];
+
+/* Copy LEN bytes of consecutive data from registers
+ starting with the REGBYTE'th byte of register data
+ into memory at MYADDR. */
+
+void
+read_register_bytes (regbyte, myaddr, len)
+ int regbyte;
+ char *myaddr;
+ int len;
+{
+ bcopy (&registers[regbyte], myaddr, len);
+}
+
+/* Copy LEN bytes of consecutive data from memory at MYADDR
+ into registers starting with the REGBYTE'th byte of register data. */
+
+void
+write_register_bytes (regbyte, myaddr, len)
+ int regbyte;
+ char *myaddr;
+ int len;
+{
+ bcopy (myaddr, &registers[regbyte], len);
+ if (have_inferior_p ())
+ store_inferior_registers (-1);
+}
+
+/* Return the contents of register REGNO,
+ regarding it as an integer. */
+
+CORE_ADDR
+read_register (regno)
+ int regno;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+ return *(int *) &registers[REGISTER_BYTE (regno)];
+}
+
+/* Store VALUE in the register number REGNO, regarded as an integer. */
+
+void
+write_register (regno, val)
+ int regno, val;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+#if defined(sun4)
+ /* This is a no-op on a Sun 4. */
+ if (regno == 0)
+ return;
+#endif
+
+ *(int *) &registers[REGISTER_BYTE (regno)] = val;
+
+ if (have_inferior_p ())
+ store_inferior_registers (regno);
+}
+
+/* Record that register REGNO contains VAL.
+ This is used when the value is obtained from the inferior or core dump,
+ so there is no need to store the value there. */
+
+void
+supply_register (regno, val)
+ int regno;
+ char *val;
+{
+ bcopy (val, &registers[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno));
+}
+
+/* Given a struct symbol for a variable,
+ and a stack frame id, read the value of the variable
+ and return a (pointer to a) struct value containing the value. */
+
+value
+read_var_value (var, frame)
+ register struct symbol *var;
+ FRAME frame;
+{
+ register value v;
+
+ struct frame_info *fi;
+
+ struct type *type = SYMBOL_TYPE (var);
+ register CORE_ADDR addr = 0;
+ int val = SYMBOL_VALUE (var);
+ register int len;
+
+ v = allocate_value (type);
+ VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
+ len = TYPE_LENGTH (type);
+
+ if (frame == 0) frame = selected_frame;
+
+ switch (SYMBOL_CLASS (var))
+ {
+ case LOC_CONST:
+ case LOC_LABEL:
+ bcopy (&val, VALUE_CONTENTS (v), len);
+ VALUE_LVAL (v) = not_lval;
+ return v;
+
+ case LOC_CONST_BYTES:
+ bcopy (val, VALUE_CONTENTS (v), len);
+ VALUE_LVAL (v) = not_lval;
+ return v;
+
+ case LOC_STATIC:
+ addr = val;
+ break;
+
+/* Nonzero if a struct which is located in a register or a LOC_ARG
+ really contains
+ the address of the struct, not the struct itself. GCC_P is nonzero
+ if the function was compiled with GCC. */
+#if !defined (REG_STRUCT_HAS_ADDR)
+#define REG_STRUCT_HAS_ADDR(gcc_p) 0
+#endif
+
+ case LOC_ARG:
+ fi = get_frame_info (frame);
+ addr = val + FRAME_ARGS_ADDRESS (fi);
+ break;
+
+ case LOC_REF_ARG:
+ fi = get_frame_info (frame);
+ addr = val + FRAME_ARGS_ADDRESS (fi);
+ addr = read_memory_integer (addr, sizeof (CORE_ADDR));
+ break;
+
+ case LOC_LOCAL:
+ fi = get_frame_info (frame);
+ addr = val + FRAME_LOCALS_ADDRESS (fi);
+ break;
+
+ case LOC_TYPEDEF:
+ error ("Cannot look up value of a typedef");
+
+ case LOC_BLOCK:
+ VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+ return v;
+
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ {
+ struct block *b = get_frame_block (frame);
+
+ v = value_from_register (type, val, frame);
+
+ if (REG_STRUCT_HAS_ADDR(b->gcc_compile_flag)
+ && TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ addr = *(CORE_ADDR *)VALUE_CONTENTS (v);
+ else
+ return v;
+ }
+ }
+
+ read_memory (addr, VALUE_CONTENTS (v), len);
+ VALUE_ADDRESS (v) = addr;
+ return v;
+}
+
+/* Return a value of type TYPE, stored in register REGNUM, in frame
+ FRAME. */
+
+value
+value_from_register (type, regnum, frame)
+ struct type *type;
+ int regnum;
+ FRAME frame;
+{
+ char raw_buffer [MAX_REGISTER_RAW_SIZE];
+ char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+ CORE_ADDR addr;
+ value v = allocate_value (type);
+ int len = TYPE_LENGTH (type);
+ char *value_bytes = 0;
+ int value_bytes_copied = 0;
+ int num_storage_locs;
+
+ VALUE_REGNO (v) = regnum;
+
+ num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
+ ((len - 1) / REGISTER_RAW_SIZE (regnum)) + 1 :
+ 1);
+
+ if (num_storage_locs > 1)
+ {
+ /* Value spread across multiple storage locations. */
+
+ int local_regnum;
+ int mem_stor = 0, reg_stor = 0;
+ int mem_tracking = 1;
+ CORE_ADDR last_addr = 0;
+
+ value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE);
+
+ /* Copy all of the data out, whereever it may be. */
+
+ for (local_regnum = regnum;
+ value_bytes_copied < len;
+ (value_bytes_copied += REGISTER_RAW_SIZE (local_regnum),
+ ++local_regnum))
+ {
+ int register_index = local_regnum - regnum;
+ addr = find_saved_register (frame, local_regnum);
+ if (addr == 0)
+ {
+ read_register_bytes (REGISTER_BYTE (local_regnum),
+ value_bytes + value_bytes_copied,
+ REGISTER_RAW_SIZE (local_regnum));
+ reg_stor++;
+ }
+ else
+ {
+ read_memory (addr, value_bytes + value_bytes_copied,
+ REGISTER_RAW_SIZE (local_regnum));
+ mem_stor++;
+ mem_tracking =
+ (mem_tracking
+ && (regnum == local_regnum
+ || addr == last_addr));
+ }
+ last_addr = addr;
+ }
+
+ if ((reg_stor && mem_stor)
+ || (mem_stor && !mem_tracking))
+ /* Mixed storage; all of the hassle we just went through was
+ for some good purpose. */
+ {
+ VALUE_LVAL (v) = lval_reg_frame_relative;
+ VALUE_FRAME (v) = FRAME_FP (frame);
+ VALUE_FRAME_REGNUM (v) = regnum;
+ }
+ else if (mem_stor)
+ {
+ VALUE_LVAL (v) = lval_memory;
+ VALUE_ADDRESS (v) = find_saved_register (frame, regnum);
+ }
+ else if (reg_stor)
+ {
+ VALUE_LVAL (v) = lval_register;
+ VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
+ }
+ else
+ fatal ("value_from_register: Value not stored anywhere!");
+
+ /* Any structure stored in more than one register will always be
+ an inegral number of registers. Otherwise, you'd need to do
+ some fiddling with the last register copied here for little
+ endian machines. */
+
+ /* Copy into the contents section of the value. */
+ bcopy (value_bytes, VALUE_CONTENTS (v), len);
+
+ return v;
+ }
+
+ /* Data is completely contained within a single register. Locate the
+ register's contents in a real register or in core;
+ read the data in raw format. */
+
+ addr = find_saved_register (frame, regnum);
+ if (addr == 0)
+ {
+ /* Value is really in a register. */
+
+ VALUE_LVAL (v) = lval_register;
+ VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
+
+ read_register_bytes (REGISTER_BYTE (regnum),
+ raw_buffer, REGISTER_RAW_SIZE (regnum));
+ }
+ else
+ {
+ /* Value was in a register that has been saved in memory. */
+
+ read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
+ VALUE_LVAL (v) = lval_memory;
+ VALUE_ADDRESS (v) = addr;
+ }
+
+ /* Convert the raw contents to virtual contents.
+ (Just copy them if the formats are the same.) */
+
+ REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
+
+ if (REGISTER_CONVERTIBLE (regnum))
+ {
+ /* When the raw and virtual formats differ, the virtual format
+ corresponds to a specific data type. If we want that type,
+ copy the data into the value.
+ Otherwise, do a type-conversion. */
+
+ if (type != REGISTER_VIRTUAL_TYPE (regnum))
+ {
+ /* eg a variable of type `float' in a 68881 register
+ with raw type `extended' and virtual type `double'.
+ Fetch it as a `double' and then convert to `float'. */
+ v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+ bcopy (virtual_buffer, VALUE_CONTENTS (v), len);
+ v = value_cast (type, v);
+ }
+ else
+ bcopy (virtual_buffer, VALUE_CONTENTS (v), len);
+ }
+ else
+ {
+ /* Raw and virtual formats are the same for this register. */
+
+#ifdef BYTES_BIG_ENDIAN
+ if (len < REGISTER_RAW_SIZE (regnum))
+ {
+ /* Big-endian, and we want less than full size. */
+ VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
+ }
+#endif
+
+ bcopy (virtual_buffer + VALUE_OFFSET (v),
+ VALUE_CONTENTS (v), len);
+ }
+
+ return v;
+}
+
+/* Given a struct symbol for a variable,
+ and a stack frame id,
+ return a (pointer to a) struct value containing the variable's address. */
+
+value
+locate_var_value (var, frame)
+ register struct symbol *var;
+ FRAME frame;
+{
+ register CORE_ADDR addr = 0;
+ int val = SYMBOL_VALUE (var);
+ struct frame_info *fi;
+ struct type *type = SYMBOL_TYPE (var);
+ struct type *result_type;
+
+ if (frame == 0) frame = selected_frame;
+
+ switch (SYMBOL_CLASS (var))
+ {
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ error ("Address requested for identifier \"%s\" which is a constant.",
+ SYMBOL_NAME (var));
+
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ addr = find_saved_register (frame, val);
+ if (addr != 0)
+ {
+ int len = TYPE_LENGTH (type);
+#ifdef BYTES_BIG_ENDIAN
+ if (len < REGISTER_RAW_SIZE (val))
+ /* Big-endian, and we want less than full size. */
+ addr += REGISTER_RAW_SIZE (val) - len;
+#endif
+ break;
+ }
+ error ("Address requested for identifier \"%s\" which is in a register.",
+ SYMBOL_NAME (var));
+
+ case LOC_STATIC:
+ case LOC_LABEL:
+ addr = val;
+ break;
+
+ case LOC_ARG:
+ fi = get_frame_info (frame);
+ addr = val + FRAME_ARGS_ADDRESS (fi);
+ break;
+
+ case LOC_REF_ARG:
+ fi = get_frame_info (frame);
+ addr = val + FRAME_ARGS_ADDRESS (fi);
+ addr = read_memory_integer (addr, sizeof (CORE_ADDR));
+ break;
+
+ case LOC_LOCAL:
+ fi = get_frame_info (frame);
+ addr = val + FRAME_LOCALS_ADDRESS (fi);
+ break;
+
+ case LOC_TYPEDEF:
+ error ("Address requested for identifier \"%s\" which is a typedef.",
+ SYMBOL_NAME (var));
+
+ case LOC_BLOCK:
+ addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+ break;
+ }
+
+ /* Address of an array is of the type of address of it's elements. */
+ result_type =
+ lookup_pointer_type (TYPE_CODE (type) == TYPE_CODE_ARRAY ?
+ TYPE_TARGET_TYPE (type) : type);
+
+ return value_cast (result_type,
+ value_from_long (builtin_type_long, (LONGEST) addr));
+}
+
diff --git a/gnu/usr.bin/kgdb/frame.h b/gnu/usr.bin/kgdb/frame.h
new file mode 100644
index 000000000000..322ddbae04b9
--- /dev/null
+++ b/gnu/usr.bin/kgdb/frame.h
@@ -0,0 +1,115 @@
+/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Note that frame.h requires param.h! */
+
+/*
+ * FRAME is the type of the identifier of a specific stack frame. It
+ * is a pointer to the frame cache item corresponding to this frame.
+ * Please note that frame id's are *not* constant over calls to the
+ * inferior. Use frame addresses, which are.
+ *
+ * FRAME_ADDR is the type of the address of a specific frame. I
+ * cannot imagine a case in which this would not be CORE_ADDR, so
+ * maybe it's silly to give it it's own type. Life's rough.
+ *
+ * FRAME_FP is a macro which converts from a frame identifier into a
+ * frame_address.
+ *
+ * FRAME_INFO_ID is a macro which "converts" from a frame info pointer
+ * to a frame id. This is here in case I or someone else decides to
+ * change the FRAME type again.
+ *
+ * This file and blockframe.c are the only places which are allowed to
+ * use the equivalence between FRAME and struct frame_info *. EXCEPTION:
+ * value.h uses CORE_ADDR instead of FRAME_ADDR because the compiler
+ * will accept that in the absense of this file.
+ */
+typedef struct frame_info *FRAME;
+typedef CORE_ADDR FRAME_ADDR;
+#define FRAME_FP(fr) ((fr)->frame)
+#define FRAME_INFO_ID(f) (f)
+
+/*
+ * Caching structure for stack frames. This is also the structure
+ * used for extended info about stack frames. May add more to this
+ * structure as it becomes necessary.
+ *
+ * Note that the first entry in the cache will always refer to the
+ * innermost executing frame. This value should be set (is it?
+ * Check) in something like normal_stop.
+ */
+struct frame_info
+ {
+ /* Nominal address of the frame described. */
+ FRAME_ADDR frame;
+ /* Address at which execution is occurring in this frame.
+ For the innermost frame, it's the current pc.
+ For other frames, it is a pc saved in the next frame. */
+ CORE_ADDR pc;
+ /* The frame called by the frame we are describing, or 0.
+ This may be set even if there isn't a frame called by the one
+ we are describing (.->next == 0); in that case it is simply the
+ bottom of this frame */
+ FRAME_ADDR next_frame;
+ /* Anything extra for this structure that may have been defined
+ in the machine depedent files. */
+#ifdef EXTRA_FRAME_INFO
+ EXTRA_FRAME_INFO
+#endif
+ /* Pointers to the next and previous frame_info's in this stack. */
+ FRAME next, prev;
+ };
+
+/* Describe the saved registers of a frame. */
+
+struct frame_saved_regs
+ {
+ /* For each register, address of where it was saved on entry to the frame,
+ or zero if it was not saved on entry to this frame. */
+ CORE_ADDR regs[NUM_REGS];
+ };
+
+/* The stack frame that the user has specified for commands to act on.
+ Note that one cannot assume this is the address of valid data. */
+
+extern FRAME selected_frame;
+
+extern struct frame_info *get_frame_info ();
+extern struct frame_info *get_prev_frame_info ();
+
+extern FRAME create_new_frame ();
+
+extern void get_frame_saved_regs ();
+
+extern FRAME get_prev_frame ();
+extern FRAME get_current_frame ();
+extern FRAME get_next_frame ();
+
+extern struct block *get_frame_block ();
+extern struct block *get_current_block ();
+extern struct block *get_selected_block ();
+extern struct symbol *get_frame_function ();
+extern struct symbol *get_pc_function ();
+
+/* In stack.c */
+extern FRAME find_relative_frame ();
+
+/* Generic pointer value indicating "I don't know." */
+#define Frame_unknown (CORE_ADDR)-1
diff --git a/gnu/usr.bin/kgdb/getpagesize.h b/gnu/usr.bin/kgdb/getpagesize.h
new file mode 100644
index 000000000000..32adae61efa2
--- /dev/null
+++ b/gnu/usr.bin/kgdb/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/usr.bin/kgdb/infcmd.c b/gnu/usr.bin/kgdb/infcmd.c
new file mode 100644
index 000000000000..a9db0c6749c5
--- /dev/null
+++ b/gnu/usr.bin/kgdb/infcmd.c
@@ -0,0 +1,1200 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)infcmd.c 6.4 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Memory-access and commands for inferior process, for GDB.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+
+#include <signal.h>
+#include <sys/param.h>
+
+#define ERROR_NO_INFERIOR \
+ if (inferior_pid == 0) error ("The program is not being run.");
+
+/* String containing arguments to give to the program,
+ with a space added at the front. Just a space means no args. */
+
+static char *inferior_args;
+
+/* File name for default use for standard in/out in the inferior. */
+
+char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now. */
+
+int inferior_pid;
+
+/* Last signal that the inferior received (why it stopped). */
+
+int stop_signal;
+
+/* Address at which inferior stopped. */
+
+CORE_ADDR stop_pc;
+
+/* Stack frame when program stopped. */
+
+FRAME_ADDR stop_frame_address;
+
+/* Number of breakpoint it stopped at, or 0 if none. */
+
+int stop_breakpoint;
+
+/* Nonzero if stopped due to a step command. */
+
+int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine. */
+
+int stop_stack_dummy;
+
+/* Nonzero if stopped due to a random (unexpected) signal in inferior
+ process. */
+
+int stopped_by_random_signal;
+
+/* Range to single step within.
+ If this is nonzero, respond to a single-step signal
+ by continuing to step if the pc is in this range. */
+
+CORE_ADDR step_range_start; /* Inclusive */
+CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+ This is how we know when we step into a subroutine call,
+ and how to set the frame for the breakpoint used to step out. */
+
+FRAME_ADDR step_frame_address;
+
+/* 1 means step over all subroutine calls.
+ -1 means step over calls to undebuggable functions. */
+
+int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+ so don't print frame next time inferior stops
+ if it stops due to stepping. */
+
+int step_multi;
+
+/* Environment to use for running inferior,
+ in format described in environ.h. */
+
+struct environ *inferior_environ;
+
+CORE_ADDR read_pc ();
+struct command_line *get_breakpoint_commands ();
+void breakpoint_clear_ignore_counts ();
+
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
+
+static void
+set_args_command (args)
+ char *args;
+{
+ free (inferior_args);
+ if (!args) args = "";
+ inferior_args = concat (" ", args, "");
+}
+
+void
+tty_command (file, from_tty)
+ char *file;
+ int from_tty;
+{
+ if (file == 0)
+ error_no_arg ("terminal name for running target process");
+
+ inferior_io_terminal = savestring (file, strlen (file));
+}
+
+static void
+run_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern char **environ;
+ register int i;
+ char *exec_file;
+ char *allargs;
+
+ extern int sys_nerr;
+ extern int errno;
+
+ dont_repeat ();
+
+ if (inferior_pid)
+ {
+ extern int inhibit_confirm;
+ if (!(inhibit_confirm ||
+ query ("The program being debugged has been started already.\n\
+Start it from the beginning? ")))
+ error ("Program not restarted.");
+ kill_inferior ();
+ }
+
+#if 0
+ /* On the other hand, some users want to do
+ break open
+ ignore 1 40
+ run
+ So it's not clear what is best. */
+
+ /* It is confusing to the user for ignore counts to stick around
+ from previous runs of the inferior. So clear them. */
+ breakpoint_clear_ignore_counts ();
+#endif
+
+ exec_file = (char *) get_exec_file (1);
+
+ if (remote_debugging)
+ {
+ if (from_tty)
+ {
+ printf ("Starting program: %s\n", exec_file);
+ fflush (stdout);
+ }
+ }
+ else
+ {
+ if (args)
+ set_args_command (args);
+
+ if (from_tty)
+ {
+ printf ("Starting program: %s%s\n",
+ exec_file, inferior_args);
+ fflush (stdout);
+ }
+
+ allargs = concat ("exec ", exec_file, inferior_args);
+ inferior_pid = create_inferior (allargs, environ_vector (inferior_environ));
+ }
+
+ clear_proceed_status ();
+
+ start_inferior ();
+}
+
+void
+cont_command (proc_count_exp, from_tty)
+ char *proc_count_exp;
+ int from_tty;
+{
+ ERROR_NO_INFERIOR;
+
+ clear_proceed_status ();
+
+ /* If have argument, set proceed count of breakpoint we stopped at. */
+
+ if (stop_breakpoint > 0 && proc_count_exp)
+ {
+ set_ignore_count (stop_breakpoint,
+ parse_and_eval_address (proc_count_exp) - 1,
+ from_tty);
+ if (from_tty)
+ printf (" ");
+ }
+
+ if (from_tty)
+ printf ("Continuing.\n");
+
+ proceed (-1, -1, 0);
+}
+
+/* Step until outside of current statement. */
+static void step_1 ();
+
+static void
+step_command (count_string)
+{
+ step_1 (0, 0, count_string);
+}
+
+/* Likewise, but skip over subroutine calls as if single instructions. */
+
+static void
+next_command (count_string)
+{
+ step_1 (1, 0, count_string);
+}
+
+/* Likewise, but step only one instruction. */
+
+static void
+stepi_command (count_string)
+{
+ step_1 (0, 1, count_string);
+}
+
+static void
+nexti_command (count_string)
+{
+ step_1 (1, 1, count_string);
+}
+
+static void
+step_1 (skip_subroutines, single_inst, count_string)
+ int skip_subroutines;
+ int single_inst;
+ char *count_string;
+{
+ register int count = 1;
+
+ ERROR_NO_INFERIOR;
+ count = count_string ? parse_and_eval_address (count_string) : 1;
+
+ for (; count > 0; count--)
+ {
+ clear_proceed_status ();
+
+ step_frame_address = FRAME_FP (get_current_frame ());
+
+ if (! single_inst)
+ {
+ find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
+ if (step_range_end == 0)
+ {
+ int misc;
+
+ misc = find_pc_misc_function (stop_pc);
+ terminal_ours ();
+ printf ("Current function has no line number information.\n");
+ fflush (stdout);
+
+ /* No info or after _etext ("Can't happen") */
+ if (misc == -1 || misc == misc_function_count - 1)
+ error ("No data available on pc function.");
+
+ printf ("Single stepping until function exit.\n");
+ fflush (stdout);
+
+ step_range_start = misc_function_vector[misc].address;
+ step_range_end = misc_function_vector[misc + 1].address;
+ }
+ }
+ else
+ {
+ /* Say we are stepping, but stop after one insn whatever it does.
+ Don't step through subroutine calls even to undebuggable
+ functions. */
+ step_range_start = step_range_end = 1;
+ if (!skip_subroutines)
+ step_over_calls = 0;
+ }
+
+ if (skip_subroutines)
+ step_over_calls = 1;
+
+ step_multi = (count > 1);
+ proceed (-1, -1, 1);
+ if (! stop_step)
+ break;
+ }
+}
+
+/* Continue program at specified address. */
+
+static void
+jump_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register CORE_ADDR addr;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+
+ ERROR_NO_INFERIOR;
+
+ if (!arg)
+ error_no_arg ("starting address");
+
+ sals = decode_line_spec_1 (arg, 1);
+ if (sals.nelts != 1)
+ {
+ error ("Unreasonable jump request");
+ }
+
+ sal = sals.sals[0];
+ free (sals.sals);
+
+ if (sal.symtab == 0 && sal.pc == 0)
+ error ("No source file has been specified.");
+
+ if (sal.pc == 0)
+ sal.pc = find_line_pc (sal.symtab, sal.line);
+
+ {
+ struct symbol *fn = get_frame_function (get_current_frame ());
+ struct symbol *sfn = find_pc_function (sal.pc);
+ if (fn != 0 && sfn != fn
+ && ! query ("Line %d is not in `%s'. Jump anyway? ",
+ sal.line, SYMBOL_NAME (fn)))
+ error ("Not confirmed.");
+ }
+
+ if (sal.pc == 0)
+ error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
+
+ addr = sal.pc;
+
+ clear_proceed_status ();
+
+ if (from_tty)
+ printf ("Continuing at 0x%x.\n", addr);
+
+ proceed (addr, 0, 0);
+}
+
+/* Continue program giving it specified signal. */
+
+static void
+signal_command (signum_exp, from_tty)
+ char *signum_exp;
+ int from_tty;
+{
+ register int signum;
+
+ dont_repeat (); /* Too dangerous. */
+ ERROR_NO_INFERIOR;
+
+ if (!signum_exp)
+ error_no_arg ("signal number");
+
+ signum = parse_and_eval_address (signum_exp);
+
+ clear_proceed_status ();
+
+ if (from_tty)
+ printf ("Continuing with signal %d.\n", signum);
+
+ proceed (stop_pc, signum, 0);
+}
+
+/* Execute a "stack dummy", a piece of code stored in the stack
+ by the debugger to be executed in the inferior.
+
+ To call: first, do PUSH_DUMMY_FRAME.
+ Then push the contents of the dummy. It should end with a breakpoint insn.
+ Then call here, passing address at which to start the dummy.
+
+ The contents of all registers are saved before the dummy frame is popped
+ and copied into the buffer BUFFER.
+
+ The dummy's frame is automatically popped whenever that break is hit.
+ If that is the first time the program stops, run_stack_dummy
+ returns to its caller with that frame already gone.
+ Otherwise, the caller never gets returned to. */
+
+/* 4 => return instead of letting the stack dummy run. */
+
+static int stack_dummy_testing = 0;
+
+void
+run_stack_dummy (addr, buffer)
+ CORE_ADDR addr;
+ REGISTER_TYPE *buffer;
+{
+ /* Now proceed, having reached the desired place. */
+ clear_proceed_status ();
+#ifdef notdef
+ if (stack_dummy_testing & 4)
+ {
+ POP_FRAME;
+ return;
+ }
+#endif
+ proceed (addr, 0, 0);
+
+ if (!stop_stack_dummy)
+ error ("Cannot continue previously requested operation.");
+
+ /* On return, the stack dummy has been popped already. */
+
+ read_register_bytes(0, buffer, REGISTER_BYTES);
+}
+
+/* Proceed until we reach the given line as argument or exit the
+ function. When called with no argument, proceed until we reach a
+ different source line with pc greater than our current one or exit
+ the function. We skip calls in both cases.
+
+ The effect of this command with an argument is identical to setting
+ a momentary breakpoint at the line specified and executing
+ "finish".
+
+ Note that eventually this command should probably be changed so
+ that only source lines are printed out when we hit the breakpoint
+ we set. I'm going to postpone this until after a hopeful rewrite
+ of wait_for_inferior and the proceed status code. -- randy */
+
+void
+until_next_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ FRAME frame;
+ CORE_ADDR pc;
+ struct symbol *func;
+ struct symtab_and_line sal;
+
+ clear_proceed_status ();
+
+ frame = get_current_frame ();
+
+ /* Step until either exited from this function or greater
+ than the current line (if in symbolic section) or pc (if
+ not). */
+
+ pc = read_pc ();
+ func = find_pc_function (pc);
+
+ if (!func)
+ {
+ int misc_func = find_pc_misc_function (pc);
+
+ if (misc_func != -1)
+ error ("Execution is not within a known function.");
+
+ step_range_start = misc_function_vector[misc_func].address;
+ step_range_end = pc;
+ }
+ else
+ {
+ sal = find_pc_line (pc, 0);
+
+ step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
+ step_range_end = sal.end;
+ }
+
+ step_over_calls = 1;
+ step_frame_address = FRAME_FP (frame);
+
+ step_multi = 0; /* Only one call to proceed */
+
+ proceed (-1, -1, 1);
+}
+
+void
+until_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (!have_inferior_p ())
+ error ("The program is not being run.");
+
+ if (arg)
+ until_break_command (arg, from_tty);
+ else
+ until_next_command (arg, from_tty);
+}
+
+/* "finish": Set a temporary breakpoint at the place
+ the selected frame will return to, then continue. */
+
+static void
+finish_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtab_and_line sal;
+ register FRAME frame;
+ struct frame_info *fi;
+ register struct symbol *function;
+
+ if (!have_inferior_p ())
+ error ("The program is not being run.");
+ if (arg)
+ error ("The \"finish\" command does not take any arguments.");
+
+ frame = get_prev_frame (selected_frame);
+ if (frame == 0)
+ error ("\"finish\" not meaningful in the outermost frame.");
+
+ clear_proceed_status ();
+
+ fi = get_frame_info (frame);
+ sal = find_pc_line (fi->pc, 0);
+ sal.pc = fi->pc;
+ set_momentary_breakpoint (sal, frame);
+
+ /* Find the function we will return from. */
+
+ fi = get_frame_info (selected_frame);
+ function = find_pc_function (fi->pc);
+
+ if (from_tty)
+ {
+ printf ("Run till exit from ");
+ print_selected_frame ();
+ }
+
+ proceed (-1, -1, 0);
+
+ if (stop_breakpoint == -3 && function != 0)
+ {
+ struct type *value_type;
+ register value val;
+ CORE_ADDR funcaddr;
+ extern char registers[];
+
+ value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
+ if (!value_type)
+ fatal ("internal: finish_command: function has no target type");
+
+ if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
+ return;
+
+ funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));
+
+ val = value_being_returned (value_type, registers,
+ using_struct_return (function,
+ funcaddr,
+ value_type));
+
+ printf ("Value returned is $%d = ", record_latest_value (val));
+ value_print (val, stdout, 0, Val_no_prettyprint);
+ putchar ('\n');
+ }
+}
+
+static void
+program_info ()
+{
+ if (inferior_pid == 0)
+ {
+ printf ("The program being debugged is not being run.\n");
+ return;
+ }
+
+ printf ("Program being debugged is in process %d, stopped at 0x%x.\n",
+ inferior_pid, stop_pc);
+ if (stop_step)
+ printf ("It stopped after being stepped.\n");
+ else if (stop_breakpoint > 0)
+ printf ("It stopped at breakpoint %d.\n", stop_breakpoint);
+ else if (stop_signal)
+ printf ("It stopped with signal %d (%s).\n",
+ stop_signal, sys_siglist[stop_signal]);
+
+ printf ("\nType \"info stack\" or \"info reg\" for more information.\n");
+}
+
+static void
+environment_info (var)
+ char *var;
+{
+ if (var)
+ {
+ register char *val = get_in_environ (inferior_environ, var);
+ if (val)
+ printf ("%s = %s\n", var, val);
+ else
+ printf ("Environment variable \"%s\" not defined.\n", var);
+ }
+ else
+ {
+ register char **vector = environ_vector (inferior_environ);
+ while (*vector)
+ printf ("%s\n", *vector++);
+ }
+}
+
+static void
+set_environment_command (arg)
+ char *arg;
+{
+ register char *p, *val, *var;
+ int nullset = 0;
+
+ if (arg == 0)
+ error_no_arg ("environment variable and value");
+
+ /* Find seperation between variable name and value */
+ p = (char *) index (arg, '=');
+ val = (char *) index (arg, ' ');
+
+ if (p != 0 && val != 0)
+ {
+ /* We have both a space and an equals. If the space is before the
+ equals and the only thing between the two is more space, use
+ the equals */
+ if (p > val)
+ while (*val == ' ')
+ val++;
+
+ /* Take the smaller of the two. If there was space before the
+ "=", they will be the same right now. */
+ p = arg + min (p - arg, val - arg);
+ }
+ else if (val != 0 && p == 0)
+ p = val;
+
+ if (p == arg)
+ error_no_arg ("environment variable to set");
+
+ if (p == 0 || p[1] == 0)
+ {
+ nullset = 1;
+ if (p == 0)
+ p = arg + strlen (arg); /* So that savestring below will work */
+ }
+ else
+ {
+ /* Not setting variable value to null */
+ val = p + 1;
+ while (*val == ' ' || *val == '\t')
+ val++;
+ }
+
+ while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--;
+
+ var = savestring (arg, p - arg);
+ if (nullset)
+ {
+ printf ("Setting environment variable \"%s\" to null value.\n", var);
+ set_in_environ (inferior_environ, var, "");
+ }
+ else
+ set_in_environ (inferior_environ, var, val);
+ free (var);
+}
+
+static void
+unset_environment_command (var, from_tty)
+ char *var;
+ int from_tty;
+{
+ if (var == 0)
+ /* If there is no argument, delete all environment variables.
+ Ask for confirmation if reading from the terminal. */
+ if (!from_tty || query ("Delete all environment variables? "))
+ {
+ free_environ (inferior_environ);
+ inferior_environ = make_environ ();
+ }
+
+ unset_in_environ (inferior_environ, var);
+}
+
+/* Read an integer from debugged memory, given address and number of bytes. */
+
+long
+read_memory_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char cbuf;
+ short sbuf;
+ int ibuf;
+ long lbuf;
+ int result_err;
+ extern int sys_nerr;
+
+ if (len == sizeof (char))
+ {
+ result_err = read_memory (memaddr, &cbuf, len);
+ if (result_err)
+ error ("Error reading memory address 0x%x: %s (%d).",
+ memaddr, (result_err < sys_nerr ?
+ sys_errlist[result_err] :
+ "uknown error"), result_err);
+ return cbuf;
+ }
+ if (len == sizeof (short))
+ {
+ result_err = read_memory (memaddr, &sbuf, len);
+ if (result_err)
+ error ("Error reading memory address 0x%x: %s (%d).",
+ memaddr, (result_err < sys_nerr ?
+ sys_errlist[result_err] :
+ "uknown error"), result_err);
+ return sbuf;
+ }
+ if (len == sizeof (int))
+ {
+ result_err = read_memory (memaddr, &ibuf, len);
+ if (result_err)
+ error ("Error reading memory address 0x%x: %s (%d).",
+ memaddr, (result_err < sys_nerr ?
+ sys_errlist[result_err] :
+ "uknown error"), result_err);
+ return ibuf;
+ }
+ if (len == sizeof (lbuf))
+ {
+ result_err = read_memory (memaddr, &lbuf, len);
+ if (result_err)
+ error ("Error reading memory address 0x%x: %s (%d).",
+ memaddr, (result_err < sys_nerr ?
+ sys_errlist[result_err] :
+ "uknown error"), result_err);
+ return lbuf;
+ }
+ error ("Cannot handle integers of %d bytes.", len);
+}
+
+CORE_ADDR
+read_pc ()
+{
+ return (CORE_ADDR) read_register (PC_REGNUM);
+}
+
+void
+write_pc (val)
+ CORE_ADDR val;
+{
+ write_register (PC_REGNUM, (long) val);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, (long) val+4);
+#endif
+}
+
+char *reg_names[] = REGISTER_NAMES;
+
+#if !defined (DO_REGISTERS_INFO)
+static void
+print_one_register(i)
+ int i;
+{
+ unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+ REGISTER_TYPE val;
+
+ /* Get the data in raw format, then convert also to virtual format. */
+ read_relative_register_raw_bytes (i, raw_buffer);
+ REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
+
+ fputs_filtered (reg_names[i], stdout);
+ print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
+
+ /* If virtual format is floating, print it that way. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT
+ && ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0,
+ stdout, 0, 1, 0, Val_pretty_default);
+ /* Else if virtual format is too long for printf,
+ print in hex a byte at a time. */
+ else if (REGISTER_VIRTUAL_SIZE (i) > sizeof (long))
+ {
+ register int j;
+ printf_filtered ("0x");
+ for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
+ printf_filtered ("%02x", virtual_buffer[j]);
+ }
+ /* Else print as integer in hex and in decimal. */
+ else
+ {
+ long val;
+
+ bcopy (virtual_buffer, &val, sizeof (long));
+ if (val == 0)
+ printf_filtered ("0");
+ else
+ printf_filtered ("0x%08x %d", val, val);
+ }
+
+ /* If register has different raw and virtual formats,
+ print the raw format in hex now. */
+
+ if (REGISTER_CONVERTIBLE (i))
+ {
+ register int j;
+
+ printf_filtered (" (raw 0x");
+ for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+ printf_filtered ("%02x", raw_buffer[j]);
+ printf_filtered (")");
+ }
+ printf_filtered ("\n");
+}
+
+
+/* Print out the machine register regnum. If regnum is -1,
+ print all registers.
+ For most machines, having all_registers_info() print the
+ register(s) one per line is good enough. If a different format
+ is required, (eg, for SPARC or Pyramid 90x, which both have
+ lots of regs), or there is an existing convention for showing
+ all the registers, define the macro DO_REGISTERS_INFO(regnum)
+ to provide that format. */
+static void
+do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ register int i;
+
+ if (regnum >= 0) {
+ print_one_register(regnum);
+ return;
+ }
+#ifdef notdef
+ printf_filtered (
+"Register Contents (relative to selected stack frame)\n\n");
+#endif
+ for (i = 0; i < NUM_REGS; i++)
+ if (TYPE_CODE(REGISTER_VIRTUAL_TYPE(i)) != TYPE_CODE_FLT ||
+ fpregs)
+ print_one_register(i);
+}
+#endif /* no DO_REGISTERS_INFO. */
+
+static void
+registers_info (addr_exp, fpregs)
+ char *addr_exp;
+ int fpregs;
+{
+ int regnum;
+
+ if (!have_inferior_p () && !have_core_file_p ())
+ error ("No inferior or core file");
+
+ if (addr_exp)
+ {
+ if (*addr_exp >= '0' && *addr_exp <= '9')
+ regnum = atoi (addr_exp);
+ else
+ {
+ register char *p = addr_exp;
+ if (p[0] == '$')
+ p++;
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (!strcmp (p, reg_names[regnum]))
+ break;
+ if (regnum == NUM_REGS)
+ error ("%s: invalid register name.", addr_exp);
+ }
+ }
+ else
+ regnum = -1;
+
+#ifdef DO_REGISTERS_INFO
+ DO_REGISTERS_INFO(regnum);
+#else
+ do_registers_info(regnum, fpregs);
+#endif
+}
+
+static void
+all_registers_info (addr_exp)
+ char *addr_exp;
+{
+ registers_info(addr_exp, 1);
+}
+
+static void
+nofp_registers_info (addr_exp)
+ char *addr_exp;
+{
+ registers_info(addr_exp, 0);
+}
+
+
+#ifdef ATTACH_DETACH
+#define PROCESS_ATTACH_ALLOWED 1
+#else
+#define PROCESS_ATTACH_ALLOWED 0
+#endif
+/*
+ * TODO:
+ * Should save/restore the tty state since it might be that the
+ * program to be debugged was started on this tty and it wants
+ * the tty in some state other than what we want. If it's running
+ * on another terminal or without a terminal, then saving and
+ * restoring the tty state is a harmless no-op.
+ * This only needs to be done if we are attaching to a process.
+ */
+
+/*
+ * attach_command --
+ * takes a program started up outside of gdb and ``attaches'' to it.
+ * This stops it cold in its tracks and allows us to start tracing it.
+ * For this to work, we must be able to send the process a
+ * signal and we must have the same effective uid as the program.
+ */
+static void
+attach_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+ int pid;
+ int remote = 0;
+
+ dont_repeat();
+
+ if (!args)
+ error_no_arg ("process-id or device file to attach");
+
+ while (*args == ' ' || *args == '\t') args++;
+
+ if (args[0] < '0' || args[0] > '9')
+ remote = 1;
+ else
+#ifndef ATTACH_DETACH
+ error ("Can't attach to a process on this machine.");
+#else
+ pid = atoi (args);
+#endif
+
+ if (inferior_pid)
+ {
+ if (query ("A program is being debugged already. Kill it? "))
+ kill_inferior ();
+ else
+ error ("Inferior not killed.");
+ }
+
+ exec_file = (char *) get_exec_file (1);
+
+ if (from_tty)
+ {
+ if (remote)
+ printf ("Attaching remote machine\n");
+ else
+ printf ("Attaching program: %s pid %d\n",
+ exec_file, pid);
+ fflush (stdout);
+ }
+
+ if (remote)
+ {
+ remote_open (args, from_tty);
+ start_remote ();
+ }
+#ifdef ATTACH_DETACH
+ else
+ attach_program (pid);
+#endif
+}
+
+/*
+ * detach_command --
+ * takes a program previously attached to and detaches it.
+ * The program resumes execution and will no longer stop
+ * on signals, etc. We better not have left any breakpoints
+ * in the program or it'll die when it hits one. For this
+ * to work, it may be necessary for the process to have been
+ * previously attached. It *might* work if the program was
+ * started via the normal ptrace (PTRACE_TRACEME).
+ */
+
+static void
+detach_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int signal = 0;
+
+#ifdef ATTACH_DETACH
+ if (inferior_pid && !remote_debugging)
+ {
+ if (from_tty)
+ {
+ char *exec_file = (char *)get_exec_file (0);
+ if (exec_file == 0)
+ exec_file = "";
+ printf ("Detaching program: %s pid %d\n",
+ exec_file, inferior_pid);
+ fflush (stdout);
+ }
+ if (args)
+ signal = atoi (args);
+
+ detach (signal);
+ inferior_pid = 0;
+ }
+ else
+#endif
+ {
+ if (!remote_debugging)
+ error ("Not currently attached to subsidiary or remote process.");
+
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ inferior_pid = 0;
+ remote_close (from_tty);
+ }
+}
+
+/* ARGSUSED */
+static void
+float_info (addr_exp)
+ char *addr_exp;
+{
+#ifdef FLOAT_INFO
+ FLOAT_INFO;
+#else
+ printf ("No floating point info available for this processor.\n");
+#endif
+}
+
+extern struct cmd_list_element *setlist, *deletelist;
+
+void
+_initialize_infcmd ()
+{
+ add_com ("tty", class_run, tty_command,
+ "Set terminal for future runs of program being debugged.");
+
+ add_cmd ("args", class_run, set_args_command,
+ "Specify arguments to give program being debugged when it is started.\n\
+Follow this command with any number of args, to be passed to the program.",
+ &setlist);
+
+ add_info ("environment", environment_info,
+ "The environment to give the program, or one variable's value.\n\
+With an argument VAR, prints the value of environment variable VAR to\n\
+give the program being debugged. With no arguments, prints the entire\n\
+environment to be given to the program.");
+
+ add_cmd ("environment", class_run, unset_environment_command,
+ "Cancel environment variable VAR for the program.\n\
+This does not affect the program until the next \"run\" command.",
+ &deletelist);
+
+ add_cmd ("environment", class_run, set_environment_command,
+ "Set environment variable value to give the program.\n\
+Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
+VALUES of environment variables are uninterpreted strings.\n\
+This does not affect the program until the next \"run\" command.",
+ &setlist);
+
+#ifdef ATTACH_DETACH
+ add_com ("attach", class_run, attach_command,
+ "Attach to a process that was started up outside of GDB.\n\
+This command may take as argument a process id or a device file.\n\
+For a process id, you must have permission to send the process a signal,\n\
+and it must have the same effective uid as the debugger.\n\
+For a device file, the file must be a connection to a remote debug server.\n\n\
+Before using \"attach\", you must use the \"exec-file\" command\n\
+to specify the program running in the process,\n\
+and the \"symbol-file\" command to load its symbol table.");
+#else
+ add_com ("attach", class_run, attach_command,
+ "Attach to a process that was started up outside of GDB.\n\
+This commands takes as an argument the name of a device file.\n\
+This file must be a connection to a remote debug server.\n\n\
+Before using \"attach\", you must use the \"exec-file\" command\n\
+to specify the program running in the process,\n\
+and the \"symbol-file\" command to load its symbol table.");
+#endif
+ add_com ("detach", class_run, detach_command,
+ "Detach the process previously attached.\n\
+The process is no longer traced and continues its execution.");
+
+ add_com ("signal", class_run, signal_command,
+ "Continue program giving it signal number SIGNUMBER.");
+
+ add_com ("stepi", class_run, stepi_command,
+ "Step one instruction exactly.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("si", "stepi", class_alias, 0);
+
+ add_com ("nexti", class_run, nexti_command,
+ "Step one instruction, but proceed through subroutine calls.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("ni", "nexti", class_alias, 0);
+
+ add_com ("finish", class_run, finish_command,
+ "Execute until selected stack frame returns.\n\
+Upon return, the value returned is printed and put in the value history.");
+
+ add_com ("next", class_run, next_command,
+ "Step program, proceeding through subroutine calls.\n\
+Like the \"step\" command as long as subroutine calls do not happen;\n\
+when they do, the call is treated as one instruction.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("n", "next", class_run, 1);
+
+ add_com ("step", class_run, step_command,
+ "Step program until it reaches a different source line.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("s", "step", class_run, 1);
+
+ add_com ("until", class_run, until_command,
+ "Execute until the program reaches a source line greater than the current\n\
+or a specified line or address or function (same args as break command).\n\
+Execution will also stop upon exit from the current stack frame.");
+ add_com_alias ("u", "until", class_run, 1);
+
+ add_com ("jump", class_run, jump_command,
+ "Continue program being debugged at specified line or address.\n\
+Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
+for an address to start at.");
+
+ add_com ("cont", class_run, cont_command,
+ "Continue program being debugged, after signal or breakpoint.\n\
+If proceeding from breakpoint, a number N may be used as an argument:\n\
+then the same breakpoint won't break until the Nth time it is reached.");
+ add_com_alias ("c", "cont", class_run, 1);
+
+ add_com ("run", class_run, run_command,
+ "Start debugged program. You may specify arguments to give it.\n\
+Args may include \"*\", or \"[...]\"; they are expanded using \"sh\".\n\
+Input and output redirection with \">\", \"<\", or \">>\" are also allowed.\n\n\
+With no arguments, uses arguments last specified (with \"run\" or \"set args\".\n\
+To cancel previous arguments and run with no arguments,\n\
+use \"set args\" without arguments.");
+ add_com_alias ("r", "run", class_run, 1);
+
+ add_info ("registers", nofp_registers_info,
+ "List of registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.\n\
+(Doesn't display floating point registers; use 'info all-registers'.)\n");
+
+ add_info ("all-registers", all_registers_info,
+ "List of registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.");
+
+ add_info ("program", program_info,
+ "Execution status of the program.");
+
+ add_info ("float", float_info,
+ "Print the status of the floating point unit\n");
+
+ inferior_args = savestring (" ", 1); /* By default, no args. */
+ inferior_environ = make_environ ();
+ init_environ (inferior_environ);
+}
+
diff --git a/gnu/usr.bin/kgdb/inferior.h b/gnu/usr.bin/kgdb/inferior.h
new file mode 100644
index 000000000000..04c662e4626c
--- /dev/null
+++ b/gnu/usr.bin/kgdb/inferior.h
@@ -0,0 +1,142 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ *
+ * @(#)inferior.h 6.3 (Berkeley) 5/8/91
+ */
+
+/* Variables that describe the inferior process running under GDB:
+ Where it is, why it stopped, and how to step it.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Structure in which to save the status of the inferior. Save
+ * through "save_inferior_status", restore through
+ * "restore_inferior_status".
+ * This pair of routines should be called around any transfer of
+ * control to the inferior which you don't want showing up in your
+ * control variables.
+ */
+struct inferior_status {
+ int pc_changed;
+ int stop_signal;
+ int stop_pc;
+ int stop_frame_address;
+ int stop_breakpoint;
+ int stop_step;
+ int stop_stack_dummy;
+ int stopped_by_random_signal;
+ int trap_expected;
+ CORE_ADDR step_range_start;
+ CORE_ADDR step_range_end;
+ FRAME_ADDR step_frame_address;
+ int step_over_calls;
+ CORE_ADDR step_resume_break_address;
+ int stop_after_trap;
+ int stop_after_attach;
+ FRAME_ADDR selected_frame_address;
+ int selected_level;
+ struct command_line *breakpoint_commands;
+ char register_context[REGISTER_BYTES];
+ int restore_stack_info;
+};
+
+void save_inferior_status (), restore_inferior_status ();
+
+/* File name for default use for standard in/out in the inferior. */
+
+extern char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now. */
+
+extern int inferior_pid;
+
+/* Nonzero if debugging a remote machine via a serial link or ethernet. */
+extern int remote_debugging;
+
+/* Routines for use in remote debugging. Documented in remote.c. */
+int remote_read_inferior_memory ();
+int remote_write_inferior_memory ();
+
+/* Last signal that the inferior received (why it stopped). */
+
+extern int stop_signal;
+
+/* Address at which inferior stopped. */
+
+extern CORE_ADDR stop_pc;
+
+/* Stack frame when program stopped. */
+
+extern FRAME_ADDR stop_frame_address;
+
+/* Number of breakpoint it stopped at, or 0 if none. */
+
+extern int stop_breakpoint;
+
+/* Nonzero if stopped due to a step command. */
+
+extern int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine. */
+
+extern int stop_stack_dummy;
+
+/* Nonzero if program stopped due to a random (unexpected) signal in
+ inferior process. */
+
+extern int stopped_by_random_signal;
+
+/* Range to single step within.
+ If this is nonzero, respond to a single-step signal
+ by continuing to step if the pc is in this range. */
+
+extern CORE_ADDR step_range_start; /* Inclusive */
+extern CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+ This is how we know when we step into a subroutine call,
+ and how to set the frame for the breakpoint used to step out. */
+
+extern FRAME_ADDR step_frame_address;
+
+/* 1 means step over all subroutine calls.
+ -1 means step over calls to undebuggable functions. */
+
+extern int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+ so don't print frame next time inferior stops
+ if it stops due to stepping. */
+
+extern int step_multi;
+
+/* Save register contents here when about to pop a stack dummy frame. */
+
+extern char stop_registers[REGISTER_BYTES];
+
+/* Nonzero if pc has been changed by the debugger
+ since the inferior stopped. */
+
+extern int pc_changed;
+
+long read_memory_integer ();
diff --git a/gnu/usr.bin/kgdb/inflow.c b/gnu/usr.bin/kgdb/inflow.c
new file mode 100644
index 000000000000..cad8638a9a4a
--- /dev/null
+++ b/gnu/usr.bin/kgdb/inflow.c
@@ -0,0 +1,568 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)inflow.c 6.5 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+/* Some USG-esque systems (some of which are BSD-esque enough so that USG
+ is not defined) want this header, and it won't do any harm. */
+#include <fcntl.h>
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+
+#ifdef HAVE_TERMIO
+#include <termio.h>
+#undef TIOCGETP
+#define TIOCGETP TCGETA
+#undef TIOCSETN
+#define TIOCSETN TCSETA
+#undef TIOCSETP
+#define TIOCSETP TCSETAF
+#define TERMINAL struct termio
+#else
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+#endif
+
+#ifdef SET_STACK_LIMIT_HUGE
+#include <sys/time.h>
+#include <sys/resource.h>
+extern int original_stack_limit;
+#endif /* SET_STACK_LIMIT_HUGE */
+
+extern int errno;
+
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+int attach_flag;
+
+
+/* Record terminal status separately for debugger and inferior. */
+
+static TERMINAL sg_inferior;
+static TERMINAL sg_ours;
+
+static int tflags_inferior;
+static int tflags_ours;
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+static struct tchars tc_inferior;
+static struct tchars tc_ours;
+#endif
+
+#ifdef TIOCGLTC
+static struct ltchars ltc_inferior;
+static struct ltchars ltc_ours;
+#endif
+
+#ifdef TIOCLGET
+static int lmode_inferior;
+static int lmode_ours;
+#endif
+
+#ifdef TIOCGPGRP
+static int pgrp_inferior;
+static int pgrp_ours;
+#else
+static int (*sigint_ours) ();
+static int (*sigquit_ours) ();
+#endif /* TIOCGPGRP */
+
+/* Copy of inferior_io_terminal when inferior was last started. */
+static char *inferior_thisrun_terminal;
+
+static void terminal_ours_1 ();
+
+/* Nonzero if our terminal settings are in effect.
+ Zero if the inferior's settings are in effect. */
+static int terminal_is_ours;
+
+/* Initialize the terminal settings we record for the inferior,
+ before we actually run the inferior. */
+
+void
+terminal_init_inferior ()
+{
+ if (remote_debugging)
+ return;
+
+ sg_inferior = sg_ours;
+ tflags_inferior = tflags_ours;
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+ tc_inferior = tc_ours;
+#endif
+
+#ifdef TIOCGLTC
+ ltc_inferior = ltc_ours;
+#endif
+
+#ifdef TIOCLGET
+ lmode_inferior = lmode_ours;
+#endif
+
+#ifdef TIOCGPGRP
+ pgrp_inferior = inferior_pid;
+#endif /* TIOCGPGRP */
+
+ terminal_is_ours = 1;
+}
+
+/* Put the inferior's terminal settings into effect.
+ This is preparation for starting or resuming the inferior. */
+
+void
+terminal_inferior ()
+{
+ if (remote_debugging)
+ return;
+
+ if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
+ {
+ fcntl (0, F_SETFL, tflags_inferior);
+ fcntl (0, F_SETFL, tflags_inferior);
+ ioctl (0, TIOCSETN, &sg_inferior);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+ ioctl (0, TIOCSETC, &tc_inferior);
+#endif
+#ifdef TIOCGLTC
+ ioctl (0, TIOCSLTC, &ltc_inferior);
+#endif
+#ifdef TIOCLGET
+ ioctl (0, TIOCLSET, &lmode_inferior);
+#endif
+
+#ifdef TIOCGPGRP
+ ioctl (0, TIOCSPGRP, &pgrp_inferior);
+#else
+ sigint_ours = (int (*) ()) signal (SIGINT, SIG_IGN);
+ sigquit_ours = (int (*) ()) signal (SIGQUIT, SIG_IGN);
+#endif /* TIOCGPGRP */
+ }
+ terminal_is_ours = 0;
+}
+
+/* Put some of our terminal settings into effect,
+ enough to get proper results from our output,
+ but do not change into or out of RAW mode
+ so that no input is discarded.
+
+ After doing this, either terminal_ours or terminal_inferior
+ should be called to get back to a normal state of affairs. */
+
+void
+terminal_ours_for_output ()
+{
+ if (remote_debugging)
+ return;
+
+ terminal_ours_1 (1);
+}
+
+/* Put our terminal settings into effect.
+ First record the inferior's terminal settings
+ so they can be restored properly later. */
+
+void
+terminal_ours ()
+{
+ if (remote_debugging)
+ return;
+
+ terminal_ours_1 (0);
+}
+
+static void
+terminal_ours_1 (output_only)
+ int output_only;
+{
+#ifdef TIOCGPGRP
+ /* Ignore this signal since it will happen when we try to set the pgrp. */
+ void (*osigttou) ();
+#endif /* TIOCGPGRP */
+
+ if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
+ {
+ terminal_is_ours = 1;
+
+#ifdef TIOCGPGRP
+ osigttou = signal (SIGTTOU, SIG_IGN);
+
+ ioctl (0, TIOCGPGRP, &pgrp_inferior);
+ ioctl (0, TIOCSPGRP, &pgrp_ours);
+
+ signal (SIGTTOU, osigttou);
+#else
+ signal (SIGINT, sigint_ours);
+ signal (SIGQUIT, sigquit_ours);
+#endif /* TIOCGPGRP */
+
+ tflags_inferior = fcntl (0, F_GETFL, 0);
+ ioctl (0, TIOCGETP, &sg_inferior);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+ ioctl (0, TIOCGETC, &tc_inferior);
+#endif
+#ifdef TIOCGLTC
+ ioctl (0, TIOCGLTC, &ltc_inferior);
+#endif
+#ifdef TIOCLGET
+ ioctl (0, TIOCLGET, &lmode_inferior);
+#endif
+ }
+
+#ifdef HAVE_TERMIO
+ sg_ours.c_lflag |= ICANON;
+ if (output_only && !(sg_inferior.c_lflag & ICANON))
+ sg_ours.c_lflag &= ~ICANON;
+#else /* not HAVE_TERMIO */
+ sg_ours.sg_flags &= ~RAW & ~CBREAK;
+ if (output_only)
+ sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
+#endif /* not HAVE_TERMIO */
+
+ fcntl (0, F_SETFL, tflags_ours);
+ fcntl (0, F_SETFL, tflags_ours);
+ ioctl (0, TIOCSETN, &sg_ours);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+ ioctl (0, TIOCSETC, &tc_ours);
+#endif
+#ifdef TIOCGLTC
+ ioctl (0, TIOCSLTC, &ltc_ours);
+#endif
+#ifdef TIOCLGET
+ ioctl (0, TIOCLSET, &lmode_ours);
+#endif
+
+#ifdef HAVE_TERMIO
+ sg_ours.c_lflag |= ICANON;
+#else /* not HAVE_TERMIO */
+ sg_ours.sg_flags &= ~RAW & ~CBREAK;
+#endif /* not HAVE_TERMIO */
+}
+
+static void
+term_status_command ()
+{
+ register int i;
+
+ if (remote_debugging)
+ {
+ printf_filtered ("No terminal status when remote debugging.\n");
+ return;
+ }
+
+ printf_filtered ("Inferior's terminal status (currently saved by GDB):\n");
+
+#ifdef HAVE_TERMIO
+
+ printf_filtered ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
+ printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
+ sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
+ printf_filtered ("c_cc: ");
+ for (i = 0; (i < NCC); i += 1)
+ printf_filtered ("0x%x ", sg_inferior.c_cc[i]);
+ printf_filtered ("\n");
+
+#else /* not HAVE_TERMIO */
+
+ printf_filtered ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
+ tflags_inferior, sg_inferior.sg_flags, pgrp_inferior);
+
+#endif /* not HAVE_TERMIO */
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+ printf_filtered ("tchars: ");
+ for (i = 0; i < sizeof (struct tchars); i++)
+ printf_filtered ("0x%x ", ((char *)&tc_inferior)[i]);
+ printf_filtered ("\n");
+#endif
+
+#ifdef TIOCGLTC
+ printf_filtered ("ltchars: ");
+ for (i = 0; i < sizeof (struct ltchars); i++)
+ printf_filtered ("0x%x ", ((char *)&ltc_inferior)[i]);
+ printf_filtered ("\n");
+ ioctl (0, TIOCSLTC, &ltc_ours);
+#endif
+
+#ifdef TIOCLGET
+ printf_filtered ("lmode: %x\n", lmode_inferior);
+#endif
+}
+
+static void
+new_tty (ttyname)
+ char *ttyname;
+{
+ register int tty;
+ register int fd;
+
+#ifdef TIOCNOTTY
+ /* Disconnect the child process from our controlling terminal. */
+ tty = open("/dev/tty", O_RDWR);
+ if (tty > 0)
+ {
+ ioctl(tty, TIOCNOTTY, 0);
+ close(tty);
+ }
+#endif
+
+ /* Now open the specified new terminal. */
+
+ tty = open(ttyname, O_RDWR);
+ if (tty == -1)
+ _exit(1);
+
+ /* Avoid use of dup2; doesn't exist on all systems. */
+ if (tty != 0)
+ { close (0); dup (tty); }
+ if (tty != 1)
+ { close (1); dup (tty); }
+ if (tty != 2)
+ { close (2); dup (tty); }
+ if (tty > 2)
+ close(tty);
+}
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a string containing shell command to run the program.
+ ENV is the environment vector to pass. */
+
+#ifndef SHELL_FILE
+#define SHELL_FILE "/bin/sh"
+#endif
+
+int
+create_inferior (allargs, env)
+ char *allargs;
+ char **env;
+{
+ int pid;
+ char *shell_command;
+ extern int sys_nerr;
+ extern int errno;
+
+ /* If desired, concat something onto the front of ALLARGS.
+ SHELL_COMMAND is the result. */
+#ifdef SHELL_COMMAND_CONCAT
+ shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1);
+ strcpy (shell_command, SHELL_COMMAND_CONCAT);
+ strcat (shell_command, allargs);
+#else
+ shell_command = allargs;
+#endif
+
+ /* exec is said to fail if the executable is open. */
+ close_exec_file ();
+
+#if defined(USG) && !defined(HAVE_VFORK)
+ pid = fork ();
+#else
+ pid = vfork ();
+#endif
+
+ if (pid < 0)
+ perror_with_name ("vfork");
+
+ if (pid == 0)
+ {
+#ifdef TIOCGPGRP
+ /* Run inferior in a separate process group. */
+ setpgrp (getpid (), getpid ());
+#endif /* TIOCGPGRP */
+
+#ifdef SET_STACK_LIMIT_HUGE
+ /* Reset the stack limit back to what it was. */
+ {
+ struct rlimit rlim;
+
+ getrlimit (RLIMIT_STACK, &rlim);
+ rlim.rlim_cur = original_stack_limit;
+ setrlimit (RLIMIT_STACK, &rlim);
+ }
+#endif /* SET_STACK_LIMIT_HUGE */
+
+
+ inferior_thisrun_terminal = inferior_io_terminal;
+ if (inferior_io_terminal != 0)
+ new_tty (inferior_io_terminal);
+
+/* It seems that changing the signal handlers for the inferior after
+ a vfork also changes them for the superior. See comments in
+ initialize_signals for how we get the right signal handlers
+ for the inferior. */
+/* Not needed on Sun, at least, and loses there
+ because it clobbers the superior. */
+/*??? signal (SIGQUIT, SIG_DFL);
+ signal (SIGINT, SIG_DFL); */
+
+ call_ptrace (0);
+ execle (SHELL_FILE, "sh", "-c", shell_command, 0, env);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+#ifdef TIOCGPGRP
+ /* Avoid race with TIOCSPGRP: guarantee that inferior's pgrp exists. */
+ setpgrp (pid, pid);
+#endif /* TIOCGPGRP */
+
+#ifdef CREATE_INFERIOR_HOOK
+ CREATE_INFERIOR_HOOK (pid);
+#endif
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+static void
+kill_command ()
+{
+ if (remote_debugging)
+ {
+ inferior_pid = 0;
+ return;
+ }
+ if (inferior_pid == 0)
+ error ("The program is not being run.");
+ if (!query ("Kill the inferior process? "))
+ error ("Not confirmed.");
+ kill_inferior ();
+}
+
+void
+inferior_died ()
+{
+ inferior_pid = 0;
+ attach_flag = 0;
+ mark_breakpoints_out ();
+ select_frame ((FRAME) 0, -1);
+ reopen_exec_file ();
+ if (have_core_file_p ())
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ else
+ set_current_frame (0);
+}
+
+#if 0
+/* This function is just for testing, and on some systems (Sony NewsOS
+ 3.2) <sys/user.h> also includes <sys/time.h> which leads to errors
+ (since on this system at least sys/time.h is not protected against
+ multiple inclusion). */
+static void
+try_writing_regs_command ()
+{
+ register int i;
+ register int value;
+ extern int errno;
+
+ if (inferior_pid == 0)
+ error ("There is no inferior process now.");
+
+ /* A Sun 3/50 or 3/60 (at least) running SunOS 4.0.3 will have a
+ kernel panic if we try to write past the end of the user area.
+ Presumably Sun will fix this bug (it has been reported), but it
+ is tacky to crash the system, so at least on SunOS4 we need to
+ stop writing when we hit the end of the user area. */
+ for (i = 0; i < sizeof (struct user); i += 2)
+ {
+ QUIT;
+ errno = 0;
+ value = call_ptrace (3, inferior_pid, i, 0);
+ call_ptrace (6, inferior_pid, i, value);
+ if (errno == 0)
+ {
+ printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
+ i, value, value);
+ }
+ else if ((i & 0377) == 0)
+ printf (" Failed at 0x%x.\n", i);
+ }
+}
+#endif
+
+void
+_initialize_inflow ()
+{
+ add_com ("term-status", class_obscure, term_status_command,
+ "Print info on inferior's saved terminal status.");
+
+#if 0
+ add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
+ "Try writing all locations in inferior's system block.\n\
+Report which ones can be written.");
+#endif
+
+ add_com ("kill", class_run, kill_command,
+ "Kill execution of program being debugged.");
+
+ inferior_pid = 0;
+
+ ioctl (0, TIOCGETP, &sg_ours);
+ tflags_ours = fcntl (0, F_GETFL, 0);
+
+#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
+ ioctl (0, TIOCGETC, &tc_ours);
+#endif
+#ifdef TIOCGLTC
+ ioctl (0, TIOCGLTC, &ltc_ours);
+#endif
+#ifdef TIOCLGET
+ ioctl (0, TIOCLGET, &lmode_ours);
+#endif
+
+#ifdef TIOCGPGRP
+ ioctl (0, TIOCGPGRP, &pgrp_ours);
+#endif /* TIOCGPGRP */
+
+ terminal_is_ours = 1;
+}
+
diff --git a/gnu/usr.bin/kgdb/infrun.c b/gnu/usr.bin/kgdb/infrun.c
new file mode 100644
index 000000000000..031700ba6943
--- /dev/null
+++ b/gnu/usr.bin/kgdb/infrun.c
@@ -0,0 +1,1458 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)infrun.c 6.4 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Start and stop the inferior process, for GDB.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Notes on the algorithm used in wait_for_inferior to determine if we
+ just did a subroutine call when stepping. We have the following
+ information at that point:
+
+ Current and previous (just before this step) pc.
+ Current and previous sp.
+ Current and previous start of current function.
+
+ If the start's of the functions don't match, then
+
+ a) We did a subroutine call.
+
+ In this case, the pc will be at the beginning of a function.
+
+ b) We did a subroutine return.
+
+ Otherwise.
+
+ c) We did a longjmp.
+
+ If we did a longjump, we were doing "nexti", since a next would
+ have attempted to skip over the assembly language routine in which
+ the longjmp is coded and would have simply been the equivalent of a
+ continue. I consider this ok behaivior. We'd like one of two
+ things to happen if we are doing a nexti through the longjmp()
+ routine: 1) It behaves as a stepi, or 2) It acts like a continue as
+ above. Given that this is a special case, and that anybody who
+ thinks that the concept of sub calls is meaningful in the context
+ of a longjmp, I'll take either one. Let's see what happens.
+
+ Acts like a subroutine return. I can handle that with no problem
+ at all.
+
+ -->So: If the current and previous beginnings of the current
+ function don't match, *and* the pc is at the start of a function,
+ we've done a subroutine call. If the pc is not at the start of a
+ function, we *didn't* do a subroutine call.
+
+ -->If the beginnings of the current and previous function do match,
+ either:
+
+ a) We just did a recursive call.
+
+ In this case, we would be at the very beginning of a
+ function and 1) it will have a prologue (don't jump to
+ before prologue, or 2) (we assume here that it doesn't have
+ a prologue) there will have been a change in the stack
+ pointer over the last instruction. (Ie. it's got to put
+ the saved pc somewhere. The stack is the usual place. In
+ a recursive call a register is only an option if there's a
+ prologue to do something with it. This is even true on
+ register window machines; the prologue sets up the new
+ window. It might not be true on a register window machine
+ where the call instruction moved the register window
+ itself. Hmmm. One would hope that the stack pointer would
+ also change. If it doesn't, somebody send me a note, and
+ I'll work out a more general theory.
+ randy@wheaties.ai.mit.edu). This is true (albeit slipperly
+ so) on all machines I'm aware of:
+
+ m68k: Call changes stack pointer. Regular jumps don't.
+
+ sparc: Recursive calls must have frames and therefor,
+ prologues.
+
+ vax: All calls have frames and hence change the
+ stack pointer.
+
+ b) We did a return from a recursive call. I don't see that we
+ have either the ability or the need to distinguish this
+ from an ordinary jump. The stack frame will be printed
+ when and if the frame pointer changes; if we are in a
+ function without a frame pointer, it's the users own
+ lookout.
+
+ c) We did a jump within a function. We assume that this is
+ true if we didn't do a recursive call.
+
+ d) We are in no-man's land ("I see no symbols here"). We
+ don't worry about this; it will make calls look like simple
+ jumps (and the stack frames will be printed when the frame
+ pointer moves), which is a reasonably non-violent response.
+
+#if 0
+ We skip this; it causes more problems than it's worth.
+#ifdef SUN4_COMPILER_FEATURE
+ We do a special ifdef for the sun 4, forcing it to single step
+ into calls which don't have prologues. This means that we can't
+ nexti over leaf nodes, we can probably next over them (since they
+ won't have debugging symbols, usually), and we can next out of
+ functions returning structures (with a "call .stret4" at the end).
+#endif
+#endif
+*/
+
+
+
+
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <signal.h>
+
+/* unistd.h is needed to #define X_OK */
+#ifdef USG
+#include <unistd.h>
+#else
+#include <sys/file.h>
+#endif
+
+#ifdef UMAX_PTRACE
+#include <aouthdr.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#endif /* UMAX_PTRACE */
+
+/* Required by <sys/user.h>. */
+#include <sys/types.h>
+/* Required by <sys/user.h>, at least on system V. */
+#include <sys/dir.h>
+/* Needed by IN_SIGTRAMP on some machines (e.g. vax). */
+#include <sys/param.h>
+/* Needed by IN_SIGTRAMP on some machines (e.g. vax). */
+#include <sys/user.h>
+
+extern int errno;
+
+/* Sigtramp is a routine that the kernel calls (which then calls the
+ signal handler). On most machines it is a library routine that
+ is linked into the executable.
+
+ This macro, given a program counter value and the name of the
+ function in which that PC resides (which can be null if the
+ name is not known), returns nonzero if the PC and name show
+ that we are in sigtramp.
+
+ On most machines just see if the name is sigtramp (and if we have
+ no name, assume we are not in sigtramp). */
+#if !defined (IN_SIGTRAMP)
+#define IN_SIGTRAMP(pc, name) \
+ name && !strcmp ("_sigtramp", name)
+#endif
+
+/* Tables of how to react to signals; the user sets them. */
+
+static char signal_stop[NSIG];
+static char signal_print[NSIG];
+static char signal_program[NSIG];
+
+/* Nonzero if breakpoints are now inserted in the inferior. */
+
+static int breakpoints_inserted;
+
+/* Function inferior was in as of last step command. */
+
+static struct symbol *step_start_function;
+
+/* This is the sequence of bytes we insert for a breakpoint. */
+
+static char break_insn[] = BREAKPOINT;
+
+/* Nonzero => address for special breakpoint for resuming stepping. */
+
+static CORE_ADDR step_resume_break_address;
+
+/* Original contents of the byte where the special breakpoint is. */
+
+static char step_resume_break_shadow[sizeof break_insn];
+
+/* Nonzero means the special breakpoint is a duplicate
+ so it has not itself been inserted. */
+
+static int step_resume_break_duplicate;
+
+/* Nonzero if we are expecting a trace trap and should proceed from it.
+ 2 means expecting 2 trace traps and should continue both times.
+ That occurs when we tell sh to exec the program: we will get
+ a trap after the exec of sh and a second when the program is exec'd. */
+
+static int trap_expected;
+
+/* Nonzero if the next time we try to continue the inferior, it will
+ step one instruction and generate a spurious trace trap.
+ This is used to compensate for a bug in HP-UX. */
+
+static int trap_expected_after_continue;
+
+/* Nonzero means expecting a trace trap
+ and should stop the inferior and return silently when it happens. */
+
+int stop_after_trap;
+
+/* Nonzero means expecting a trace trap due to attaching to a process. */
+
+int stop_after_attach;
+
+/* Nonzero if pc has been changed by the debugger
+ since the inferior stopped. */
+
+int pc_changed;
+
+/* Nonzero if debugging a remote machine via a serial link or ethernet. */
+
+int remote_debugging;
+
+/* Nonzero if program stopped due to error trying to insert breakpoints. */
+
+static int breakpoints_failed;
+
+/* Nonzero if inferior is in sh before our program got exec'd. */
+
+static int running_in_shell;
+
+/* Nonzero after stop if current stack frame should be printed. */
+
+static int stop_print_frame;
+
+#ifdef NO_SINGLE_STEP
+extern int one_stepped; /* From machine dependent code */
+extern void single_step (); /* Same. */
+#endif /* NO_SINGLE_STEP */
+
+static void insert_step_breakpoint ();
+static void remove_step_breakpoint ();
+static void wait_for_inferior ();
+static void normal_stop ();
+
+
+/* Clear out all variables saying what to do when inferior is continued.
+ First do this, then set the ones you want, then call `proceed'. */
+
+void
+clear_proceed_status ()
+{
+ trap_expected = 0;
+ step_range_start = 0;
+ step_range_end = 0;
+ step_frame_address = 0;
+ step_over_calls = -1;
+ step_resume_break_address = 0;
+ stop_after_trap = 0;
+ stop_after_attach = 0;
+
+ /* Discard any remaining commands left by breakpoint we had stopped at. */
+ clear_breakpoint_commands ();
+}
+
+/* Basic routine for continuing the program in various fashions.
+
+ ADDR is the address to resume at, or -1 for resume where stopped.
+ SIGNAL is the signal to give it, or 0 for none,
+ or -1 for act according to how it stopped.
+ STEP is nonzero if should trap after one instruction.
+ -1 means return after that and print nothing.
+ You should probably set various step_... variables
+ before calling here, if you are stepping.
+
+ You should call clear_proceed_status before calling proceed. */
+
+void
+proceed (addr, signal, step)
+ CORE_ADDR addr;
+ int signal;
+ int step;
+{
+ int oneproc = 0;
+
+ if (step > 0)
+ step_start_function = find_pc_function (read_pc ());
+ if (step < 0)
+ stop_after_trap = 1;
+
+ if (addr == -1)
+ {
+ /* If there is a breakpoint at the address we will resume at,
+ step one instruction before inserting breakpoints
+ so that we do not stop right away. */
+
+ if (!pc_changed && breakpoint_here_p (read_pc ()))
+ oneproc = 1;
+ }
+ else
+ {
+ write_register (PC_REGNUM, addr);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, addr + 4);
+#endif
+ }
+
+ if (trap_expected_after_continue)
+ {
+ /* If (step == 0), a trap will be automatically generated after
+ the first instruction is executed. Force step one
+ instruction to clear this condition. This should not occur
+ if step is nonzero, but it is harmless in that case. */
+ oneproc = 1;
+ trap_expected_after_continue = 0;
+ }
+
+ if (oneproc)
+ /* We will get a trace trap after one instruction.
+ Continue it automatically and insert breakpoints then. */
+ trap_expected = 1;
+ else
+ {
+ int temp = insert_breakpoints ();
+ if (temp)
+ {
+ print_sys_errmsg ("ptrace", temp);
+ error ("Cannot insert breakpoints.\n\
+The same program may be running in another process.");
+ }
+ breakpoints_inserted = 1;
+ }
+
+ /* Install inferior's terminal modes. */
+ terminal_inferior ();
+
+ if (signal >= 0)
+ stop_signal = signal;
+ /* If this signal should not be seen by program,
+ give it zero. Used for debugging signals. */
+ else if (stop_signal < NSIG && !signal_program[stop_signal])
+ stop_signal= 0;
+
+ /* Resume inferior. */
+ resume (oneproc || step, stop_signal);
+
+ /* Wait for it to stop (if not standalone)
+ and in any case decode why it stopped, and act accordingly. */
+
+ wait_for_inferior ();
+ normal_stop ();
+}
+
+/* Writing the inferior pc as a register calls this function
+ to inform infrun that the pc has been set in the debugger. */
+
+void
+writing_pc (val)
+ CORE_ADDR val;
+{
+ stop_pc = val;
+ pc_changed = 1;
+}
+
+/* Start an inferior process for the first time.
+ Actually it was started by the fork that created it,
+ but it will have stopped one instruction after execing sh.
+ Here we must get it up to actual execution of the real program. */
+
+void
+start_inferior ()
+{
+ /* We will get a trace trap after one instruction.
+ Continue it automatically. Eventually (after shell does an exec)
+ it will get another trace trap. Then insert breakpoints and continue. */
+
+#ifdef START_INFERIOR_TRAPS_EXPECTED
+ trap_expected = START_INFERIOR_TRAPS_EXPECTED;
+#else
+ trap_expected = 2;
+#endif
+
+ running_in_shell = 0; /* Set to 1 at first SIGTRAP, 0 at second. */
+ trap_expected_after_continue = 0;
+ breakpoints_inserted = 0;
+ mark_breakpoints_out ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ terminal_init_inferior ();
+
+ /* Install inferior's terminal modes. */
+ terminal_inferior ();
+
+ if (remote_debugging)
+ {
+ trap_expected = 0;
+ fetch_inferior_registers();
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ stop_frame_address = FRAME_FP (get_current_frame());
+ inferior_pid = 3;
+ if (insert_breakpoints())
+ fatal("Can't insert breakpoints");
+ breakpoints_inserted = 1;
+ proceed(-1, -1, 0);
+ }
+ else
+ {
+ wait_for_inferior ();
+ normal_stop ();
+ }
+}
+
+/* Start or restart remote-debugging of a machine over a serial link. */
+
+void
+restart_remote ()
+{
+ clear_proceed_status ();
+ running_in_shell = 0;
+ trap_expected = 0;
+ stop_after_attach = 1;
+ inferior_pid = 3;
+ wait_for_inferior ();
+ normal_stop();
+}
+
+void
+start_remote ()
+{
+ breakpoints_inserted = 0;
+ mark_breakpoints_out ();
+ restart_remote();
+}
+
+#ifdef ATTACH_DETACH
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+void
+attach_program (pid)
+ int pid;
+{
+ attach (pid);
+ inferior_pid = pid;
+
+ mark_breakpoints_out ();
+ terminal_init_inferior ();
+ clear_proceed_status ();
+ stop_after_attach = 1;
+ /*proceed (-1, 0, -2);*/
+ terminal_inferior ();
+ wait_for_inferior ();
+ normal_stop ();
+}
+#endif /* ATTACH_DETACH */
+
+/* Wait for control to return from inferior to debugger.
+ If inferior gets a signal, we may decide to start it up again
+ instead of returning. That is why there is a loop in this function.
+ When this function actually returns it means the inferior
+ should be left stopped and GDB should read more commands. */
+
+static void
+wait_for_inferior ()
+{
+ register int pid;
+ WAITTYPE w;
+ CORE_ADDR pc;
+ int tem;
+ int another_trap;
+ int random_signal;
+ CORE_ADDR stop_sp, prev_sp;
+ CORE_ADDR prev_func_start, stop_func_start;
+ char *prev_func_name, *stop_func_name;
+ CORE_ADDR prologue_pc;
+ int stop_step_resume_break;
+ CORE_ADDR step_resume_break_sp;
+ int newmisc;
+ int newfun_pc;
+ struct symtab_and_line sal;
+ int prev_pc;
+ extern CORE_ADDR text_end;
+ int remove_breakpoints_on_following_step = 0;
+
+ prev_pc = read_pc ();
+ (void) find_pc_partial_function (prev_pc, &prev_func_name,
+ &prev_func_start);
+ prev_func_start += FUNCTION_START_OFFSET;
+ prev_sp = read_register (SP_REGNUM);
+
+ while (1)
+ {
+ /* Clean up saved state that will become invalid. */
+ pc_changed = 0;
+ flush_cached_frames ();
+
+ if (remote_debugging)
+ remote_wait (&w);
+ else
+ {
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ continue;
+ }
+
+ /* See if the process still exists; clean up if it doesn't. */
+ if (WIFEXITED (w))
+ {
+ terminal_ours_for_output ();
+ if (WEXITSTATUS (w))
+ printf ("\nProgram exited with code 0%o.\n", WEXITSTATUS (w));
+ else
+ printf ("\nProgram exited normally.\n");
+ fflush (stdout);
+ inferior_died ();
+#ifdef NO_SINGLE_STEP
+ one_stepped = 0;
+#endif
+ stop_print_frame = 0;
+ break;
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ kill_inferior ();
+ stop_print_frame = 0;
+ stop_signal = WTERMSIG (w);
+ terminal_ours_for_output ();
+ printf ("\nProgram terminated with signal %d, %s\n",
+ stop_signal,
+ stop_signal < NSIG
+ ? sys_siglist[stop_signal]
+ : "(undocumented)");
+ printf ("The inferior process no longer exists.\n");
+ fflush (stdout);
+#ifdef NO_SINGLE_STEP
+ one_stepped = 0;
+#endif
+ break;
+ }
+
+#ifdef NO_SINGLE_STEP
+ if (one_stepped)
+ single_step (0); /* This actually cleans up the ss */
+#endif /* NO_SINGLE_STEP */
+
+ fetch_inferior_registers ();
+ stop_pc = read_pc ();
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+
+ stop_frame_address = FRAME_FP (get_current_frame ());
+ stop_sp = read_register (SP_REGNUM);
+ stop_func_start = 0;
+ stop_func_name = 0;
+ /* Don't care about return value; stop_func_start and stop_func_name
+ will both be 0 if it doesn't work. */
+ (void) find_pc_partial_function (stop_pc, &stop_func_name,
+ &stop_func_start);
+ stop_func_start += FUNCTION_START_OFFSET;
+ another_trap = 0;
+ stop_breakpoint = 0;
+ stop_step = 0;
+ stop_stack_dummy = 0;
+ stop_print_frame = 1;
+ stop_step_resume_break = 0;
+ random_signal = 0;
+ stopped_by_random_signal = 0;
+ breakpoints_failed = 0;
+
+ /* Look at the cause of the stop, and decide what to do.
+ The alternatives are:
+ 1) break; to really stop and return to the debugger,
+ 2) drop through to start up again
+ (set another_trap to 1 to single step once)
+ 3) set random_signal to 1, and the decision between 1 and 2
+ will be made according to the signal handling tables. */
+
+ stop_signal = WSTOPSIG (w);
+
+ /* First, distinguish signals caused by the debugger from signals
+ that have to do with the program's own actions.
+ Note that breakpoint insns may cause SIGTRAP or SIGILL
+ or SIGEMT, depending on the operating system version.
+ Here we detect when a SIGILL or SIGEMT is really a breakpoint
+ and change it to SIGTRAP. */
+
+ if (stop_signal == SIGTRAP
+ || (breakpoints_inserted &&
+ (stop_signal == SIGILL
+ || stop_signal == SIGEMT))
+ || stop_after_attach)
+ {
+ if (stop_signal == SIGTRAP && stop_after_trap)
+ {
+ stop_print_frame = 0;
+ break;
+ }
+ if (stop_after_attach)
+ break;
+ /* Don't even think about breakpoints
+ if still running the shell that will exec the program
+ or if just proceeded over a breakpoint. */
+ if (stop_signal == SIGTRAP && trap_expected)
+ stop_breakpoint = 0;
+ else
+ {
+ /* See if there is a breakpoint at the current PC. */
+#if DECR_PC_AFTER_BREAK
+ /* Notice the case of stepping through a jump
+ that leads just after a breakpoint.
+ Don't confuse that with hitting the breakpoint.
+ What we check for is that 1) stepping is going on
+ and 2) the pc before the last insn does not match
+ the address of the breakpoint before the current pc. */
+ if (!(prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+ && step_range_end && !step_resume_break_address))
+#endif /* DECR_PC_AFTER_BREAK not zero */
+ {
+ /* See if we stopped at the special breakpoint for
+ stepping over a subroutine call. */
+ if (stop_pc - DECR_PC_AFTER_BREAK
+ == step_resume_break_address)
+ {
+ stop_step_resume_break = 1;
+ if (DECR_PC_AFTER_BREAK)
+ {
+ stop_pc -= DECR_PC_AFTER_BREAK;
+ write_register (PC_REGNUM, stop_pc);
+ pc_changed = 0;
+ }
+ }
+ else
+ {
+ stop_breakpoint =
+ breakpoint_stop_status (stop_pc, stop_frame_address);
+ /* Following in case break condition called a
+ function. */
+ stop_print_frame = 1;
+ if (stop_breakpoint && DECR_PC_AFTER_BREAK)
+ {
+ stop_pc -= DECR_PC_AFTER_BREAK;
+ write_register (PC_REGNUM, stop_pc);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, stop_pc + 4);
+#endif
+ pc_changed = 0;
+ }
+ }
+ }
+ }
+
+ if (stop_signal == SIGTRAP)
+ random_signal
+ = !(stop_breakpoint || trap_expected
+ || stop_step_resume_break
+#ifndef CANNOT_EXECUTE_STACK
+ || (stop_sp INNER_THAN stop_pc
+ && stop_pc INNER_THAN stop_frame_address)
+#else
+ || stop_pc == text_end - 2
+#endif
+ || (step_range_end && !step_resume_break_address));
+ else
+ {
+ random_signal
+ = !(stop_breakpoint
+ || stop_step_resume_break
+#ifdef sony_news
+ || (stop_sp INNER_THAN stop_pc
+ && stop_pc INNER_THAN stop_frame_address)
+#endif
+
+ );
+ if (!random_signal)
+ stop_signal = SIGTRAP;
+ }
+ }
+ else
+ random_signal = 1;
+
+ /* For the program's own signals, act according to
+ the signal handling tables. */
+
+ if (random_signal
+ && !(running_in_shell && stop_signal == SIGSEGV))
+ {
+ /* Signal not for debugging purposes. */
+ int printed = 0;
+
+ stopped_by_random_signal = 1;
+
+ if (stop_signal >= NSIG
+ || signal_print[stop_signal])
+ {
+ printed = 1;
+ terminal_ours_for_output ();
+ printf ("\nProgram received signal %d, %s\n",
+ stop_signal,
+ stop_signal < NSIG
+ ? sys_siglist[stop_signal]
+ : "(undocumented)");
+ fflush (stdout);
+ }
+ if (stop_signal >= NSIG
+ || signal_stop[stop_signal])
+ break;
+ /* If not going to stop, give terminal back
+ if we took it away. */
+ else if (printed)
+ terminal_inferior ();
+ }
+
+ /* Handle cases caused by hitting a breakpoint. */
+
+ if (!random_signal
+ && (stop_breakpoint || stop_step_resume_break))
+ {
+ /* Does a breakpoint want us to stop? */
+ if (stop_breakpoint && stop_breakpoint != -1
+ && stop_breakpoint != -0x1000001)
+ {
+ /* 0x1000000 is set in stop_breakpoint as returned by
+ breakpoint_stop_status to indicate a silent
+ breakpoint. */
+ if ((stop_breakpoint > 0 ? stop_breakpoint :
+ -stop_breakpoint)
+ & 0x1000000)
+ {
+ stop_print_frame = 0;
+ if (stop_breakpoint > 0)
+ stop_breakpoint -= 0x1000000;
+ else
+ stop_breakpoint += 0x1000000;
+ }
+ break;
+ }
+ /* But if we have hit the step-resumption breakpoint,
+ remove it. It has done its job getting us here.
+ The sp test is to make sure that we don't get hung
+ up in recursive calls in functions without frame
+ pointers. If the stack pointer isn't outside of
+ where the breakpoint was set (within a routine to be
+ stepped over), we're in the middle of a recursive
+ call. Not true for reg window machines (sparc)
+ because the must change frames to call things and
+ the stack pointer doesn't have to change if it
+ the bp was set in a routine without a frame (pc can
+ be stored in some other window).
+
+ The removal of the sp test is to allow calls to
+ alloca. Nasty things were happening. Oh, well,
+ gdb can only handle one level deep of lack of
+ frame pointer. */
+ if (stop_step_resume_break
+ && (step_frame_address == 0
+ || (stop_frame_address == step_frame_address)))
+ {
+ remove_step_breakpoint ();
+ step_resume_break_address = 0;
+ }
+ /* Otherwise, must remove breakpoints and single-step
+ to get us past the one we hit. */
+ else
+ {
+ remove_breakpoints ();
+ remove_step_breakpoint ();
+ breakpoints_inserted = 0;
+ another_trap = 1;
+ }
+
+ /* We come here if we hit a breakpoint but should not
+ stop for it. Possibly we also were stepping
+ and should stop for that. So fall through and
+ test for stepping. But, if not stepping,
+ do not stop. */
+ }
+
+ /* If this is the breakpoint at the end of a stack dummy,
+ just stop silently. */
+#ifndef CANNOT_EXECUTE_STACK
+ if (stop_sp INNER_THAN stop_pc
+ && stop_pc INNER_THAN stop_frame_address)
+#else
+ if (stop_pc == text_end - 2)
+#endif
+ {
+ stop_print_frame = 0;
+ stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 1;
+#endif
+ break;
+ }
+
+ if (step_resume_break_address)
+ /* Having a step-resume breakpoint overrides anything
+ else having to do with stepping commands until
+ that breakpoint is reached. */
+ ;
+ /* If stepping through a line, keep going if still within it. */
+ else if (!random_signal
+ && step_range_end
+ && stop_pc >= step_range_start
+ && stop_pc < step_range_end
+ /* The step range might include the start of the
+ function, so if we are at the start of the
+ step range and either the stack or frame pointers
+ just changed, we've stepped outside */
+ && !(stop_pc == step_range_start
+ && stop_frame_address
+ && (stop_sp INNER_THAN prev_sp
+ || stop_frame_address != step_frame_address)))
+ {
+ /* Don't step through the return from a function
+ unless that is the first instruction stepped through. */
+ if (ABOUT_TO_RETURN (stop_pc))
+ {
+ stop_step = 1;
+ break;
+ }
+ }
+
+ /* We stepped out of the stepping range. See if that was due
+ to a subroutine call that we should proceed to the end of. */
+ else if (!random_signal && step_range_end)
+ {
+ if (stop_func_start)
+ {
+ prologue_pc = stop_func_start;
+ SKIP_PROLOGUE (prologue_pc);
+ }
+
+ /* Did we just take a signal? */
+ if (IN_SIGTRAMP (stop_pc, stop_func_name)
+ && !IN_SIGTRAMP (prev_pc, prev_func_name))
+ {
+ /* This code is needed at least in the following case:
+ The user types "next" and then a signal arrives (before
+ the "next" is done). */
+ /* We've just taken a signal; go until we are back to
+ the point where we took it and one more. */
+ step_resume_break_address = prev_pc;
+ step_resume_break_duplicate =
+ breakpoint_here_p (step_resume_break_address);
+ step_resume_break_sp = stop_sp;
+ if (breakpoints_inserted)
+ insert_step_breakpoint ();
+ /* Make sure that the stepping range gets us past
+ that instruction. */
+ if (step_range_end == 1)
+ step_range_end = (step_range_start = prev_pc) + 1;
+ remove_breakpoints_on_following_step = 1;
+ }
+
+ /* ==> See comments at top of file on this algorithm. <==*/
+
+ else if (stop_pc == stop_func_start
+ && (stop_func_start != prev_func_start
+ || prologue_pc != stop_func_start
+ || stop_sp != prev_sp))
+ {
+ /* It's a subroutine call */
+ if (step_over_calls > 0
+ || (step_over_calls && find_pc_function (stop_pc) == 0))
+ {
+ /* A subroutine call has happened. */
+ /* Set a special breakpoint after the return */
+ step_resume_break_address =
+ SAVED_PC_AFTER_CALL (get_current_frame ());
+ step_resume_break_duplicate
+ = breakpoint_here_p (step_resume_break_address);
+ step_resume_break_sp = stop_sp;
+ if (breakpoints_inserted)
+ insert_step_breakpoint ();
+ }
+ /* Subroutine call with source code we should not step over.
+ Do step to the first line of code in it. */
+ else if (step_over_calls)
+ {
+ SKIP_PROLOGUE (stop_func_start);
+ sal = find_pc_line (stop_func_start, 0);
+ /* Use the step_resume_break to step until
+ the end of the prologue, even if that involves jumps
+ (as it seems to on the vax under 4.2). */
+ /* If the prologue ends in the middle of a source line,
+ continue to the end of that source line.
+ Otherwise, just go to end of prologue. */
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+ /* no, don't either. It skips any code that's
+ legitimately on the first line. */
+#else
+ if (sal.end && sal.pc != stop_func_start)
+ stop_func_start = sal.end;
+#endif
+
+ if (stop_func_start == stop_pc)
+ {
+ /* We are already there: stop now. */
+ stop_step = 1;
+ break;
+ }
+ else
+ /* Put the step-breakpoint there and go until there. */
+ {
+ step_resume_break_address = stop_func_start;
+ step_resume_break_sp = stop_sp;
+
+ step_resume_break_duplicate
+ = breakpoint_here_p (step_resume_break_address);
+ if (breakpoints_inserted)
+ insert_step_breakpoint ();
+ /* Do not specify what the fp should be when we stop
+ since on some machines the prologue
+ is where the new fp value is established. */
+ step_frame_address = 0;
+ /* And make sure stepping stops right away then. */
+ step_range_end = step_range_start;
+ }
+ }
+ else
+ {
+ /* We get here only if step_over_calls is 0 and we
+ just stepped into a subroutine. I presume
+ that step_over_calls is only 0 when we're
+ supposed to be stepping at the assembly
+ language level.*/
+ stop_step = 1;
+ break;
+ }
+ }
+ /* No subroutince call; stop now. */
+ else
+ {
+ stop_step = 1;
+ break;
+ }
+ }
+
+ /* Save the pc before execution, to compare with pc after stop. */
+ prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
+ prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER
+ BREAK is defined, the
+ original pc would not have
+ been at the start of a
+ function. */
+ prev_func_name = stop_func_name;
+ prev_sp = stop_sp;
+
+ /* If we did not do break;, it means we should keep
+ running the inferior and not return to debugger. */
+
+ /* If trap_expected is 2, it means continue once more
+ and insert breakpoints at the next trap.
+ If trap_expected is 1 and the signal was SIGSEGV, it means
+ the shell is doing some memory allocation--just resume it
+ with SIGSEGV.
+ Otherwise insert breakpoints now, and possibly single step. */
+
+ if (trap_expected > 1)
+ {
+ trap_expected--;
+ running_in_shell = 1;
+ resume (0, 0);
+ }
+ else if (running_in_shell && stop_signal == SIGSEGV)
+ {
+ resume (0, SIGSEGV);
+ }
+ else if (trap_expected && stop_signal != SIGTRAP)
+ {
+ /* We took a signal which we are supposed to pass through to
+ the inferior and we haven't yet gotten our trap. Simply
+ continue. */
+ resume ((step_range_end && !step_resume_break_address)
+ || trap_expected,
+ stop_signal);
+ }
+ else
+ {
+ /* Here, we are not awaiting another exec to get
+ the program we really want to debug.
+ Insert breakpoints now, unless we are trying
+ to one-proceed past a breakpoint. */
+ running_in_shell = 0;
+ /* If we've just finished a special step resume and we don't
+ want to hit a breakpoint, pull em out. */
+ if (!step_resume_break_address &&
+ remove_breakpoints_on_following_step)
+ {
+ remove_breakpoints_on_following_step = 0;
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ }
+ else if (!breakpoints_inserted && !another_trap)
+ {
+ insert_step_breakpoint ();
+ breakpoints_failed = insert_breakpoints ();
+ if (breakpoints_failed)
+ break;
+ breakpoints_inserted = 1;
+ }
+
+ trap_expected = another_trap;
+
+ if (stop_signal == SIGTRAP)
+ stop_signal = 0;
+
+ resume ((step_range_end && !step_resume_break_address)
+ || trap_expected,
+ stop_signal);
+ }
+ }
+}
+
+/* Here to return control to GDB when the inferior stops for real.
+ Print appropriate messages, remove breakpoints, give terminal our modes.
+
+ RUNNING_IN_SHELL nonzero means the shell got a signal before
+ exec'ing the program we wanted to run.
+ STOP_PRINT_FRAME nonzero means print the executing frame
+ (pc, function, args, file, line number and line text).
+ BREAKPOINTS_FAILED nonzero means stop was due to error
+ attempting to insert breakpoints. */
+
+static void
+normal_stop ()
+{
+ /* Make sure that the current_frame's pc is correct. This
+ is a correction for setting up the frame info before doing
+ DECR_PC_AFTER_BREAK */
+ if (inferior_pid)
+ (get_current_frame ())->pc = read_pc ();
+
+ if (breakpoints_failed)
+ {
+ terminal_ours_for_output ();
+ print_sys_errmsg ("ptrace", breakpoints_failed);
+ printf ("Stopped; cannot insert breakpoints.\n\
+The same program may be running in another process.\n");
+ }
+
+ if (inferior_pid)
+ remove_step_breakpoint ();
+
+ if (inferior_pid && breakpoints_inserted)
+ if (remove_breakpoints ())
+ {
+ terminal_ours_for_output ();
+ printf ("Cannot remove breakpoints because program is no longer writable.\n\
+It must be running in another process.\n\
+Further execution is probably impossible.\n");
+ }
+
+ breakpoints_inserted = 0;
+
+ /* Delete the breakpoint we stopped at, if it wants to be deleted.
+ Delete any breakpoint that is to be deleted at the next stop. */
+
+ breakpoint_auto_delete (stop_breakpoint);
+
+ /* If an auto-display called a function and that got a signal,
+ delete that auto-display to avoid an infinite recursion. */
+
+ if (stopped_by_random_signal)
+ disable_current_display ();
+
+ if (step_multi && stop_step)
+ return;
+
+ terminal_ours ();
+
+ if (running_in_shell)
+ {
+ if (stop_signal == SIGSEGV)
+ {
+ char *exec_file = (char *) get_exec_file (1);
+
+ if (access (exec_file, X_OK) != 0)
+ printf ("The file \"%s\" is not executable.\n", exec_file);
+ else
+ /* I don't think we should ever get here.
+ wait_for_inferior now ignores SIGSEGV's which happen in
+ the shell (since the Bourne shell (/bin/sh) has some
+ rather, er, uh, *unorthodox* memory management
+ involving catching SIGSEGV). */
+ printf ("\
+You have just encountered a bug in \"sh\". GDB starts your program\n\
+by running \"sh\" with a command to exec your program.\n\
+This is so that \"sh\" will process wildcards and I/O redirection.\n\
+This time, \"sh\" crashed.\n\
+\n\
+One known bug in \"sh\" bites when the environment takes up a lot of space.\n\
+Try \"info env\" to see the environment; then use \"delete env\" to kill\n\
+some variables whose values are large; then do \"run\" again.\n\
+\n\
+If that works, you might want to put those \"delete env\" commands\n\
+into a \".gdbinit\" file in this directory so they will happen every time.\n");
+ }
+ /* Don't confuse user with his program's symbols on sh's data. */
+ stop_print_frame = 0;
+ }
+
+ if (inferior_pid == 0)
+ return;
+
+ /* Select innermost stack frame except on return from a stack dummy routine,
+ or if the program has exited. */
+ if (!stop_stack_dummy)
+ {
+ select_frame (get_current_frame (), 0);
+
+ if (stop_print_frame)
+ {
+ if (stop_breakpoint > 0)
+ printf ("\nBpt %d, ", stop_breakpoint);
+ print_sel_frame (stop_step
+ && step_frame_address == stop_frame_address
+ && step_start_function == find_pc_function (stop_pc));
+ /* Display the auto-display expressions. */
+ do_displays ();
+ }
+ }
+
+ if (stop_stack_dummy)
+ {
+ /* Pop the empty frame that contains the stack dummy.
+ POP_FRAME ends with a setting of the current frame, so we
+ can use that next. */
+#ifndef NEW_CALL_FUNCTION
+ POP_FRAME;
+#endif
+ select_frame (get_current_frame (), 0);
+ }
+}
+
+static void
+insert_step_breakpoint ()
+{
+ if (step_resume_break_address && !step_resume_break_duplicate)
+ {
+ read_memory (step_resume_break_address,
+ step_resume_break_shadow, sizeof break_insn);
+ write_memory (step_resume_break_address,
+ break_insn, sizeof break_insn);
+ }
+}
+
+static void
+remove_step_breakpoint ()
+{
+ if (step_resume_break_address && !step_resume_break_duplicate)
+ write_memory (step_resume_break_address, step_resume_break_shadow,
+ sizeof break_insn);
+}
+
+/* Specify how various signals in the inferior should be handled. */
+
+static void
+handle_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ int signum = 0;
+ register int digits, wordlen;
+
+ if (!args)
+ error_no_arg ("signal to handle");
+
+ while (*p)
+ {
+ /* Find the end of the next word in the args. */
+ for (wordlen = 0; p[wordlen] && p[wordlen] != ' ' && p[wordlen] != '\t';
+ wordlen++);
+ for (digits = 0; p[digits] >= '0' && p[digits] <= '9'; digits++);
+
+ /* If it is all digits, it is signal number to operate on. */
+ if (digits == wordlen)
+ {
+ signum = atoi (p);
+ if (signum <= 0 || signum >= NSIG)
+ {
+ p[wordlen] = '\0';
+ error ("Invalid signal %s given as argument to \"handle\".", p);
+ }
+ if (signum == SIGTRAP || signum == SIGINT)
+ {
+ if (!query ("Signal %d is used by the debugger.\nAre you sure you want to change it? ", signum))
+ error ("Not confirmed.");
+ }
+ }
+ else if (signum == 0)
+ error ("First argument is not a signal number.");
+
+ /* Else, if already got a signal number, look for flag words
+ saying what to do for it. */
+ else if (!strncmp (p, "stop", wordlen))
+ {
+ signal_stop[signum] = 1;
+ signal_print[signum] = 1;
+ }
+ else if (wordlen >= 2 && !strncmp (p, "print", wordlen))
+ signal_print[signum] = 1;
+ else if (wordlen >= 2 && !strncmp (p, "pass", wordlen))
+ signal_program[signum] = 1;
+ else if (!strncmp (p, "ignore", wordlen))
+ signal_program[signum] = 0;
+ else if (wordlen >= 3 && !strncmp (p, "nostop", wordlen))
+ signal_stop[signum] = 0;
+ else if (wordlen >= 4 && !strncmp (p, "noprint", wordlen))
+ {
+ signal_print[signum] = 0;
+ signal_stop[signum] = 0;
+ }
+ else if (wordlen >= 4 && !strncmp (p, "nopass", wordlen))
+ signal_program[signum] = 0;
+ else if (wordlen >= 3 && !strncmp (p, "noignore", wordlen))
+ signal_program[signum] = 1;
+ /* Not a number and not a recognized flag word => complain. */
+ else
+ {
+ p[wordlen] = 0;
+ error ("Unrecognized flag word: \"%s\".", p);
+ }
+
+ /* Find start of next word. */
+ p += wordlen;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+
+ if (from_tty)
+ {
+ /* Show the results. */
+ printf ("Number\tStop\tPrint\tPass to program\tDescription\n");
+ printf ("%d\t", signum);
+ printf ("%s\t", signal_stop[signum] ? "Yes" : "No");
+ printf ("%s\t", signal_print[signum] ? "Yes" : "No");
+ printf ("%s\t\t", signal_program[signum] ? "Yes" : "No");
+ printf ("%s\n", sys_siglist[signum]);
+ }
+}
+
+/* Print current contents of the tables set by the handle command. */
+
+static void
+signals_info (signum_exp)
+ char *signum_exp;
+{
+ register int i;
+ printf_filtered ("Number\tStop\tPrint\tPass to program\tDescription\n");
+
+ if (signum_exp)
+ {
+ i = parse_and_eval_address (signum_exp);
+ if (i >= NSIG || i < 0)
+ error ("Signal number out of bounds.");
+ printf_filtered ("%d\t", i);
+ printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No");
+ printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No");
+ printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No");
+ printf_filtered ("%s\n", sys_siglist[i]);
+ return;
+ }
+
+ printf_filtered ("\n");
+ for (i = 0; i < NSIG; i++)
+ {
+ QUIT;
+
+ printf_filtered ("%d\t", i);
+ printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No");
+ printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No");
+ printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No");
+ printf_filtered ("%s\n", sys_siglist[i]);
+ }
+
+ printf_filtered ("\nUse the \"handle\" command to change these tables.\n");
+}
+
+/* Save all of the information associated with the inferior<==>gdb
+ connection. INF_STATUS is a pointer to a "struct inferior_status"
+ (defined in inferior.h). */
+
+struct command_line *get_breakpoint_commands ();
+
+void
+save_inferior_status (inf_status, restore_stack_info)
+ struct inferior_status *inf_status;
+ int restore_stack_info;
+{
+ inf_status->pc_changed = pc_changed;
+ inf_status->stop_signal = stop_signal;
+ inf_status->stop_pc = stop_pc;
+ inf_status->stop_frame_address = stop_frame_address;
+ inf_status->stop_breakpoint = stop_breakpoint;
+ inf_status->stop_step = stop_step;
+ inf_status->stop_stack_dummy = stop_stack_dummy;
+ inf_status->stopped_by_random_signal = stopped_by_random_signal;
+ inf_status->trap_expected = trap_expected;
+ inf_status->step_range_start = step_range_start;
+ inf_status->step_range_end = step_range_end;
+ inf_status->step_frame_address = step_frame_address;
+ inf_status->step_over_calls = step_over_calls;
+ inf_status->step_resume_break_address = step_resume_break_address;
+ inf_status->stop_after_trap = stop_after_trap;
+ inf_status->stop_after_attach = stop_after_attach;
+ inf_status->breakpoint_commands = get_breakpoint_commands ();
+ inf_status->restore_stack_info = restore_stack_info;
+
+ read_register_bytes(0, inf_status->register_context, REGISTER_BYTES);
+ record_selected_frame (&(inf_status->selected_frame_address),
+ &(inf_status->selected_level));
+ return;
+}
+
+void
+restore_inferior_status (inf_status)
+ struct inferior_status *inf_status;
+{
+ FRAME fid;
+ int level = inf_status->selected_level;
+
+ pc_changed = inf_status->pc_changed;
+ stop_signal = inf_status->stop_signal;
+ stop_pc = inf_status->stop_pc;
+ stop_frame_address = inf_status->stop_frame_address;
+ stop_breakpoint = inf_status->stop_breakpoint;
+ stop_step = inf_status->stop_step;
+ stop_stack_dummy = inf_status->stop_stack_dummy;
+ stopped_by_random_signal = inf_status->stopped_by_random_signal;
+ trap_expected = inf_status->trap_expected;
+ step_range_start = inf_status->step_range_start;
+ step_range_end = inf_status->step_range_end;
+ step_frame_address = inf_status->step_frame_address;
+ step_over_calls = inf_status->step_over_calls;
+ step_resume_break_address = inf_status->step_resume_break_address;
+ stop_after_trap = inf_status->stop_after_trap;
+ stop_after_attach = inf_status->stop_after_attach;
+ set_breakpoint_commands (inf_status->breakpoint_commands);
+
+ write_register_bytes(0, inf_status->register_context, REGISTER_BYTES);
+
+ /* The inferior can be gone if the user types "print exit(0)"
+ (and perhaps other times). */
+ if (have_inferior_p() && inf_status->restore_stack_info)
+ {
+ flush_cached_frames();
+ set_current_frame(create_new_frame(read_register (FP_REGNUM),
+ read_pc()));
+
+ fid = find_relative_frame (get_current_frame (), &level);
+
+ if (fid == 0 ||
+ FRAME_FP (fid) != inf_status->selected_frame_address ||
+ level != 0)
+ {
+ /* I'm not sure this error message is a good idea. I have
+ only seen it occur after "Can't continue previously
+ requested operation" (we get called from do_cleanups), in
+ which case it just adds insult to injury (one confusing
+ error message after another. Besides which, does the
+ user really care if we can't restore the previously
+ selected frame? */
+ fprintf (stderr, "Unable to restore previously selected frame.\n");
+ select_frame (get_current_frame (), 0);
+ return;
+ }
+
+ select_frame (fid, inf_status->selected_level);
+ }
+ return;
+}
+
+
+void
+_initialize_infrun ()
+{
+ register int i;
+
+ add_info ("signals", signals_info,
+ "What debugger does when program gets various signals.\n\
+Specify a signal number as argument to print info on that signal only.");
+
+ add_com ("handle", class_run, handle_command,
+ "Specify how to handle a signal.\n\
+Args are signal number followed by flags.\n\
+Flags allowed are \"stop\", \"print\", \"pass\",\n\
+ \"nostop\", \"noprint\" or \"nopass\".\n\
+Print means print a message if this signal happens.\n\
+Stop means reenter debugger if this signal happens (implies print).\n\
+Pass means let program see this signal; otherwise program doesn't know.\n\
+Pass and Stop may be combined.");
+
+ for (i = 0; i < NSIG; i++)
+ {
+ signal_stop[i] = 1;
+ signal_print[i] = 1;
+ signal_program[i] = 1;
+ }
+
+ /* Signals caused by debugger's own actions
+ should not be given to the program afterwards. */
+ signal_program[SIGTRAP] = 0;
+ signal_program[SIGINT] = 0;
+
+ /* Signals that are not errors should not normally enter the debugger. */
+#ifdef SIGALRM
+ signal_stop[SIGALRM] = 0;
+ signal_print[SIGALRM] = 0;
+#endif /* SIGALRM */
+#ifdef SIGVTALRM
+ signal_stop[SIGVTALRM] = 0;
+ signal_print[SIGVTALRM] = 0;
+#endif /* SIGVTALRM */
+#ifdef SIGPROF
+ signal_stop[SIGPROF] = 0;
+ signal_print[SIGPROF] = 0;
+#endif /* SIGPROF */
+#ifdef SIGCHLD
+ signal_stop[SIGCHLD] = 0;
+ signal_print[SIGCHLD] = 0;
+#endif /* SIGCHLD */
+#ifdef SIGCLD
+ signal_stop[SIGCLD] = 0;
+ signal_print[SIGCLD] = 0;
+#endif /* SIGCLD */
+#ifdef SIGIO
+ signal_stop[SIGIO] = 0;
+ signal_print[SIGIO] = 0;
+#endif /* SIGIO */
+#ifdef SIGURG
+ signal_stop[SIGURG] = 0;
+ signal_print[SIGURG] = 0;
+#endif /* SIGURG */
+}
+
diff --git a/gnu/usr.bin/kgdb/kgdb.1 b/gnu/usr.bin/kgdb/kgdb.1
new file mode 100644
index 000000000000..3cc2dd9556a3
--- /dev/null
+++ b/gnu/usr.bin/kgdb/kgdb.1
@@ -0,0 +1,15 @@
+.\" Copyright (c) 1994 Paul Richards
+.TH kgdb 1 "10June94" "GNU Tools" "GNU Tools"
+.SH NAME
+kgdb \- The GDB Kernel Debugger
+.SH SYNOPSIS
+.na
+.TP
+.B kgdb
+.RB "[\|" \-help "\|]"
+.ad b
+.SH DESCRIPTION
+kgdb is the old gdb (GDB-3.5) used in FreeBSD 1.1 hardwired
+to run in kernel debugging mode since the installed gdb (GDB-4.11)
+does not support kernel debugging. For further details on gdb refer
+to the gdb man page.
diff --git a/gnu/usr.bin/kgdb/kgdb_proto.h b/gnu/usr.bin/kgdb/kgdb_proto.h
new file mode 100644
index 000000000000..ceef707cb263
--- /dev/null
+++ b/gnu/usr.bin/kgdb/kgdb_proto.h
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Steven McCanne of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kgdb_proto.h 6.3 (Berkeley) 5/8/91
+ *
+ *
+ * /home/ncvs/src/gnu/usr.bin/kgdb/kgdb_proto.h,v 1.1 1993/06/29 09:47:25 nate Exp (LBL)
+ */
+
+/*
+ * Message types.
+ */
+#define KGDB_MEM_R 0x01
+#define KGDB_MEM_W 0x02
+#define KGDB_REG_R 0x03
+#define KGDB_REG_W 0x04
+#define KGDB_CONT 0x05
+#define KGDB_STEP 0x06
+#define KGDB_KILL 0x07
+#define KGDB_SIGNAL 0x08
+#define KGDB_EXEC 0x09
+
+#define KGDB_CMD(x) ((x) & 0x0f)
+
+/*
+ * Message flags.
+ */
+#define KGDB_ACK 0x80
+#define KGDB_DELTA 0x40
+#define KGDB_MORE 0x20
+#define KGDB_SEQ 0x10
diff --git a/gnu/usr.bin/kgdb/main.c b/gnu/usr.bin/kgdb/main.c
new file mode 100644
index 000000000000..37b6c18ade57
--- /dev/null
+++ b/gnu/usr.bin/kgdb/main.c
@@ -0,0 +1,2236 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c 6.6 (Berkeley) 5/13/91";
+#endif /* not lint */
+
+/* Top level for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "command.h"
+#include "param.h"
+#include "expression.h"
+
+#ifdef USG
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include <sys/file.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#ifdef SET_STACK_LIMIT_HUGE
+#include <sys/time.h>
+#include <sys/resource.h>
+
+int original_stack_limit;
+#endif
+
+/* If this definition isn't overridden by the header files, assume
+ that isatty and fileno exist on this system. */
+#ifndef ISATTY
+#define ISATTY(FP) (isatty (fileno (FP)))
+#endif
+
+extern void free ();
+
+/* Version number of GDB, as a string. */
+
+extern char *version;
+
+/*
+ * Declare all cmd_list_element's
+ */
+
+/* Chain containing all defined commands. */
+
+struct cmd_list_element *cmdlist;
+
+/* Chain containing all defined info subcommands. */
+
+struct cmd_list_element *infolist;
+
+/* Chain containing all defined enable subcommands. */
+
+struct cmd_list_element *enablelist;
+
+/* Chain containing all defined disable subcommands. */
+
+struct cmd_list_element *disablelist;
+
+/* Chain containing all defined delete subcommands. */
+
+struct cmd_list_element *deletelist;
+
+/* Chain containing all defined "enable breakpoint" subcommands. */
+
+struct cmd_list_element *enablebreaklist;
+
+/* Chain containing all defined set subcommands */
+
+struct cmd_list_element *setlist;
+
+/* Chain containing all defined \"set history\". */
+
+struct cmd_list_element *sethistlist;
+
+/* Chain containing all defined \"unset history\". */
+
+struct cmd_list_element *unsethistlist;
+
+/* stdio stream that command input is being read from. */
+
+FILE *instream;
+
+/* Current working directory. */
+
+char *current_directory;
+
+/* The directory name is actually stored here (usually). */
+static char dirbuf[MAXPATHLEN];
+
+#ifdef KERNELDEBUG
+/* Nonzero if we're debugging /dev/mem or a kernel crash dump */
+
+int kernel_debugging = 1;
+#endif
+
+/* Nonzero to inhibit confirmation of quitting or restarting
+ a stopped inferior. */
+int inhibit_confirm;
+
+/* Nonzero if we can write in text or core file */
+
+int writeable_text;
+
+/* The number of lines on a page, and the number of spaces
+ in a line. */
+int linesize, pagesize;
+
+/* Nonzero if we should refrain from using an X window. */
+
+int inhibit_windows = 0;
+
+/* Function to call before reading a command, if nonzero.
+ The function receives two args: an input stream,
+ and a prompt string. */
+
+void (*window_hook) ();
+
+extern int frame_file_full_name;
+int xgdb_verbose;
+
+void execute_command();
+void free_command_lines ();
+char *gdb_readline ();
+char *command_line_input ();
+static void initialize_main ();
+static void initialize_cmd_lists ();
+void command_loop ();
+static void source_command ();
+static void print_gdb_version ();
+static void float_handler ();
+static void cd_command ();
+
+char *getenv ();
+
+/* gdb prints this when reading a command interactively */
+static char *prompt;
+
+/* Buffer used for reading command lines, and the size
+ allocated for it so far. */
+
+char *line;
+int linesize;
+
+
+/* This is how `error' returns to command level. */
+
+jmp_buf to_top_level;
+
+void
+return_to_top_level ()
+{
+ quit_flag = 0;
+ immediate_quit = 0;
+ clear_breakpoint_commands ();
+ clear_momentary_breakpoints ();
+ disable_current_display ();
+ do_cleanups (0);
+ longjmp (to_top_level, 1);
+}
+
+/* Call FUNC with arg ARG, catching any errors.
+ If there is no error, return the value returned by FUNC.
+ If there is an error, return zero after printing ERRSTRING
+ (which is in addition to the specific error message already printed). */
+
+int
+catch_errors (func, arg, errstring)
+ int (*func) ();
+ int arg;
+ char *errstring;
+{
+ jmp_buf saved;
+ int val;
+ struct cleanup *saved_cleanup_chain;
+
+ saved_cleanup_chain = save_cleanups ();
+
+ bcopy (to_top_level, saved, sizeof (jmp_buf));
+
+ if (setjmp (to_top_level) == 0)
+ val = (*func) (arg);
+ else
+ {
+ fprintf (stderr, "%s\n", errstring);
+ val = 0;
+ }
+
+ restore_cleanups (saved_cleanup_chain);
+
+ bcopy (saved, to_top_level, sizeof (jmp_buf));
+ return val;
+}
+
+/* Handler for SIGHUP. */
+
+static void
+disconnect ()
+{
+ kill_inferior_fast ();
+ signal (SIGHUP, SIG_DFL);
+ kill (getpid (), SIGHUP);
+}
+
+/* Clean up on error during a "source" command (or execution of a
+ user-defined command).
+ Close the file opened by the command
+ and restore the previous input stream. */
+
+static void
+source_cleanup (stream)
+ FILE *stream;
+{
+ /* Instream may be 0; set to it when executing user-defined command. */
+ if (instream)
+ fclose (instream);
+ instream = stream;
+}
+
+/*
+ * Source $HOME/.gdbinit and $cwd/.gdbinit.
+ * If X is enabled, also $HOME/.xgdbinit and $cwd/.xgdbinit.source
+ */
+void
+source_init_files()
+{
+ char *homedir, initfile[256];
+ int samedir = 0;
+
+ /* Read init file, if it exists in home directory */
+ homedir = getenv ("HOME");
+ if (homedir) {
+ struct stat homebuf, cwdbuf;
+
+ sprintf(initfile, "%s/.gdbinit", homedir);
+ if (access (initfile, R_OK) == 0)
+ if (!setjmp (to_top_level))
+ source_command (initfile);
+ if (!inhibit_windows) {
+ sprintf(initfile, "%s/.xgdbinit", homedir);
+ if (access (initfile, R_OK) == 0)
+ if (!setjmp (to_top_level))
+ source_command (initfile);
+ }
+ /* Determine if current directory is the same as the home
+ directory, so we don't source the same file twice. */
+
+ bzero (&homebuf, sizeof (struct stat));
+ bzero (&cwdbuf, sizeof (struct stat));
+
+ stat(homedir, &homebuf);
+ stat(".", &cwdbuf);
+
+ samedir = bcmp(&homebuf, &cwdbuf, sizeof(struct stat)) == 0;
+ }
+ /* Read the input file in the current directory, *if* it isn't
+ the same file (it should exist, also). */
+ if (!samedir) {
+ if (access (".gdbinit", R_OK) == 0)
+ if (!setjmp (to_top_level))
+ source_command (".gdbinit");
+ if (access (".xgdbinit", R_OK) == 0)
+ if (!setjmp (to_top_level))
+ source_command (".xgdbinit");
+ }
+}
+
+
+int
+main (argc, argv, envp)
+ int argc;
+ char **argv;
+ char **envp;
+{
+ int count;
+ int inhibit_gdbinit = 0;
+ int quiet = 1;
+ int batch = 0;
+ register int i;
+ char *cp;
+
+ /* XXX Windows only for xgdb. */
+ char *strrchr();
+ if (cp = strrchr(argv[0], '/'))
+ ++cp;
+ else
+ cp = argv[0];
+ if (*cp != 'x')
+ inhibit_windows = 1;
+
+#if defined (ALIGN_STACK_ON_STARTUP)
+ i = (int) &count & 0x3;
+ if (i != 0)
+ alloca (4 - i);
+#endif
+
+ quit_flag = 0;
+ linesize = 100;
+ line = (char *) xmalloc (linesize);
+ *line = 0;
+ instream = stdin;
+
+ getwd (dirbuf);
+ current_directory = dirbuf;
+
+#ifdef SET_STACK_LIMIT_HUGE
+ {
+ struct rlimit rlim;
+
+ /* Set the stack limit huge so that alloca (particularly stringtab
+ * in dbxread.c) does not fail. */
+ getrlimit (RLIMIT_STACK, &rlim);
+ original_stack_limit = rlim.rlim_cur;
+ rlim.rlim_cur = rlim.rlim_max;
+ setrlimit (RLIMIT_STACK, &rlim);
+ }
+#endif /* SET_STACK_LIMIT_HUGE */
+
+ /* Look for flag arguments. */
+
+ for (i = 1; i < argc; i++)
+ {
+ if (!strcmp (argv[i], "-q") || !strcmp (argv[i], "-quiet"))
+ quiet = 1;
+ else if (!strcmp (argv[i], "-nx"))
+ inhibit_gdbinit = 1;
+ else if (!strcmp (argv[i], "-nw"))
+ inhibit_windows = 1;
+ else if (!strcmp (argv[i], "-batch"))
+ batch = 1, quiet = 1;
+ else if (!strcmp (argv[i], "-fullname"))
+ frame_file_full_name = 1;
+ else if (!strcmp (argv[i], "-xgdb_verbose"))
+ xgdb_verbose = 1;
+ /* -help: print a summary of command line switches. */
+ else if (!strcmp (argv[i], "-help"))
+ {
+ fputs ("\
+This is GDB, the GNU debugger. Use the command\n\
+ gdb [options] [executable [core-file]]\n\
+to enter the debugger.\n\
+\n\
+Options available are:\n\
+ -help Print this message.\n\
+ -quiet Do not print version number on startup.\n\
+ -fullname Output information used by emacs-GDB interface.\n\
+ -batch Exit after processing options.\n\
+ -nx Do not read .gdbinit file.\n\
+ -tty TTY Use TTY for input/output by the program being debugged.\n\
+ -cd DIR Change current directory to DIR.\n\
+ -directory DIR Search for source files in DIR.\n\
+ -command FILE Execute GDB commands from FILE.\n\
+ -symbols SYMFILE Read symbols from SYMFILE.\n\
+ -exec EXECFILE Use EXECFILE as the executable.\n\
+ -se FILE Use FILE as symbol file and executable file.\n\
+ -core COREFILE Analyze the core dump COREFILE.\n\
+ -w Writeable text.\n\
+ -v Print GNU message and version number on startup.\n\
+ -nc Don't confirm quit or run commands.\n\
+\n\
+For more information, type \"help\" from within GDB, or consult the\n\
+GDB manual (available as on-line info or a printed manual).\n", stderr);
+ /* Exiting after printing this message seems like
+ the most useful thing to do. */
+ exit (0);
+ }
+ else if (!strcmp (argv[i], "-w"))
+ writeable_text = 1;
+ else if (!strcmp (argv[i], "-v"))
+ quiet = 0;
+ else if (!strcmp (argv[i], "-nc"))
+ inhibit_confirm = 1;
+ else if (argv[i][0] == '-')
+ /* Other options take arguments, so don't confuse an
+ argument with an option. */
+ i++;
+ }
+
+ /* Run the init function of each source file */
+
+ initialize_cmd_lists (); /* This needs to be done first */
+ initialize_all_files ();
+ initialize_main (); /* But that omits this file! Do it now */
+ initialize_signals ();
+
+ if (!quiet)
+ print_gdb_version ();
+
+ /* Process the command line arguments. */
+
+ count = 0;
+ for (i = 1; i < argc; i++)
+ {
+ extern void exec_file_command (), symbol_file_command ();
+ extern void core_file_command ();
+ register char *arg = argv[i];
+ /* Args starting with - say what to do with the following arg
+ as a filename. */
+ if (arg[0] == '-')
+ {
+ extern void tty_command (), directory_command ();
+
+ if (!strcmp (arg, "-q") || !strcmp (arg, "-nx")
+ || !strcmp (arg, "-quiet") || !strcmp (arg, "-batch")
+ || !strcmp (arg, "-fullname") || !strcmp (arg, "-nw")
+ || !strcmp (arg, "-xgdb_verbose")
+ || !strcmp (arg, "-help")
+ || !strcmp (arg, "-k")
+ || !strcmp (arg, "-w")
+ || !strcmp (arg, "-v")
+ || !strcmp (arg, "-nc"))
+ /* Already processed above */
+ continue;
+
+ if (++i == argc)
+ fprintf (stderr, "No argument follows \"%s\".\n", arg);
+ if (!setjmp (to_top_level))
+ {
+ /* -s foo: get syms from foo. -e foo: execute foo.
+ -se foo: do both with foo. -c foo: use foo as core dump. */
+ if (!strcmp (arg, "-se"))
+ {
+ exec_file_command (argv[i], !batch);
+ symbol_file_command (argv[i], !batch);
+ }
+ else if (!strcmp (arg, "-s") || !strcmp (arg, "-symbols"))
+ symbol_file_command (argv[i], !batch);
+ else if (!strcmp (arg, "-e") || !strcmp (arg, "-exec"))
+ exec_file_command (argv[i], !batch);
+ else if (!strcmp (arg, "-c") || !strcmp (arg, "-core"))
+ core_file_command (argv[i], !batch);
+ /* -x foo: execute commands from foo. */
+ else if (!strcmp (arg, "-x") || !strcmp (arg, "-command")
+ || !strcmp (arg, "-commands"))
+ source_command (argv[i]);
+ /* -d foo: add directory `foo' to source-file directory
+ search-list */
+ else if (!strcmp (arg, "-d") || !strcmp (arg, "-dir")
+ || !strcmp (arg, "-directory"))
+ directory_command (argv[i], 0);
+ /* -cd FOO: specify current directory as FOO.
+ GDB remembers the precise string FOO as the dirname. */
+ else if (!strcmp (arg, "-cd"))
+ {
+ cd_command (argv[i], 0);
+ init_source_path ();
+ }
+ /* -t /def/ttyp1: use /dev/ttyp1 for inferior I/O. */
+ else if (!strcmp (arg, "-t") || !strcmp (arg, "-tty"))
+ tty_command (argv[i], 0);
+
+ else
+ error ("Unknown command-line switch: \"%s\"\n", arg);
+ }
+ }
+ else
+ {
+ /* Args not thus accounted for
+ are treated as, first, the symbol/executable file
+ and, second, the core dump file. */
+ count++;
+ if (!setjmp (to_top_level))
+ switch (count)
+ {
+ case 1:
+ exec_file_command (arg, !batch);
+ symbol_file_command (arg, !batch);
+ break;
+
+ case 2:
+ core_file_command (arg, !batch);
+ break;
+
+ case 3:
+ fprintf (stderr, "Excess command line args ignored. (%s%s)\n",
+ arg, (i == argc - 1) ? "" : " ...");
+ }
+ }
+ }
+
+ if (!inhibit_gdbinit)
+ source_init_files();
+
+ if (batch)
+ {
+#if 0
+ fatal ("Attempt to read commands from stdin in batch mode.");
+#endif
+ /* We have hit the end of the batch file. */
+ exit (0);
+ }
+
+ if (!quiet)
+ printf ("Type \"help\" for a list of commands.\n");
+
+ /* The command loop. */
+
+ while (1)
+ {
+ if (!setjmp (to_top_level))
+ command_loop ();
+ if (ISATTY(stdin))
+ clearerr (stdin); /* Don't get hung if C-d is typed. */
+ else if (feof(instream)) /* Avoid endless loops for redirected stdin */
+ break;
+ }
+ exit (0);
+}
+
+
+static void
+do_nothing ()
+{
+}
+
+/* Read commands from `instream' and execute them
+ until end of file. */
+void
+command_loop ()
+{
+ struct cleanup *old_chain;
+ register int toplevel = (instream == stdin);
+ register int interactive = (toplevel && ISATTY(stdin));
+
+ while (!feof (instream))
+ {
+ register char *cmd_line;
+
+ quit_flag = 0;
+ if (interactive)
+ reinitialize_more_filter ();
+ old_chain = make_cleanup (do_nothing, 0);
+ cmd_line = command_line_input (prompt, toplevel);
+ execute_command (cmd_line, toplevel);
+ /* Do any commands attached to breakpoint we stopped at. */
+ do_breakpoint_commands ();
+ do_cleanups (old_chain);
+ }
+}
+
+/* Commands call this if they do not want to be repeated by null lines. */
+
+void
+dont_repeat ()
+{
+ /* If we aren't reading from standard input, we are saving the last
+ thing read from stdin in line and don't want to delete it. Null lines
+ won't repeat here in any case. */
+ if (instream == stdin)
+ *line = 0;
+}
+
+/* Read a line from the stream "instream" without command line editing.
+
+ It prints PROMPT once at the start.
+ Action is compatible with "readline" (i.e., space for typing is
+ malloced & should be freed by caller). */
+char *
+gdb_readline (prompt)
+ char *prompt;
+{
+ int c;
+ char *result;
+ int input_index = 0;
+ int result_size = 80;
+
+ if (prompt)
+ {
+ printf (prompt);
+ fflush (stdout);
+ }
+
+ result = (char *) xmalloc (result_size);
+
+ while (1)
+ {
+ c = fgetc (instream ? instream : stdin);
+ if (c == EOF)
+ {
+ free(result);
+ return ((char *)0);
+ }
+ if (c == '\n')
+ break;
+
+ result[input_index++] = c;
+ if (input_index >= result_size)
+ {
+ result_size <= 1;
+ result = (char *)xrealloc(result, result_size);
+ }
+ }
+ result[input_index++] = '\0';
+ return result;
+}
+
+/* Declaration for fancy readline with command line editing. */
+char *readline ();
+
+/* Variables which control command line editing and history
+ substitution. These variables are given default values at the end
+ of this file. */
+static int command_editing_p;
+static int history_expansion_p;
+static int write_history_p;
+static int history_size;
+static char *history_filename;
+
+/* Variables which are necessary for fancy command line editing. */
+char *gdb_completer_word_break_characters =
+ " \t\n!@#$%^&*()-+=|~`}{[]\"';:?/>.<,";
+
+/* Functions that are used as part of the fancy command line editing. */
+
+/* Generate symbol names one by one for the completer. If STATE is
+ zero, then we need to initialize, otherwise the initialization has
+ already taken place. TEXT is what we expect the symbol to start
+ with. RL_LINE_BUFFER is available to be looked at; it contains the
+ entire text of the line. RL_POINT is the offset in that line of
+ the cursor. You should pretend that the line ends at RL_POINT. */
+char *
+symbol_completion_function (text, state)
+ char *text;
+ int state;
+{
+ char **make_symbol_completion_list ();
+ static char **list = (char **)NULL;
+ static int index;
+ char *output;
+ extern char *rl_line_buffer;
+ extern int rl_point;
+ char *tmp_command, *p;
+ struct cmd_list_element *c, *result_list;
+
+ if (!state)
+ {
+ /* Free the storage used by LIST, but not by the strings inside. This is
+ because rl_complete_internal () frees the strings. */
+ if (list)
+ free (list);
+ list = 0;
+ index = 0;
+
+ /* Decide whether to complete on a list of gdb commands or on
+ symbols. */
+ tmp_command = (char *) alloca (rl_point + 1);
+ p = tmp_command;
+
+ strncpy (tmp_command, rl_line_buffer, rl_point);
+ tmp_command[rl_point] = '\0';
+
+ if (rl_point == 0)
+ {
+ /* An empty line we want to consider ambiguous; that is,
+ it could be any command. */
+ c = (struct cmd_list_element *) -1;
+ result_list = 0;
+ }
+ else
+ c = lookup_cmd_1 (&p, cmdlist, &result_list, 1);
+
+ /* Move p up to the next interesting thing. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ if (!c)
+ /* He's typed something unrecognizable. Sigh. */
+ list = (char **) 0;
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ if (p + strlen(text) != tmp_command + rl_point)
+ error ("Unrecognized command.");
+
+ /* He's typed something ambiguous. This is easier. */
+ if (result_list)
+ list = complete_on_cmdlist (*result_list->prefixlist, text);
+ else
+ list = complete_on_cmdlist (cmdlist, text);
+ }
+ else
+ {
+ /* If we've gotten this far, gdb has recognized a full
+ command. There are several possibilities:
+
+ 1) We need to complete on the command.
+ 2) We need to complete on the possibilities coming after
+ the command.
+ 2) We need to complete the text of what comes after the
+ command. */
+
+ if (!*p && *text)
+ /* Always (might be longer versions of thie command). */
+ list = complete_on_cmdlist (result_list, text);
+ else if (!*p && !*text)
+ {
+ if (c->prefixlist)
+ list = complete_on_cmdlist (*c->prefixlist, "");
+ else
+ list = make_symbol_completion_list ("");
+ }
+ else
+ {
+ if (c->prefixlist && !c->allow_unknown)
+ {
+ *p = '\0';
+ error ("\"%s\" command requires a subcommand.",
+ tmp_command);
+ }
+ else
+ list = make_symbol_completion_list (text);
+ }
+ }
+ }
+
+ /* If the debugged program wasn't compiled with symbols, or if we're
+ clearly completing on a command and no command matches, return
+ NULL. */
+ if (!list)
+ return ((char *)NULL);
+
+ output = list[index];
+ if (output)
+ index++;
+
+ return (output);
+}
+
+
+void
+print_prompt ()
+{
+ if (prompt)
+ {
+ printf ("%s", prompt);
+ fflush (stdout);
+ }
+}
+
+
+#ifdef HAVE_TERMIO
+#include <termio.h>
+static struct termio norm_tty;
+
+static void
+suspend_sig()
+{
+ int tty = fileno(stdin);
+ struct termio cur_tty;
+
+ ioctl(tty, TCGETA, &cur_tty);
+ ioctl(tty, TCSETAW, &norm_tty);
+
+ (void) sigsetmask(0);
+ signal(SIGTSTP, SIG_DFL);
+ kill(0, SIGTSTP);
+
+ /*
+ * we've just been resumed -- current tty params become new
+ * 'normal' params (in case tset/stty was done while we were
+ * suspended). Merge values that readline might have changed
+ * into new params, then restore term mode.
+ */
+ ioctl(tty, TCGETA, &norm_tty);
+ cur_tty.c_lflag = (cur_tty.c_lflag & (ICANON|ECHO|ISIG)) |
+ (norm_tty.c_lflag &~ (ICANON|ECHO|ISIG));
+ cur_tty.c_iflag = (cur_tty.c_iflag & (IXON|ISTRIP|INPCK)) |
+ (norm_tty.c_iflag &~ (IXON|ISTRIP|INPCK));
+ ioctl(tty, TCSETAW, &cur_tty);
+
+ signal(SIGTSTP, suspend_sig);
+ print_prompt();
+
+ /*
+ * Forget about any previous command -- null line now will do
+ * nothing.
+ */
+ dont_repeat();
+}
+
+#else
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sgtty.h>
+
+static struct sgttyb norm_tty;
+static struct tchars norm_tchars;
+static struct ltchars norm_ltchars;
+static int norm_lflags;
+
+#ifdef PASS8
+#define RL_TFLAGS (RAW|CRMOD|ECHO|CBREAK|PASS8)
+#else
+#define RL_TFLAGS (RAW|CRMOD|ECHO|CBREAK)
+#endif
+
+static void
+suspend_sig()
+{
+ int tty = fileno(stdin);
+ struct sgttyb cur_tty;
+ struct tchars cur_tchars;
+ struct ltchars cur_ltchars;
+ int cur_lflags;
+ int cur_flags;
+
+ ioctl(tty, TIOCGETP, &cur_tty);
+ ioctl(tty, TIOCGETC, &cur_tchars);
+ ioctl(tty, TIOCLGET, &cur_lflags);
+ ioctl(tty, TIOCGLTC, &cur_ltchars);
+
+ ioctl(tty, TIOCSETP, &norm_tty);
+ ioctl(tty, TIOCSETC, &norm_tchars);
+ ioctl(tty, TIOCLSET, &norm_lflags);
+ ioctl(tty, TIOCSLTC, &norm_ltchars);
+
+ (void) sigsetmask(0);
+ signal(SIGTSTP, SIG_DFL);
+ kill(0, SIGTSTP);
+
+ /*
+ * we've just been resumed -- current tty params become new
+ * 'normal' params (in case tset/stty was done while we were
+ * suspended). Merge values that readline might have changed
+ * into new params, then restore term mode.
+ */
+ ioctl(tty, TIOCGETP, &norm_tty);
+ cur_flags = cur_tty.sg_flags;
+ cur_tty = norm_tty;
+ cur_tty.sg_flags = (cur_tty.sg_flags &~ RL_TFLAGS)
+ | (cur_flags & RL_TFLAGS);
+
+ ioctl(tty, TIOCLGET, &norm_lflags);
+#ifdef LPASS8
+ cur_lflags = (cur_lflags &~ LPASS8) | (cur_flags & LPASS8);
+#endif
+ ioctl(tty, TIOCGETC, &norm_tchars);
+ ioctl(tty, TIOCGLTC, &norm_ltchars);
+
+ ioctl(tty, TIOCSETP, &cur_tty);
+ ioctl(tty, TIOCSETC, &cur_tchars);
+ ioctl(tty, TIOCLSET, &cur_lflags);
+ ioctl(tty, TIOCSLTC, &cur_ltchars);
+
+ signal(SIGTSTP, suspend_sig);
+ print_prompt();
+
+ /*
+ * Forget about any previous command -- null line now will do
+ * nothing.
+ */
+ dont_repeat();
+}
+#endif /* HAVE_TERMIO */
+
+/* Initialize signal handlers. */
+initialize_signals ()
+{
+ extern void request_quit ();
+ int tty = fileno(stdin);
+
+ signal (SIGINT, request_quit);
+
+ /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get
+ passed to the inferior, which we don't want. It would be
+ possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but
+ on BSD4.3 systems using vfork, that will (apparently) affect the
+ GDB process as well as the inferior (the signal handling tables
+ being shared between the two, apparently). Since we establish
+ a handler for SIGQUIT, when we call exec it will set the signal
+ to SIG_DFL for us. */
+ signal (SIGQUIT, do_nothing);
+ if (signal (SIGHUP, do_nothing) != SIG_IGN)
+ signal (SIGHUP, disconnect);
+ signal (SIGFPE, float_handler);
+
+ ioctl(tty, TIOCGETP, &norm_tty);
+ ioctl(tty, TIOCLGET, &norm_lflags);
+ ioctl(tty, TIOCGETC, &norm_tchars);
+ ioctl(tty, TIOCGLTC, &norm_ltchars);
+ signal(SIGTSTP, suspend_sig);
+}
+
+char *
+finish_command_input(inputline, repeat, interactive)
+ register char *inputline;
+ int repeat;
+ int interactive;
+{
+ static char *do_free;
+
+ if (do_free) {
+ free(do_free);
+ do_free = NULL;
+ }
+
+ /* Do history expansion if that is wished. */
+ if (interactive && history_expansion_p) {
+ int expanded;
+
+ expanded = history_expand(inputline, &do_free);
+ if (expanded) {
+ /* Print the changes. */
+ puts(do_free);
+
+ /* An error acts like no input. */
+ if (expanded < 0) {
+ *do_free = 0;
+ return (do_free);
+ }
+ }
+ inputline = do_free;
+ }
+ /* get rid of any leading whitespace */
+ while (isspace(*inputline))
+ ++inputline;
+ /*
+ * If we just got an empty line, and that is supposed to repeat the
+ * previous command, return the value in the global buffer.
+ */
+ if (*inputline == 0) {
+ if (repeat)
+ return (line);
+ } else if (interactive)
+ add_history(inputline);
+
+ /*
+ * If line is a comment, clear it out.
+ * Note: comments are added to the command history. This is useful
+ * when you type a command, and then realize you don't want to
+ * execute it quite yet. You can comment out the command and then
+ * later fetch it from the value history and remove the '#'.
+ */
+ if (*inputline == '#')
+ *inputline = 0;
+ else if (repeat) {
+ /* Save into global buffer. */
+ register int i = strlen(inputline) + 1;
+
+ if (i > linesize) {
+ line = xrealloc(line, i);
+ linesize = i;
+ }
+ strcpy(line, inputline);
+ }
+ return (inputline);
+}
+
+static char *
+get_a_cmd_line(prompt, interactive)
+ char *prompt;
+ int interactive;
+{
+ register char *cp;
+
+ /* Control-C quits instantly if typed while reading input. */
+ immediate_quit++;
+ if (interactive && command_editing_p) {
+ extern void (*rl_event_hook)();
+
+ rl_event_hook = window_hook;
+ cp = readline(prompt);
+ } else {
+ if (interactive) {
+ if (window_hook) {
+ print_prompt();
+ (*window_hook)();
+ }
+ } else
+ prompt = NULL;
+ cp = gdb_readline(prompt);
+ }
+ --immediate_quit;
+ return (cp);
+}
+
+/* Read one line from the command input stream `instream'
+ Returns the address of the start of the line.
+
+ *If* the instream == stdin & stdin is a terminal, the line read
+ is copied into the file line saver (global var char *line,
+ length linesize) so that it can be duplicated.
+
+ This routine either uses fancy command line editing or
+ simple input as the user has requested. */
+
+char *
+command_line_input(prompt, repeat)
+ char *prompt;
+ int repeat;
+{
+ static char *do_free;
+ register int interactive = (instream == stdin && ISATTY(instream));
+ register char *cp;
+ register int i;
+
+ if (do_free) {
+ free(do_free);
+ do_free = NULL;
+ }
+ cp = get_a_cmd_line(prompt, interactive);
+
+ /*
+ * handle continued lines (this loop is not particularly
+ * efficient because it's rare).
+ */
+ while (cp && cp[i = strlen(cp) - 1] == '\\') {
+ register char *np = get_a_cmd_line(prompt, interactive);
+ register int j;
+
+ if (np == NULL) {
+ cp[i] = 0;
+ break;
+ }
+ j = strlen(np);
+ cp = xrealloc(cp, i + j + 1);
+ strcpy(cp + i, np);
+ free(np);
+ }
+ if (cp == NULL)
+ return ("");
+ do_free = cp;
+ return (finish_command_input(cp, repeat, interactive));
+}
+
+
+#define MAX_USER_ARGS 32
+
+static struct user_args {
+ struct {
+ char *arg;
+ int len;
+ } a[10];
+} uargs[MAX_USER_ARGS];
+
+static struct user_args *user_arg = uargs;
+
+static void
+arg_cleanup(ap)
+ struct user_args *ap;
+{
+ user_arg = ap;
+}
+
+/* Bind arguments $arg0, $arg1, ..., for a user defined command. */
+struct cleanup *
+setup_user_args(p)
+ char *p;
+{
+ register int i;
+ struct cleanup *old_chain = make_cleanup(arg_cleanup, user_arg);
+
+ if (++user_arg >= &uargs[MAX_USER_ARGS])
+ error("user defined functions nested too deeply\n");
+
+ bzero(user_arg, sizeof(*user_arg));
+
+ i = 0;
+ while (*p) {
+ while (isspace(*p))
+ ++p;
+ user_arg->a[i].arg = p;
+ while (*p && ! isspace(*p))
+ ++p;
+ user_arg->a[i].len = p - user_arg->a[i].arg;
+ ++i;
+ }
+ return (old_chain);
+}
+
+static char *
+findarg(str)
+ register char *str;
+{
+ register char *cp = str;
+ extern char *index();
+
+ while (cp = index(cp, '$')) {
+ if (strncmp(cp, "$arg", 4) == 0 && isdigit(cp[4]))
+ return (cp);
+ ++cp;
+ }
+ return (char *)0;
+}
+
+/* expand arguments from "line" into "new" */
+static void
+expand_args(line, new)
+ register char *line, *new;
+{
+ register char *cp = findarg(line);
+
+ while (cp = findarg(line)) {
+ int i, len;
+
+ bcopy(line, new, cp - line);
+ new += cp - line;
+ i = cp[4] - '0';
+ if (len = user_arg->a[i].len) {
+ bcopy(user_arg->a[i].arg, new, len);
+ new += len;
+ }
+ line = cp + 5;
+ }
+ strcpy(new, line);
+}
+
+/* expand any arguments in "line" then execute the result */
+static void
+expand_and_execute(line, from_tty)
+ char *line;
+ int from_tty;
+{
+ void execute_command();
+ char new[1024];
+
+ if (! findarg(line)) {
+ execute_command(line, from_tty);
+ return;
+ }
+ expand_args(line, new);
+ execute_command(new, from_tty);
+}
+
+char *
+read_one_command_line(prompt, from_tty)
+ char *prompt;
+{
+ register char *p, *p1;
+
+ dont_repeat();
+ p = command_line_input(prompt, from_tty);
+
+ /* Remove trailing blanks. */
+ p1 = p + strlen(p);
+ while (--p1 > p && (*p1 == ' ' || *p1 == '\t'))
+ ;
+ *++p1 = 0;
+ return (p);
+}
+
+static char cmd_prompt[] = " > ";
+
+int
+parse_control_structure(rootcmd, from_tty, level)
+ struct command_line *rootcmd;
+ int from_tty;
+{
+ struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
+ char *prompt;
+
+ ++level;
+ prompt = from_tty? &cmd_prompt[sizeof(cmd_prompt) - 1 - 2*level] :
+ (char *)0;
+ bzero(cmd, sizeof(*cmd));
+ rootcmd->body = cmd;
+ while (1) {
+ char *p = read_one_command_line(prompt, from_tty);
+
+ p = savestring(p, strlen(p));
+ cmd->line = p;
+ if (!strncmp(p, "while ", 6)) {
+ cmd->type = CL_WHILE;
+ if (parse_control_structure(cmd, from_tty, level))
+ return (1);
+ } else if (!strncmp(p, "if ", 3)) {
+ cmd->type = CL_IF;
+ if (parse_control_structure(cmd, from_tty, level)) {
+ struct command_line *tmp;
+ int stat;
+
+ cmd->elsebody = cmd->body;
+ stat = parse_control_structure(cmd, from_tty,
+ level);
+ tmp = cmd->elsebody;
+ cmd->elsebody = cmd->body;
+ cmd->body = tmp;
+ if (stat)
+ return (1);
+ }
+ } else if (!strcmp(p, "else")) {
+ cmd->type = CL_END;
+ return (1);
+ } else if (!strcmp(p, "end")) {
+ cmd->type = CL_END;
+ return (0);
+ } else if (!strcmp(p, "exitloop")) {
+ cmd->type = CL_EXITLOOP;
+ } else {
+ cmd->type = CL_NORMAL;
+ }
+ cmd->next = (struct command_line *)xmalloc(sizeof(*cmd));
+ cmd = cmd->next;
+ bzero(cmd, sizeof(*cmd));
+ }
+ /* NOTREACHED */
+}
+
+int
+execute_control_structure(cmd)
+ register struct command_line *cmd;
+{
+ char expn[1024];
+ struct expression *cond;
+ int stat;
+
+ while (cmd) {
+ QUIT;
+ switch (cmd->type) {
+ case CL_END:
+ return (0);
+ case CL_NORMAL:
+ expand_and_execute(cmd->line, 0);
+ break;
+ case CL_WHILE:
+ expand_args(cmd->line + 6, expn);
+ cond = parse_c_expression(expn);
+ while (breakpoint_cond_eval(cond) == 0)
+ if (execute_control_structure(cmd->body))
+ break;
+ free(cond);
+ break;
+ case CL_IF:
+ expand_args(cmd->line + 3, expn);
+ cond = parse_c_expression(expn);
+ stat = breakpoint_cond_eval(cond);
+ free(cond);
+ if (stat == 0) {
+ if (execute_control_structure(cmd->body))
+ return (1);
+ } else if (cmd->elsebody) {
+ if (execute_control_structure(cmd->elsebody))
+ return (1);
+ }
+ break;
+ case CL_EXITLOOP:
+ return (1);
+ }
+ cmd = cmd->next;
+ }
+ free_all_values();
+}
+
+execute_command_lines(cmd)
+ struct command_line *cmd;
+{
+ struct cleanup *old_chain = make_cleanup(source_cleanup, instream);
+
+ /*
+ * Set the instream to 0, indicating execution of a user-defined
+ * function.
+ */
+ ++immediate_quit;
+ instream = (FILE *) 0;
+ (void)execute_control_structure(cmd);
+ --immediate_quit;
+ do_cleanups(old_chain);
+}
+
+/* do following command lines if expression true */
+if_command(p, from_tty)
+ char *p;
+ int from_tty;
+{
+ struct cleanup *old_chain;
+ struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
+ char buf[128];
+
+ sprintf(buf, "if %s", p);
+
+ bzero(cmd, sizeof(*cmd));
+ old_chain = make_cleanup(free_command_lines, cmd);
+ cmd->type = CL_IF;
+ cmd->line = savestring(buf, strlen(buf));
+ /* XXX cmd->line? */
+ if (parse_control_structure(cmd, from_tty, 0)) {
+ struct command_line *tmp;
+
+ cmd->elsebody = cmd->body;
+ (void) parse_control_structure(cmd, from_tty, 0);
+ tmp = cmd->elsebody;
+ cmd->elsebody = cmd->body;
+ cmd->body = tmp;
+ }
+ (void) execute_command_lines(cmd);
+ do_cleanups(old_chain);
+}
+
+/* do following command lines while expression true */
+while_command(p, from_tty)
+ char *p;
+ int from_tty;
+{
+ struct cleanup *old_chain;
+ struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
+ char buf[128];
+
+ sprintf(buf, "while %s", p);
+
+ bzero(cmd, sizeof(*cmd));
+ old_chain = make_cleanup(free_command_lines, cmd);
+ cmd->type = CL_WHILE;
+ cmd->line = savestring(buf, strlen(buf));
+ (void)parse_control_structure(cmd, from_tty, 0);
+ (void)execute_command_lines(cmd);
+ do_cleanups(old_chain);
+}
+
+/*
+ * Execute the line P as a command.
+ * Pass FROM_TTY as second argument to the defining function.
+ */
+void
+execute_command (p, from_tty)
+ char *p;
+ int from_tty;
+{
+ register struct cmd_list_element *c;
+ register struct command_line *cmdlines;
+
+ free_all_values();
+ if (*p) {
+ c = lookup_cmd(&p, cmdlist, "", 0, 1);
+ if (c->function == 0)
+ error("That is not a command, just a help topic.");
+ else if (c->class == (int) class_user) {
+ struct cleanup *old_chain = setup_user_args(p);
+
+ cmdlines = (struct command_line *) c->function;
+ if (cmdlines)
+ (void)execute_command_lines(cmdlines);
+
+ do_cleanups(old_chain);
+ } else
+ /* Pass null arg rather than an empty one. */
+ (*c->function) (*p ? p : 0, from_tty);
+ }
+}
+
+/*
+ * Read lines from the input stream and accumulate them in a chain of struct
+ * command_line's which is then returned.
+ */
+struct command_line *
+read_command_lines(from_tty)
+ int from_tty;
+{
+ struct cleanup *old_chain;
+ struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
+ struct command_line *next;
+
+ bzero(cmd, sizeof(*cmd));
+ old_chain = make_cleanup(free_command_lines, cmd);
+ cmd->type = CL_NOP;
+ (void)parse_control_structure(cmd, from_tty, 0);
+ dont_repeat();
+ discard_cleanups(old_chain);
+ next = cmd->body;
+ free(cmd);
+ return (next);
+}
+
+/* Free a chain of struct command_line's. */
+
+void
+free_command_lines(cmds)
+ struct command_line *cmds;
+{
+ struct command_line *next;
+
+ while (cmds) {
+ if (cmds->body)
+ free(cmds->body);
+ if (cmds->elsebody)
+ free(cmds->elsebody);
+ if (cmds->line)
+ free(cmds->line);
+ next = cmds->next;
+ free(cmds);
+ cmds = next;
+ }
+}
+
+/* Add an element to the list of info subcommands. */
+
+void
+add_info (name, fun, doc)
+ char *name;
+ void (*fun) ();
+ char *doc;
+{
+ add_cmd (name, no_class, fun, doc, &infolist);
+}
+
+/* Add an alias to the list of info subcommands. */
+
+void
+add_info_alias (name, oldname, abbrev_flag)
+ char *name;
+ char *oldname;
+ int abbrev_flag;
+{
+ add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist);
+}
+
+/* The "info" command is defined as a prefix, with allow_unknown = 0.
+ Therefore, its own definition is called only for "info" with no args. */
+
+static void
+info_command ()
+{
+ printf ("\"info\" must be followed by the name of an info command.\n");
+ help_list (infolist, "info ", -1, stdout);
+}
+
+/* Add an element to the list of commands. */
+
+void
+add_com (name, class, fun, doc)
+ char *name;
+ int class;
+ void (*fun) ();
+ char *doc;
+{
+ add_cmd (name, class, fun, doc, &cmdlist);
+}
+
+/* Add an alias or abbreviation command to the list of commands. */
+
+void
+add_com_alias (name, oldname, class, abbrev_flag)
+ char *name;
+ char *oldname;
+ int class;
+ int abbrev_flag;
+{
+ add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist);
+}
+
+void
+error_no_arg (why)
+ char *why;
+{
+ error ("Argument required (%s).", why);
+}
+
+static void
+help_command (command, from_tty)
+ char *command;
+ int from_tty; /* Ignored */
+{
+ help_cmd (command, stdout);
+}
+
+static void
+validate_comname (comname)
+ char *comname;
+{
+ register char *p;
+
+ if (comname == 0)
+ error_no_arg ("name of command to define");
+
+ p = comname;
+ while (*p)
+ {
+ if (!(*p >= 'A' && *p <= 'Z')
+ && !(*p >= 'a' && *p <= 'z')
+ && !(*p >= '0' && *p <= '9')
+ && *p != '-')
+ error ("Junk in argument list: \"%s\"", p);
+ p++;
+ }
+}
+
+static void
+define_command (comname, from_tty)
+ char *comname;
+ int from_tty;
+{
+ register struct command_line *cmds;
+ register struct cmd_list_element *c;
+ char *tem = comname;
+
+ validate_comname (comname);
+
+ c = lookup_cmd (&tem, cmdlist, "", -1, 1);
+ if (c)
+ {
+ if (c->class == (int) class_user || c->class == (int) class_alias)
+ tem = "Redefine command \"%s\"? ";
+ else
+ tem = "Really redefine built-in command \"%s\"? ";
+ if (!query (tem, comname))
+ error ("Command \"%s\" not redefined.", comname);
+ }
+
+ if (from_tty)
+ {
+ printf ("Type commands for definition of \"%s\".\n\
+End with a line saying just \"end\".\n", comname);
+ fflush (stdout);
+ }
+ comname = savestring (comname, strlen (comname));
+
+ cmds = read_command_lines (from_tty);
+
+ if (c && c->class == (int) class_user)
+ free_command_lines (c->function);
+
+ add_com (comname, class_user, cmds,
+ (c && c->class == (int) class_user)
+ ? c->doc : savestring ("User-defined.", 13));
+}
+
+static void
+document_command (comname, from_tty)
+ char *comname;
+ int from_tty;
+{
+ register struct cmd_list_element *c;
+ register char *p;
+ register char *cp;
+ register char *doc = 0;
+ register int len;
+ char *tmp = comname;
+
+ validate_comname (comname);
+ c = lookup_cmd (&tmp, cmdlist, "", 0, 1);
+ if (c->class != (int) class_user)
+ error ("Command \"%s\" is built-in.", comname);
+
+ if (from_tty)
+ printf ("Type documentation for \"%s\". \
+End with a line saying just \"end\".\n", comname);
+
+ while (p = read_one_command_line(from_tty? "> " : 0, from_tty))
+ {
+ if (strcmp(p, "end") == 0)
+ break;
+ len = strlen(p) + 1;
+ if (! doc)
+ {
+ doc = xmalloc(len);
+ cp = doc;
+ }
+ else
+ {
+ int i = cp - doc;
+ doc = xrealloc(doc, i + len);
+ cp = doc + i;
+ }
+ strcpy(cp, p);
+ cp += len;
+ cp[-1] = '\n';
+ }
+ if (doc && cp > doc)
+ cp[-1] = 0;
+ if (c->doc)
+ free (c->doc);
+ c->doc = doc;
+}
+
+static void
+print_gdb_version ()
+{
+ printf ("GDB %s, Copyright (C) 1989 Free Software Foundation, Inc.\n\
+There is ABSOLUTELY NO WARRANTY for GDB; type \"info warranty\" for details.\n\
+GDB is free software and you are welcome to distribute copies of it\n\
+ under certain conditions; type \"info copying\" to see the conditions.\n",
+ version);
+}
+
+static void
+version_info ()
+{
+ immediate_quit++;
+ print_gdb_version ();
+ immediate_quit--;
+}
+
+
+/* Command to specify a prompt string instead of "(gdb) ". */
+
+void
+set_prompt_command (text)
+ char *text;
+{
+ char *p, *q;
+ register int c;
+ char *new;
+
+ if (text == 0)
+ error_no_arg ("string to which to set prompt");
+
+ new = (char *) xmalloc (strlen (text) + 2);
+ p = text; q = new;
+ while (c = *p++)
+ {
+ if (c == '\\')
+ {
+ /* \ at end of argument is used after spaces
+ so they won't be lost. */
+ if (*p == 0)
+ break;
+ c = parse_escape (&p);
+ if (c == 0)
+ break; /* C loses */
+ else if (c > 0)
+ *q++ = c;
+ }
+ else
+ *q++ = c;
+ }
+ if (*(p - 1) != '\\')
+ *q++ = ' ';
+ *q++ = '\0';
+ new = (char *) xrealloc (new, q - new);
+ free (prompt);
+ prompt = new;
+}
+
+static void
+quit_command ()
+{
+ extern void exec_file_command ();
+ if (have_inferior_p ())
+ {
+ if (inhibit_confirm || query ("The program is running. Quit anyway? "))
+ {
+ /* Prevent any warning message from reopen_exec_file, in case
+ we have a core file that's inconsistent with the exec file. */
+ exec_file_command (0, 0);
+ kill_inferior ();
+ }
+ else
+ error ("Not confirmed.");
+ }
+ /* Save the history information if it is appropriate to do so. */
+ if (write_history_p && history_filename)
+ write_history (history_filename);
+ exit (0);
+}
+
+int
+input_from_terminal_p ()
+{
+ return instream == stdin;
+}
+
+static void
+pwd_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (arg) error ("The \"pwd\" command does not take an argument: %s", arg);
+ getwd (dirbuf);
+
+ if (strcmp (dirbuf, current_directory))
+ printf ("Working directory %s\n (canonically %s).\n",
+ current_directory, dirbuf);
+ else
+ printf ("Working directory %s.\n", current_directory);
+}
+
+static void
+cd_command (dir, from_tty)
+ char *dir;
+ int from_tty;
+{
+ int len;
+ int change;
+
+ if (dir == 0)
+ error_no_arg ("new working directory");
+
+ dir = tilde_expand (dir);
+ make_cleanup (free, dir);
+
+ len = strlen (dir);
+ dir = savestring (dir, len - (len > 1 && dir[len-1] == '/'));
+ if (dir[0] == '/')
+ current_directory = dir;
+ else
+ {
+ current_directory = concat (current_directory, "/", dir);
+ free (dir);
+ }
+
+ /* Now simplify any occurrences of `.' and `..' in the pathname. */
+
+ change = 1;
+ while (change)
+ {
+ char *p;
+ change = 0;
+
+ for (p = current_directory; *p;)
+ {
+ if (!strncmp (p, "/./", 2)
+ && (p[2] == 0 || p[2] == '/'))
+ strcpy (p, p + 2);
+ else if (!strncmp (p, "/..", 3)
+ && (p[3] == 0 || p[3] == '/')
+ && p != current_directory)
+ {
+ char *q = p;
+ while (q != current_directory && q[-1] != '/') q--;
+ if (q != current_directory)
+ {
+ strcpy (q-1, p+3);
+ p = q-1;
+ }
+ }
+ else p++;
+ }
+ }
+
+ if (chdir (dir) < 0)
+ perror_with_name (dir);
+
+ if (from_tty)
+ pwd_command ((char *) 0, 1);
+}
+
+static void
+source_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ FILE *stream;
+ struct cleanup *cleanups;
+ char *file = arg;
+ char *path;
+
+ if (file == 0)
+ /* Let source without arguments read .gdbinit. */
+ file = ".gdbinit";
+
+ file = tilde_expand (file);
+ make_cleanup (free, file);
+
+#ifdef KERNELDEBUG
+ if (path = getenv(kernel_debugging? "KGDBPATH" : "GDBPATH"))
+#else
+ if (path = getenv("GDBPATH"))
+#endif
+ {
+ int fd = openp(path, 1, file, O_RDONLY, 0, 0);
+
+ if (fd == -1)
+ stream = 0;
+ else
+ stream = fdopen(fd, "r");
+ }
+ else
+ stream = fopen (file, "r");
+
+ if (stream == 0)
+ perror_with_name (file);
+
+ cleanups = make_cleanup (source_cleanup, instream);
+
+ instream = stream;
+
+ command_loop ();
+
+ do_cleanups (cleanups);
+}
+
+static void
+echo_command (text)
+ char *text;
+{
+ char *p = text;
+ register int c;
+
+ if (text)
+ while (c = *p++)
+ {
+ if (c == '\\')
+ {
+ /* \ at end of argument is used after spaces
+ so they won't be lost. */
+ if (*p == 0)
+ return;
+
+ c = parse_escape (&p);
+ if (c >= 0)
+ fputc (c, stdout);
+ }
+ else
+ fputc (c, stdout);
+ }
+ fflush(stdout);
+}
+
+static void
+dump_me_command ()
+{
+ if (query ("Should GDB dump core? "))
+ {
+ signal (SIGQUIT, SIG_DFL);
+ kill (getpid (), SIGQUIT);
+ }
+}
+
+int
+parse_binary_operation (caller, arg)
+ char *caller, *arg;
+{
+ int length;
+
+ if (!arg || !*arg)
+ return 1;
+
+ length = strlen (arg);
+
+ while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
+ length--;
+
+ if (!strncmp (arg, "on", length)
+ || !strncmp (arg, "1", length)
+ || !strncmp (arg, "yes", length))
+ return 1;
+ else
+ if (!strncmp (arg, "off", length)
+ || !strncmp (arg, "0", length)
+ || !strncmp (arg, "no", length))
+ return 0;
+ else
+ error ("\"%s\" not given a binary valued argument.", caller);
+}
+
+/* Functions to manipulate command line editing control variables. */
+
+static void
+set_editing (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ command_editing_p = parse_binary_operation ("set command-editing", arg);
+}
+
+/* Number of commands to print in each call to editing_info. */
+#define Hist_print 10
+static void
+editing_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ /* Index for history commands. Relative to history_base. */
+ int offset;
+
+ /* Number of the history entry which we are planning to display next.
+ Relative to history_base. */
+ static int num = 0;
+
+ /* The first command in the history which doesn't exist (i.e. one more
+ than the number of the last command). Relative to history_base. */
+ int hist_len;
+
+ struct _hist_entry {
+ char *line;
+ char *data;
+ } *history_get();
+ extern int history_base;
+
+ printf_filtered ("Interactive command editing is %s.\n",
+ command_editing_p ? "on" : "off");
+
+ printf_filtered ("History expansion of command input is %s.\n",
+ history_expansion_p ? "on" : "off");
+ printf_filtered ("Writing of a history record upon exit is %s.\n",
+ write_history_p ? "enabled" : "disabled");
+ printf_filtered ("The size of the history list (number of stored commands) is %d.\n",
+ history_size);
+ printf_filtered ("The name of the history record is \"%s\".\n\n",
+ history_filename ? history_filename : "");
+
+ /* Print out some of the commands from the command history. */
+ /* First determine the length of the history list. */
+ hist_len = history_size;
+ for (offset = 0; offset < history_size; offset++)
+ {
+ if (!history_get (history_base + offset))
+ {
+ hist_len = offset;
+ break;
+ }
+ }
+
+ if (arg)
+ {
+ if (arg[0] == '+' && arg[1] == '\0')
+ /* "info editing +" should print from the stored position. */
+ ;
+ else
+ /* "info editing <exp>" should print around command number <exp>. */
+ num = (parse_and_eval_address (arg) - history_base) - Hist_print / 2;
+ }
+ /* "info editing" means print the last Hist_print commands. */
+ else
+ {
+ num = hist_len - Hist_print;
+ }
+
+ if (num < 0)
+ num = 0;
+
+ /* If there are at least Hist_print commands, we want to display the last
+ Hist_print rather than, say, the last 6. */
+ if (hist_len - num < Hist_print)
+ {
+ num = hist_len - Hist_print;
+ if (num < 0)
+ num = 0;
+ }
+
+ if (num == hist_len - Hist_print)
+ printf_filtered ("The list of the last %d commands is:\n\n", Hist_print);
+ else
+ printf_filtered ("Some of the stored commands are:\n\n");
+
+ for (offset = num; offset < num + Hist_print && offset < hist_len; offset++)
+ {
+ printf_filtered ("%5d %s\n", history_base + offset,
+ (history_get (history_base + offset))->line);
+ }
+
+ /* The next command we want to display is the next one that we haven't
+ displayed yet. */
+ num += Hist_print;
+
+ /* If the user repeats this command with return, it should do what
+ "info editing +" does. This is unnecessary if arg is null,
+ because "info editing +" is not useful after "info editing". */
+ if (from_tty && arg)
+ {
+ arg[0] = '+';
+ arg[1] = '\0';
+ }
+}
+
+static void
+set_history_expansion (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ history_expansion_p = parse_binary_operation ("set history expansion", arg);
+}
+
+static void
+set_history_write (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ write_history_p = parse_binary_operation ("set history write", arg);
+}
+
+static void
+set_history (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf ("\"set history\" must be followed by the name of a history subcommand.\n");
+ help_list (sethistlist, "set history ", -1, stdout);
+}
+
+static void
+set_history_size (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (!*arg)
+ error_no_arg ("set history size");
+
+ history_size = atoi (arg);
+}
+
+static void
+set_history_filename (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int i;
+
+ if (!arg)
+ error_no_arg ("history file name");
+
+ arg = tilde_expand (arg);
+ make_cleanup (free, arg);
+
+ i = strlen (arg) - 1;
+
+ free (history_filename);
+
+ while (i > 0 && (arg[i] == ' ' || arg[i] == '\t'))
+ i--;
+ ++i;
+
+ if (!*arg)
+ history_filename = (char *) 0;
+ else
+ history_filename = savestring (arg, i + 1);
+ history_filename[i] = '\0';
+}
+
+int info_verbose;
+
+static void
+set_verbose_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ info_verbose = parse_binary_operation ("set verbose", arg);
+}
+
+static void
+verbose_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (arg)
+ error ("\"info verbose\" does not take any arguments.\n");
+
+ printf ("Verbose printing of information is %s.\n",
+ info_verbose ? "on" : "off");
+}
+
+static void
+float_handler ()
+{
+ error ("Invalid floating value encountered or computed.");
+}
+
+
+static void
+initialize_cmd_lists ()
+{
+ cmdlist = (struct cmd_list_element *) 0;
+ infolist = (struct cmd_list_element *) 0;
+ enablelist = (struct cmd_list_element *) 0;
+ disablelist = (struct cmd_list_element *) 0;
+ deletelist = (struct cmd_list_element *) 0;
+ enablebreaklist = (struct cmd_list_element *) 0;
+ setlist = (struct cmd_list_element *) 0;
+ sethistlist = (struct cmd_list_element *) 0;
+ unsethistlist = (struct cmd_list_element *) 0;
+}
+
+static void
+initialize_main ()
+{
+ char *tmpenv;
+ /* Command line editing externals. */
+ extern int (*rl_completion_entry_function)();
+ extern char *rl_completer_word_break_characters;
+ extern char *rl_readline_name;
+
+ /* Set default verbose mode on. */
+ info_verbose = 1;
+
+#ifdef KERNELDEBUG
+ if (kernel_debugging)
+ prompt = savestring ("(kgdb) ", 7);
+ else
+#endif
+ prompt = savestring ("(gdb) ", 6);
+
+ /* Set the important stuff up for command editing. */
+ command_editing_p = 1;
+ history_expansion_p = 0;
+ write_history_p = 0;
+
+ if (tmpenv = getenv ("HISTSIZE"))
+ history_size = atoi (tmpenv);
+ else
+ history_size = 256;
+
+ stifle_history (history_size);
+
+ if (tmpenv = getenv ("GDBHISTFILE"))
+ history_filename = savestring (tmpenv, strlen(tmpenv));
+ else
+ /* We include the current directory so that if the user changes
+ directories the file written will be the same as the one
+ that was read. */
+ history_filename = concat (current_directory, "/.gdb_history", "");
+
+ read_history (history_filename);
+
+ /* Setup important stuff for command line editing. */
+ rl_completion_entry_function = (int (*)()) symbol_completion_function;
+ rl_completer_word_break_characters = gdb_completer_word_break_characters;
+ rl_readline_name = "gdb";
+
+ /* Define the classes of commands.
+ They will appear in the help list in the reverse of this order. */
+
+ add_cmd ("obscure", class_obscure, 0, "Obscure features.", &cmdlist);
+ add_cmd ("alias", class_alias, 0, "Aliases of other commands.", &cmdlist);
+ add_cmd ("user", class_user, 0, "User-defined commands.\n\
+The commands in this class are those defined by the user.\n\
+Use the \"define\" command to define a command.", &cmdlist);
+ add_cmd ("support", class_support, 0, "Support facilities.", &cmdlist);
+ add_cmd ("status", class_info, 0, "Status inquiries.", &cmdlist);
+ add_cmd ("files", class_files, 0, "Specifying and examining files.", &cmdlist);
+ add_cmd ("breakpoints", class_breakpoint, 0, "Making program stop at certain points.", &cmdlist);
+ add_cmd ("data", class_vars, 0, "Examining data.", &cmdlist);
+ add_cmd ("stack", class_stack, 0, "Examining the stack.\n\
+The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\
+counting from zero for the innermost (currently executing) frame.\n\n\
+At any time gdb identifies one frame as the \"selected\" frame.\n\
+Variable lookups are done with respect to the selected frame.\n\
+When the program being debugged stops, gdb selects the innermost frame.\n\
+The commands below can be used to select other frames by number or address.",
+ &cmdlist);
+ add_cmd ("running", class_run, 0, "Running the program.", &cmdlist);
+
+ add_com ("pwd", class_files, pwd_command,
+ "Print working directory. This is used for your program as well.");
+ add_com ("cd", class_files, cd_command,
+ "Set working directory to DIR for debugger and program being debugged.\n\
+The change does not take effect for the program being debugged\n\
+until the next time it is started.");
+
+ add_cmd ("prompt", class_support, set_prompt_command,
+ "Change gdb's prompt from the default of \"(gdb)\"",
+ &setlist);
+ add_com ("echo", class_support, echo_command,
+ "Print a constant string. Give string as argument.\n\
+C escape sequences may be used in the argument.\n\
+No newline is added at the end of the argument;\n\
+use \"\\n\" if you want a newline to be printed.\n\
+Since leading and trailing whitespace are ignored in command arguments,\n\
+if you want to print some you must use \"\\\" before leading whitespace\n\
+to be printed or after trailing whitespace.");
+ add_com ("document", class_support, document_command,
+ "Document a user-defined command.\n\
+Give command name as argument. Give documentation on following lines.\n\
+End with a line of just \"end\".");
+ add_com ("define", class_support, define_command,
+ "Define a new command name. Command name is argument.\n\
+Definition appears on following lines, one command per line.\n\
+End with a line of just \"end\".\n\
+Use the \"document\" command to give documentation for the new command.\n\
+Commands defined in this way do not take arguments.");
+
+ add_com ("source", class_support, source_command,
+ "Read commands from a file named FILE.\n\
+Note that the file \".gdbinit\" is read automatically in this way\n\
+when gdb is started.");
+ add_com ("quit", class_support, quit_command, "Exit gdb.");
+ add_com ("help", class_support, help_command, "Print list of commands.");
+ add_com_alias ("q", "quit", class_support, 1);
+ add_com_alias ("h", "help", class_support, 1);
+ add_com ("while", class_support, while_command,
+ "execute following commands while condition is true.\n\
+Expression for condition follows \"while\" keyword.");
+ add_com ("if", class_support, if_command,
+ "execute following commands if condition is true.\n\
+Expression for condition follows \"if\" keyword.");
+ add_cmd ("verbose", class_support, set_verbose_command,
+ "Change the number of informational messages gdb prints.",
+ &setlist);
+ add_info ("verbose", verbose_info,
+ "Status of gdb's verbose printing option.\n");
+
+ add_com ("dump-me", class_obscure, dump_me_command,
+ "Get fatal error; make debugger dump its core.");
+
+ add_cmd ("editing", class_support, set_editing,
+ "Enable or disable command line editing.\n\
+Use \"on\" to enable to enable the editing, and \"off\" to disable it.\n\
+Without an argument, command line editing is enabled.", &setlist);
+
+ add_prefix_cmd ("history", class_support, set_history,
+ "Generic command for setting command history parameters.",
+ &sethistlist, "set history ", 0, &setlist);
+
+ add_cmd ("expansion", no_class, set_history_expansion,
+ "Enable or disable history expansion on command input.\n\
+Without an argument, history expansion is enabled.", &sethistlist);
+
+ add_cmd ("write", no_class, set_history_write,
+ "Enable or disable saving of the history record on exit.\n\
+Use \"on\" to enable to enable the saving, and \"off\" to disable it.\n\
+Without an argument, saving is enabled.", &sethistlist);
+
+ add_cmd ("size", no_class, set_history_size,
+ "Set the size of the command history, \n\
+ie. the number of previous commands to keep a record of.", &sethistlist);
+
+ add_cmd ("filename", no_class, set_history_filename,
+ "Set the filename in which to record the command history\n\
+ (the list of previous commands of which a record is kept).", &sethistlist);
+
+ add_prefix_cmd ("info", class_info, info_command,
+ "Generic command for printing status.",
+ &infolist, "info ", 0, &cmdlist);
+ add_com_alias ("i", "info", class_info, 1);
+
+ add_info ("editing", editing_info, "Status of command editor.");
+
+ add_info ("version", version_info, "Report what version of GDB this is.");
+}
diff --git a/gnu/usr.bin/kgdb/ngdb.i386/Makefile b/gnu/usr.bin/kgdb/ngdb.i386/Makefile
new file mode 100644
index 000000000000..554ca98ce6cd
--- /dev/null
+++ b/gnu/usr.bin/kgdb/ngdb.i386/Makefile
@@ -0,0 +1,29 @@
+# %W% (Berkeley) %G%
+
+.include "../config/Makefile.$(MACHINE)"
+
+PROG= ngdb
+SRCS= i386bsd-dep.c blockframe.c
+GDBOBJS+= i386-pinsn.o \
+ breakpoint.o command.o copying.o core.o \
+ cplus-dem.o dbxread.o environ.o eval.o expprint.o \
+ expread.o findvar.o infcmd.o inflow.o infrun.o \
+ main.o obstack.o printcmd.o regex.o remote.o \
+ remote-sl.o source.o stack.o symmisc.o symtab.o \
+ utils.o valarith.o valops.o valprint.o values.o \
+ version.o \
+ funmap.o history.o keymaps.o readline.o \
+ init.o
+CFLAGS+= -g -I$(.CURDIR) -I.. -I$(.CURDIR)/.. -I$(.CURDIR)/../config \
+ -I/usr/src/sys.newvm \
+ -DNEWVM -DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG
+# CC= /usr/old/bin/cc
+# CC= cc -traditional
+# XXX objects should be in OBJS so that bsd.prog.mk handles their dependencies
+DPADD+= $(GDBOBJS:S/^/..\//g) ${LIBTERMCAP}
+LDADD+= $(GDBOBJS:S/^/..\//g) -ltermcap
+NOMAN= noman
+
+.PATH: $(.CURDIR)/../config $(.CURDIR)/..
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/kgdb/obstack.c b/gnu/usr.bin/kgdb/obstack.c
new file mode 100644
index 000000000000..6f4b282d1e7a
--- /dev/null
+++ b/gnu/usr.bin/kgdb/obstack.c
@@ -0,0 +1,313 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 1, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+#include "obstack.h"
+
+#ifdef __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment. */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+ But in fact it might be less smart and round addresses to as much as
+ DEFAULT_ROUNDING. So we prepare for it to do that. */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+ On some machines, copying successive ints does not work;
+ in such a case, redefine COPYING_UNIT to `long' (if that works)
+ or `char' as a last resort. */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+/* The non-GNU-C macros copy the obstack into this global variable
+ to avoid multiple evaluation. */
+
+struct obstack *_obstack;
+
+/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
+ Objects start on multiples of ALIGNMENT (0 means use default).
+ CHUNKFUN is the function to use to allocate chunks,
+ and FREEFUN the function to free them. */
+
+void
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+ struct obstack *h;
+ int size;
+ int alignment;
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+{
+ register struct _obstack_chunk* chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block.
+ Pick a number small enough that when rounded up to DEFAULT_ROUNDING
+ it is still smaller than 4096 - 4. */
+ {
+ int extra = 4;
+ if (extra < DEFAULT_ROUNDING)
+ extra = DEFAULT_ROUNDING;
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+
+ chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+}
+
+/* Allocate a new current chunk for the obstack *H
+ on the assumption that LENGTH bytes need to be added
+ to the current object, or a new object of length LENGTH allocated.
+ Copies any partial object from the end of the old chunk
+ to the beginning of the new one. */
+
+void
+_obstack_newchunk (h, length)
+ struct obstack *h;
+ int length;
+{
+ register struct _obstack_chunk* old_chunk = h->chunk;
+ register struct _obstack_chunk* new_chunk;
+ register long new_size;
+ register int obj_size = h->next_free - h->object_base;
+ register int i;
+
+ /* Compute size for new chunk. */
+ new_size = (obj_size + length) << 1;
+ if (new_size < h->chunk_size)
+ new_size = h->chunk_size;
+
+ /* Allocate and initialize the new chunk. */
+ new_chunk = h->chunk = (*h->chunkfun) (new_size);
+ new_chunk->prev = old_chunk;
+ new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+ /* Move the existing object to the new chunk.
+ Word at a time is fast and is safe because these
+ structures are aligned at least that much. */
+ for (i = (obj_size + sizeof (COPYING_UNIT) - 1) / sizeof (COPYING_UNIT) - 1;
+ i >= 0; i--)
+ ((COPYING_UNIT *)new_chunk->contents)[i]
+ = ((COPYING_UNIT *)h->object_base)[i];
+
+ h->object_base = new_chunk->contents;
+ h->next_free = h->object_base + obj_size;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+ This is here for debugging.
+ If you use it in a program, you are probably losing. */
+
+int
+_obstack_allocated_p (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp -> prev;
+ lp = plp;
+ }
+ return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+ more recently than OBJ. If OBJ is zero, free everything in H. */
+
+void
+#ifdef __STDC__
+#undef obstack_free
+obstack_free (struct obstack *h, POINTER obj)
+#else
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+#endif
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp -> prev;
+ (*h->freefun) (lp);
+ lp = plp;
+ }
+ if (lp)
+ {
+ (h)->object_base = (h)->next_free = (char *)(obj);
+ (h)->chunk_limit = lp->limit;
+ (h)->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+/* Let same .o link with output of gcc and other compilers. */
+
+#ifdef __STDC__
+void
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ obstack_free (h, obj);
+}
+#endif
+
+#if 0
+/* These are now turned off because the applications do not use it
+ and it uses bcopy via obstack_grow, which causes trouble on sysV. */
+
+/* Now define the functional versions of the obstack macros.
+ Define them to simply use the corresponding macros to do the job. */
+
+#ifdef __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+ they won't pass through the macro names in parentheses. */
+
+/* The function names appear in parentheses in order to prevent
+ the macro-definitions of the names from being expanded there. */
+
+POINTER (obstack_base) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_room (obstack);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+#endif /* 0 */
diff --git a/gnu/usr.bin/kgdb/obstack.h b/gnu/usr.bin/kgdb/obstack.h
new file mode 100644
index 000000000000..27c017e2f253
--- /dev/null
+++ b/gnu/usr.bin/kgdb/obstack.h
@@ -0,0 +1,372 @@
+/* obstack.h - object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 1, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+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! */
+
+
+/* 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 "facist 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 aymbol 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 beggining of the new larger chunk. We then carry on
+accreting characters to the end of the object as we normaly 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. */
+};
+
+#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_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_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, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#if defined (__GNUC__) && defined (__STDC__)
+
+/* For GNU C, if not -traditional,
+ we can define these macros to compute all args only once
+ without using a global variable.
+ Also, we can avoid using the `temp' slot, to make faster code. */
+
+#define obstack_object_size(OBSTACK) \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->next_free - __o->object_base); })
+
+#define obstack_room(OBSTACK) \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->chunk_limit - __o->next_free); })
+
+#define obstack_grow(OBSTACK,where,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, __len) : 0); \
+ bcopy (where, __o->next_free, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_grow0(OBSTACK,where,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len + 1 > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, __len + 1) : 0), \
+ bcopy (where, __o->next_free, __len), \
+ __o->next_free += __len, \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+#define obstack_1grow(OBSTACK,datum) \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + 1 > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, 1) : 0), \
+ *(__o->next_free)++ = (datum); \
+ (void) 0; })
+
+#define obstack_blank(OBSTACK,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, __len) : 0); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_alloc(OBSTACK,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy(OBSTACK,where,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy0(OBSTACK,where,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_finish(OBSTACK) \
+({ struct obstack *__o = (OBSTACK); \
+ void *value = (void *) __o->object_base; \
+ __o->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
+ & ~ (__o->alignment_mask)); \
+ ((__o->next_free - (char *)__o->chunk \
+ > __o->chunk_limit - (char *)__o->chunk) \
+ ? (__o->next_free = __o->chunk_limit) : 0); \
+ __o->object_base = __o->next_free; \
+ value; })
+
+#define obstack_free(OBSTACK, OBJ) \
+({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (OBJ); \
+ if (__obj >= (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ __o->next_free = __o->object_base = __obj; \
+ else (obstack_free) (__o, __obj); })
+
+#else /* not __GNUC__ or not __STDC__ */
+
+/* The non-GNU macros copy the obstack-pointer into this global variable
+ to avoid multiple evaluation. */
+
+extern struct obstack *_obstack;
+
+#define obstack_object_size(h) \
+ (unsigned) (_obstack = (h), (h)->next_free - (h)->object_base)
+
+#define obstack_room(h) \
+ (unsigned) (_obstack = (h), (h)->chunk_limit - (h)->next_free)
+
+#define obstack_grow(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), (h)->temp) : 0), \
+ bcopy (where, (h)->next_free, (h)->temp), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_grow0(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), (h)->temp + 1) : 0), \
+ bcopy (where, (h)->next_free, (h)->temp), \
+ (h)->next_free += (h)->temp, \
+ *((h)->next_free)++ = 0)
+
+#define obstack_1grow(h,datum) \
+( (((h)->next_free + 1 > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), 1) : 0), \
+ *((h)->next_free)++ = (datum))
+
+#define obstack_blank(h,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), (h)->temp) : 0), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_alloc(h,length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+#define obstack_copy(h,where,length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_copy0(h,where,length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_finish(h) \
+( (h)->temp = __PTR_TO_INT ((h)->object_base), \
+ (h)->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
+ & ~ ((h)->alignment_mask)), \
+ (((h)->next_free - (char *)(h)->chunk \
+ > (h)->chunk_limit - (char *)(h)->chunk) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ __INT_TO_PTR ((h)->temp))
+
+#ifdef __STDC__
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
+#else
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
+#endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+#endif /* not __OBSTACKS__ */
+
diff --git a/gnu/usr.bin/kgdb/printcmd.c b/gnu/usr.bin/kgdb/printcmd.c
new file mode 100644
index 000000000000..6edd7bd2c2f3
--- /dev/null
+++ b/gnu/usr.bin/kgdb/printcmd.c
@@ -0,0 +1,1867 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)printcmd.c 6.5 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Print values for GNU debugger GDB.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "symtab.h"
+#include "value.h"
+#include "expression.h"
+
+struct format_data
+{
+ int count;
+ char format;
+ char size;
+};
+
+/* Last specified output format. */
+
+static char last_format = 'x';
+
+/* Last specified examination size. 'b', 'h', 'w' or `q'. */
+
+static char last_size = 'w';
+
+/* Default address to examine next. */
+
+static CORE_ADDR next_address;
+
+/* Last address examined. */
+
+static CORE_ADDR last_examine_address;
+
+/* Contents of last address examined.
+ This is not valid past the end of the `x' command! */
+
+static value last_examine_value;
+
+/* Number of auto-display expression currently being displayed.
+ So that we can deleted it if we get an error or a signal within it.
+ -1 when not doing one. */
+
+int current_display_number;
+
+static void do_one_display ();
+
+void do_displays ();
+void print_address ();
+void print_floating ();
+void print_scalar_formatted ();
+void print_formatted_address ();
+
+
+/* Decode a format specification. *STRING_PTR should point to it.
+ OFORMAT and OSIZE are used as defaults for the format and size
+ if none are given in the format specification.
+ If OSIZE is zero, then the size field of the returned value
+ should be set only if a size is explicitly specified by the
+ user.
+ The structure returned describes all the data
+ found in the specification. In addition, *STRING_PTR is advanced
+ past the specification and past all whitespace following it. */
+
+struct format_data
+decode_format (string_ptr, oformat, osize)
+ char **string_ptr;
+ char oformat;
+ char osize;
+{
+ struct format_data val;
+ register char *p = *string_ptr;
+
+ val.format = '?';
+ val.size = '?';
+ val.count = 1;
+
+ if (*p >= '0' && *p <= '9')
+ val.count = atoi (p);
+ while (*p >= '0' && *p <= '9') p++;
+
+ /* Now process size or format letters that follow. */
+
+ while (1)
+ {
+ if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g')
+ val.size = *p++;
+#ifdef LONG_LONG
+ else if (*p == 'l')
+ {
+ val.size = 'g';
+ p++;
+ }
+#endif
+ else if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z'))
+ val.format = *p++;
+ else
+ break;
+ }
+
+#ifndef LONG_LONG
+ /* Make sure 'g' size is not used on integer types.
+ Well, actually, we can handle hex. */
+ if (val.size == 'g' && val.format != 'f' && val.format != 'x')
+ val.size = 'w';
+#endif
+
+ while (*p == ' ' || *p == '\t') p++;
+ *string_ptr = p;
+
+ /* Set defaults for format and size if not specified. */
+ if (val.format == '?')
+ {
+ if (val.size == '?')
+ {
+ /* Neither has been specified. */
+ val.format = oformat;
+ val.size = osize;
+ }
+ else
+ /* If a size is specified, any format makes a reasonable
+ default except 'i'. */
+ val.format = oformat == 'i' ? 'x' : oformat;
+ }
+ else if (val.size == '?')
+ switch (val.format)
+ {
+ case 'a':
+ case 's':
+ case 'A':
+ /* Addresses must be words. */
+ val.size = osize ? 'w' : osize;
+ break;
+ case 'f':
+ /* Floating point has to be word or giantword. */
+ if (osize == 'w' || osize == 'g')
+ val.size = osize;
+ else
+ /* Default it to giantword if the last used size is not
+ appropriate. */
+ val.size = osize ? 'g' : osize;
+ break;
+ case 'c':
+ /* Characters default to one byte. */
+ val.size = osize ? 'b' : osize;
+ break;
+ default:
+ /* The default is the size most recently specified. */
+ val.size = osize;
+ }
+
+ return val;
+}
+
+/* Print value VAL on stdout according to FORMAT, a letter or 0.
+ Do not end with a newline.
+ 0 means print VAL according to its own type.
+ SIZE is the letter for the size of datum being printed.
+ This is used to pad hex numbers so they line up. */
+
+static void
+print_formatted (val, format, size)
+ register value val;
+ register char format;
+ char size;
+{
+ int len = TYPE_LENGTH (VALUE_TYPE (val));
+
+ if (VALUE_LVAL (val) == lval_memory)
+ next_address = VALUE_ADDRESS (val) + len;
+
+ switch (format)
+ {
+ case 's':
+ next_address = VALUE_ADDRESS (val)
+ + value_print (value_addr (val), stdout, 0, Val_pretty_default);
+ break;
+
+ case 'i':
+ next_address = VALUE_ADDRESS (val)
+ + print_insn (VALUE_ADDRESS (val), stdout);
+ break;
+
+ default:
+ if (format == 0
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION
+ || VALUE_REPEATED (val))
+ value_print (val, stdout, format, Val_pretty_default);
+ else
+ print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val),
+ format, size, stdout);
+ }
+}
+
+/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
+ according to letters FORMAT and SIZE on STREAM.
+ FORMAT may not be zero. Formats s and i are not supported at this level.
+
+ This is how the elements of an array or structure are printed
+ with a format. */
+
+void
+print_scalar_formatted (valaddr, type, format, size, stream)
+ char *valaddr;
+ struct type *type;
+ char format;
+ int size;
+ FILE *stream;
+{
+ LONGEST val_long;
+ int len = TYPE_LENGTH (type);
+
+ if (size == 'g' && sizeof (LONGEST) < 8
+ && format == 'x')
+ {
+ /* ok, we're going to have to get fancy here. Assumption: a
+ long is four bytes. */
+ unsigned long v1, v2, tmp;
+
+ v1 = unpack_long (builtin_type_long, valaddr);
+ v2 = unpack_long (builtin_type_long, valaddr + 4);
+
+#ifdef BYTES_BIG_ENDIAN
+#else
+ /* Little endian -- swap the two for printing */
+ tmp = v1;
+ v1 = v2;
+ v2 = tmp;
+#endif
+
+ switch (format)
+ {
+ case 'x':
+ fprintf_filtered (stream, "0x%08x%08x", v1, v2);
+ break;
+ default:
+ error ("Output size \"g\" unimplemented for format \"%c\".",
+ format);
+ }
+ return;
+ }
+
+ val_long = unpack_long (type, valaddr);
+
+ /* If value is unsigned, truncate it in case negative. */
+ if (format != 'd')
+ {
+ if (len == sizeof (char))
+ val_long &= (1 << 8 * sizeof(char)) - 1;
+ else if (len == sizeof (short))
+ val_long &= (1 << 8 * sizeof(short)) - 1;
+ else if (len == sizeof (long))
+ val_long &= (unsigned long) - 1;
+ }
+
+ switch (format)
+ {
+ case 'x':
+#ifdef LONG_LONG
+ if (!size)
+ size = (len < sizeof (long long) ? 'w' : 'g');
+ switch (size)
+ {
+ case 'b':
+ fprintf_filtered (stream, "0x%02llx", val_long);
+ break;
+ case 'h':
+ fprintf_filtered (stream, "0x%04llx", val_long);
+ break;
+ case 0: /* no size specified, like in print */
+ case 'w':
+ fprintf_filtered (stream, "0x%08llx", val_long);
+ break;
+ case 'g':
+ fprintf_filtered (stream, "0x%016llx", val_long);
+ break;
+ default:
+ error ("Undefined output size \"%c\".", size);
+ }
+#else
+ switch (size)
+ {
+ case 'b':
+ fprintf_filtered (stream, "0x%02x", val_long);
+ break;
+ case 'h':
+ fprintf_filtered (stream, "0x%04x", val_long);
+ break;
+ case 0: /* no size specified, like in print */
+ case 'w':
+ fprintf_filtered (stream, "0x%08x", val_long);
+ break;
+ case 'g':
+ fprintf_filtered (stream, "0x%o16x", val_long);
+ break;
+ default:
+ error ("Undefined output size \"%c\".", size);
+ }
+#endif /* not LONG_LONG */
+ break;
+
+ case 'd':
+#ifdef LONG_LONG
+ fprintf_filtered (stream, "%lld", val_long);
+#else
+ fprintf_filtered (stream, "%d", val_long);
+#endif
+ break;
+
+ case 'u':
+#ifdef LONG_LONG
+ fprintf_filtered (stream, "%llu", val_long);
+#else
+ fprintf_filtered (stream, "%u", val_long);
+#endif
+ break;
+
+ case 'o':
+ if (val_long)
+#ifdef LONG_LONG
+ fprintf_filtered (stream, "0%llo", val_long);
+#else
+ fprintf_filtered (stream, "0%o", val_long);
+#endif
+ else
+ fprintf_filtered (stream, "0");
+ break;
+
+ case 'a':
+ print_address ((CORE_ADDR) val_long, stream);
+ break;
+
+ case 'A':
+ print_formatted_address ((CORE_ADDR) val_long, stream);
+ break;
+
+ case 'c':
+ value_print (value_from_long (builtin_type_char, val_long), stream, 0,
+ Val_pretty_default);
+ break;
+
+ case 'f':
+ if (len == sizeof (float))
+ type = builtin_type_float;
+ else if (len == sizeof (double))
+ type = builtin_type_double;
+ print_floating(valaddr, type, stream);
+ break;
+
+ case 0:
+ abort ();
+
+ default:
+ error ("Undefined output format \"%c\".", format);
+ }
+}
+
+/* Print a floating point value of type TYPE, pointed to in GDB by VALADDR,
+ on STREAM. */
+
+void
+print_floating(valaddr, type, stream)
+ char *valaddr;
+ struct type *type;
+ FILE *stream;
+{
+ double doub;
+ int inv;
+ int len = TYPE_LENGTH (type);
+
+ doub = unpack_double (type, valaddr, &inv);
+ if (inv)
+ fprintf_filtered (stream, "Invalid float value");
+ else if (doub != doub)
+ {
+ /* Surely it is an IEEE floating point NaN. */
+
+ long low, high, *arg = (long *)valaddr; /* ASSUMED 32 BITS */
+ int nonneg;
+
+ if (len <= sizeof(float))
+ {
+ /* It's single precision. */
+ low = *arg;
+ nonneg = low >= 0;
+ low &= 0x7fffff;
+ high = 0;
+ }
+ else
+ {
+ /* It's double precision.
+ Get the high and low words of the fraction.
+ Distinguish big and little-endian machines. */
+#ifdef WORDS_BIG_ENDIAN
+ low = arg[1], high = arg[0];
+#else
+ low = arg[0], high = arg[1];
+#endif
+ nonneg = high >= 0;
+ high &= 0xfffff;
+ }
+ if (high)
+ fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonneg, high, low);
+ else
+ fprintf_filtered (stream, "-NaN(0x%lx)" + nonneg, low);
+ }
+ else
+ fprintf_filtered (stream, len <= sizeof(float) ? "%.6g" : "%.17g", doub);
+}
+
+/* Specify default address for `x' command.
+ `info lines' uses this. */
+
+void
+set_next_address (addr)
+ CORE_ADDR addr;
+{
+ next_address = addr;
+
+ /* Make address available to the user as $_. */
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_long (builtin_type_int, (LONGEST) addr));
+}
+
+/* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM. */
+
+void
+print_address_symbolic (addr, stream)
+ CORE_ADDR addr;
+ FILE *stream;
+{
+ register char *format;
+ int name_location;
+ register int i = find_pc_misc_function (addr);
+
+ /* If nothing comes out, don't print anything symbolic. */
+ if (i < 0) return;
+ name_location = misc_function_vector[i].address;
+
+ if (addr - name_location)
+ format = " <%s+%d>";
+ else
+ format = " <%s>";
+
+ fprintf_filtered (stream, format,
+ misc_function_vector[i].name, addr - name_location);
+}
+
+/* Print address ADDR symbolically on STREAM.
+ First print it as a number. Then perhaps print
+ <SYMBOL + OFFSET> after the number. */
+
+void
+print_address (addr, stream)
+ CORE_ADDR addr;
+ FILE *stream;
+{
+ fprintf_filtered (stream, "0x%x", addr);
+ print_address_symbolic (addr, stream);
+}
+
+/* Like print_address but opnly prints symbolically. */
+
+void
+print_formatted_address (addr, stream)
+ CORE_ADDR addr;
+ FILE *stream;
+{
+ register int i = 0;
+ register char *format;
+ register struct symbol *fs;
+ char *name;
+ int name_location;
+
+ i = find_pc_partial_function (addr, &name, &name_location);
+
+ /* If nothing comes out, don't print anything symbolic. */
+
+ if (i == 0)
+ fprintf_filtered (stream, "0x%x", addr);
+ else if (addr - name_location)
+ fprintf_filtered (stream, "%s+%d", name, addr - name_location);
+ else
+ fprintf_filtered (stream, "%s", name);
+}
+
+/* Examine data at address ADDR in format FMT.
+ Fetch it from memory and print on stdout. */
+
+static void
+do_examine (fmt, addr)
+ struct format_data fmt;
+ CORE_ADDR addr;
+{
+ register char format = 0;
+ register char size;
+ register int count = 1;
+ struct type *val_type;
+ register int i;
+ register int maxelts;
+
+ format = fmt.format;
+ size = fmt.size;
+ count = fmt.count;
+ next_address = addr;
+
+ /* String or instruction format implies fetch single bytes
+ regardless of the specified size. */
+ if (format == 's' || format == 'i')
+ size = 'b';
+
+ if (size == 'b')
+ val_type = builtin_type_char;
+ else if (size == 'h')
+ val_type = builtin_type_short;
+ else if (size == 'w')
+ val_type = builtin_type_long;
+ else if (size == 'g')
+#ifndef LONG_LONG
+ val_type = builtin_type_double;
+#else
+ val_type = builtin_type_long_long;
+#endif
+
+ maxelts = 8;
+ if (size == 'w')
+ maxelts = 4;
+ if (size == 'g')
+ maxelts = 2;
+ if (format == 's' || format == 'i')
+ maxelts = 1;
+
+ /* Print as many objects as specified in COUNT, at most maxelts per line,
+ with the address of the next one at the start of each line. */
+
+ while (count > 0)
+ {
+ print_address (next_address, stdout);
+ printf_filtered (":");
+ for (i = maxelts;
+ i > 0 && count > 0;
+ i--, count--)
+ {
+ printf_filtered ("\t");
+ /* Note that print_formatted sets next_address for the next
+ object. */
+ last_examine_address = next_address;
+ last_examine_value = value_at (val_type, next_address);
+ print_formatted (last_examine_value, format, size);
+ }
+ printf_filtered ("\n");
+ fflush (stdout);
+ }
+}
+
+static void
+validate_format (fmt, cmdname)
+ struct format_data fmt;
+ char *cmdname;
+{
+ if (fmt.size != 0)
+ error ("Size letters are meaningless in \"%s\" command.", cmdname);
+ if (fmt.count != 1)
+ error ("Item count other than 1 is meaningless in \"%s\" command.",
+ cmdname);
+ if (fmt.format == 'i' || fmt.format == 's')
+ error ("Format letter \"%c\" is meaningless in \"%s\" command.",
+ fmt.format, cmdname);
+}
+
+static void
+print_command (exp)
+ char *exp;
+{
+ struct expression *expr;
+ register struct cleanup *old_chain = 0;
+ register char format = 0;
+ register value val;
+ struct format_data fmt;
+ int histindex;
+ int cleanup = 0;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, last_format, 0);
+ validate_format (fmt, "print");
+ last_format = format = fmt.format;
+ }
+
+ if (exp && *exp)
+ {
+ expr = parse_c_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ cleanup = 1;
+ val = evaluate_expression (expr);
+ }
+ else
+ val = access_value_history (0);
+
+ histindex = record_latest_value (val);
+ if (histindex >= 0) printf_filtered ("$%d = ", histindex);
+
+ print_formatted (val, format, fmt.size);
+ printf_filtered ("\n");
+
+ if (cleanup)
+ do_cleanups (old_chain);
+}
+
+static void
+output_command (exp)
+ char *exp;
+{
+ struct expression *expr;
+ register struct cleanup *old_chain;
+ register char format = 0;
+ register value val;
+ struct format_data fmt;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, 0, 0);
+ validate_format (fmt, "print");
+ format = fmt.format;
+ }
+
+ expr = parse_c_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+
+ print_formatted (val, format, fmt.size);
+
+ do_cleanups (old_chain);
+}
+
+static void
+set_command (exp)
+ char *exp;
+{
+ struct expression *expr = parse_c_expression (exp);
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+ evaluate_expression (expr);
+ do_cleanups (old_chain);
+}
+
+static void
+address_info (exp)
+ char *exp;
+{
+ register struct symbol *sym;
+ register CORE_ADDR val;
+ int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero
+ if exp is a field of `this'. */
+
+ if (exp == 0)
+ error ("Argument required.");
+
+ sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE,
+ &is_a_field_of_this);
+ if (sym == 0)
+ {
+ register int i;
+
+ if (is_a_field_of_this)
+ {
+ printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp);
+ return;
+ }
+
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, exp))
+ break;
+
+ if (i < misc_function_count)
+ printf ("Symbol \"%s\" is at 0x%x in a file compiled without -g.\n",
+ exp, misc_function_vector[i].address);
+ else
+ error ("No symbol \"%s\" in current context.", exp);
+ return;
+ }
+
+ printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym));
+ val = SYMBOL_VALUE (sym);
+
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ printf ("constant");
+ break;
+
+ case LOC_LABEL:
+ printf ("a label at address 0x%x", val);
+ break;
+
+ case LOC_REGISTER:
+ printf ("a variable in register %s", reg_names[val]);
+ break;
+
+ case LOC_STATIC:
+ printf ("static at address 0x%x", val);
+ break;
+
+ case LOC_REGPARM:
+ printf ("an argument in register %s", reg_names[val]);
+ break;
+
+ case LOC_ARG:
+ printf ("an argument at offset %d", val);
+ break;
+
+ case LOC_LOCAL:
+ printf ("a local variable at frame offset %d", val);
+ break;
+
+ case LOC_REF_ARG:
+ printf ("a reference argument at offset %d", val);
+ break;
+
+ case LOC_TYPEDEF:
+ printf ("a typedef");
+ break;
+
+ case LOC_BLOCK:
+ printf ("a function at address 0x%x",
+ BLOCK_START (SYMBOL_BLOCK_VALUE (sym)));
+ break;
+ }
+ printf (".\n");
+}
+
+static void
+x_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct expression *expr;
+ struct format_data fmt;
+ struct cleanup *old_chain;
+ struct value *val;
+
+ fmt.format = last_format;
+ fmt.size = last_size;
+ fmt.count = 1;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, last_format, last_size);
+ last_size = fmt.size;
+ last_format = fmt.format;
+ }
+
+ /* If we have an expression, evaluate it and use it as the address. */
+
+ if (exp != 0 && *exp != 0)
+ {
+ expr = parse_c_expression (exp);
+ /* Cause expression not to be there any more
+ if this command is repeated with Newline.
+ But don't clobber a user-defined command's definition. */
+ if (from_tty)
+ *exp = 0;
+ old_chain = make_cleanup (free_current_contents, &expr);
+ val = evaluate_expression (expr);
+ /* In rvalue contexts, such as this, functions are coerced into
+ pointers to functions. This makes "x/i main" work. */
+ if (/* last_format == 'i'
+ && */ TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC
+ && VALUE_LVAL (val) == lval_memory)
+ next_address = VALUE_ADDRESS (val);
+ else
+ next_address = (CORE_ADDR) value_as_long (val);
+ do_cleanups (old_chain);
+ }
+
+ do_examine (fmt, next_address);
+
+ /* Set a couple of internal variables if appropriate. */
+ if (last_examine_value)
+ {
+ /* Make last address examined available to the user as $_. */
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_long (builtin_type_int,
+ (LONGEST) last_examine_address));
+
+ /* Make contents of last address examined available to the user as $__.*/
+ set_internalvar (lookup_internalvar ("__"), last_examine_value);
+ }
+}
+
+/* Commands for printing types of things. */
+
+static void
+whatis_command (exp)
+ char *exp;
+{
+ struct expression *expr;
+ register value val;
+ register struct cleanup *old_chain;
+
+ if (exp)
+ {
+ expr = parse_c_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ val = evaluate_type (expr);
+ }
+ else
+ val = access_value_history (0);
+
+ printf_filtered ("type = ");
+ /* Most of the time users do not want to see all the fields
+ in a structure. If they do they can use the "ptype" command.
+ Hence the "-1" below. */
+ type_print (VALUE_TYPE (val), "", stdout, -1);
+ printf_filtered ("\n");
+
+ if (exp)
+ do_cleanups (old_chain);
+}
+
+static void
+ptype_command (typename)
+ char *typename;
+{
+ register char *p = typename;
+ register int len;
+ extern struct block *get_current_block ();
+ register struct block *b
+ = (have_inferior_p () || have_core_file_p ()) ? get_current_block () : 0;
+ register struct type *type;
+
+ if (typename == 0)
+ error_no_arg ("type name");
+
+ while (*p && *p != ' ' && *p != '\t') p++;
+ len = p - typename;
+ while (*p == ' ' || *p == '\t') p++;
+
+ if (len == 6 && !strncmp (typename, "struct", 6))
+ type = lookup_struct (p, b);
+ else if (len == 5 && !strncmp (typename, "union", 5))
+ type = lookup_union (p, b);
+ else if (len == 4 && !strncmp (typename, "enum", 4))
+ type = lookup_enum (p, b);
+ else
+ {
+ type = lookup_typename (typename, b, 1);
+ if (type == 0)
+ {
+ register struct symbol *sym
+ = lookup_symbol (typename, b, STRUCT_NAMESPACE, 0);
+ if (sym == 0)
+ error ("No type named %s.", typename);
+ printf_filtered ("No type named %s, but there is a ",
+ typename);
+ switch (TYPE_CODE (SYMBOL_TYPE (sym)))
+ {
+ case TYPE_CODE_STRUCT:
+ printf_filtered ("struct");
+ break;
+
+ case TYPE_CODE_UNION:
+ printf_filtered ("union");
+ break;
+
+ case TYPE_CODE_ENUM:
+ printf_filtered ("enum");
+ }
+ printf_filtered (" %s. Type \"help ptype\".\n", typename);
+ type = SYMBOL_TYPE (sym);
+ }
+ }
+
+ type_print (type, "", stdout, 1);
+ printf_filtered ("\n");
+}
+
+enum display_status {disabled, enabled};
+
+struct display
+{
+ /* Chain link to next auto-display item. */
+ struct display *next;
+ /* Expression to be evaluated and displayed. */
+ struct expression *exp;
+ /* Item number of this auto-display item. */
+ int number;
+ /* Display format specified. */
+ struct format_data format;
+ /* Innermost block required by this expression when evaluated */
+ struct block *block;
+ /* Status of this display (enabled or disabled) */
+ enum display_status status;
+};
+
+/* Chain of expressions whose values should be displayed
+ automatically each time the program stops. */
+
+static struct display *display_chain;
+
+static int display_number;
+
+/* Add an expression to the auto-display chain.
+ Specify the expression. */
+
+static void
+display_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct format_data fmt;
+ register struct expression *expr;
+ register struct display *new;
+ extern struct block *innermost_block;
+
+ if (exp == 0)
+ {
+ do_displays ();
+ return;
+ }
+
+ if (*exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, 0, 0);
+ if (fmt.size && fmt.format == 0)
+ fmt.format = 'x';
+ if (fmt.format == 'i' || fmt.format == 's')
+ fmt.size = 'b';
+ }
+ else
+ {
+ fmt.format = 0;
+ fmt.size = 0;
+ fmt.count = 0;
+ }
+
+ innermost_block = 0;
+ expr = parse_c_expression (exp);
+
+ new = (struct display *) xmalloc (sizeof (struct display));
+
+ new->exp = expr;
+ new->block = innermost_block;
+ new->next = display_chain;
+ new->number = ++display_number;
+ new->format = fmt;
+ new->status = enabled;
+ display_chain = new;
+
+ if (from_tty && have_inferior_p ())
+ do_one_display (new);
+
+ dont_repeat ();
+}
+
+static void
+free_display (d)
+ struct display *d;
+{
+ free (d->exp);
+ free (d);
+}
+
+/* Clear out the display_chain.
+ Done when new symtabs are loaded, since this invalidates
+ the types stored in many expressions. */
+
+void
+clear_displays ()
+{
+ register struct display *d;
+
+ while (d = display_chain)
+ {
+ free (d->exp);
+ display_chain = d->next;
+ free (d);
+ }
+}
+
+/* Delete the auto-display number NUM. */
+
+void
+delete_display (num)
+ int num;
+{
+ register struct display *d1, *d;
+
+ if (!display_chain)
+ error ("No display number %d.", num);
+
+ if (display_chain->number == num)
+ {
+ d1 = display_chain;
+ display_chain = d1->next;
+ free_display (d1);
+ }
+ else
+ for (d = display_chain; ; d = d->next)
+ {
+ if (d->next == 0)
+ error ("No display number %d.", num);
+ if (d->next->number == num)
+ {
+ d1 = d->next;
+ d->next = d1->next;
+ free_display (d1);
+ break;
+ }
+ }
+}
+
+/* Delete some values from the auto-display chain.
+ Specify the element numbers. */
+
+static void
+undisplay_command (args)
+ char *args;
+{
+ register char *p = args;
+ register char *p1;
+ register int num;
+ register struct display *d, *d1;
+
+ if (args == 0)
+ {
+ if (query ("Delete all auto-display expressions? "))
+ clear_displays ();
+ dont_repeat ();
+ return;
+ }
+
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9') p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ num = atoi (p);
+
+ delete_display (num);
+
+ p = p1;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+ dont_repeat ();
+}
+
+/* Display a single auto-display.
+ Do nothing if the display cannot be printed in the current context,
+ or if the display is disabled. */
+
+static void
+do_one_display (d)
+ struct display *d;
+{
+ int within_current_scope;
+
+ if (d->status == disabled)
+ return;
+
+ if (d->block)
+ within_current_scope = contained_in (get_selected_block (), d->block);
+ else
+ within_current_scope = 1;
+ if (!within_current_scope)
+ return;
+
+ current_display_number = d->number;
+
+ printf_filtered ("%d: ", d->number);
+ if (d->format.size)
+ {
+ printf_filtered ("x/");
+ if (d->format.count != 1)
+ printf_filtered ("%d", d->format.count);
+ printf_filtered ("%c", d->format.format);
+ if (d->format.format != 'i' && d->format.format != 's')
+ printf_filtered ("%c", d->format.size);
+ printf_filtered (" ");
+ print_expression (d->exp, stdout);
+ if (d->format.count != 1)
+ printf_filtered ("\n");
+ else
+ printf_filtered (" ");
+ do_examine (d->format,
+ (CORE_ADDR) value_as_long (evaluate_expression (d->exp)));
+
+ }
+ else
+ {
+ if (d->format.format)
+ printf_filtered ("/%c ", d->format.format);
+ print_expression (d->exp, stdout);
+ printf_filtered (" = ");
+ print_formatted (evaluate_expression (d->exp),
+ d->format.format, d->format.size);
+ printf_filtered ("\n");
+ }
+
+ fflush (stdout);
+ current_display_number = -1;
+}
+
+/* Display all of the values on the auto-display chain which can be
+ evaluated in the current scope. */
+
+void
+do_displays ()
+{
+ register struct display *d;
+
+ for (d = display_chain; d; d = d->next)
+ do_one_display (d);
+}
+
+/* Delete the auto-display which we were in the process of displaying.
+ This is done when there is an error or a signal. */
+
+void
+disable_display (num)
+ int num;
+{
+ register struct display *d;
+
+ for (d = display_chain; d; d = d->next)
+ if (d->number == num)
+ {
+ d->status = disabled;
+ return;
+ }
+ printf ("No display number %d.\n", num);
+}
+
+void
+disable_current_display ()
+{
+ if (current_display_number >= 0)
+ {
+ disable_display (current_display_number);
+ fprintf (stderr, "Disabling display %d to avoid infinite recursion.\n",
+ current_display_number);
+ }
+ current_display_number = -1;
+}
+
+static void
+display_info ()
+{
+ register struct display *d;
+
+ if (!display_chain)
+ printf ("There are no auto-display expressions now.\n");
+ else
+ printf_filtered ("Auto-display expressions now in effect:\n\
+Num Enb Expression\n");
+
+ for (d = display_chain; d; d = d->next)
+ {
+ printf_filtered ("%d: %c ", d->number, "ny"[(int)d->status]);
+ if (d->format.size)
+ printf_filtered ("/%d%c%c ", d->format.count, d->format.size,
+ d->format.format);
+ else if (d->format.format)
+ printf_filtered ("/%c ", d->format.format);
+ print_expression (d->exp, stdout);
+ if (d->block && !contained_in (get_selected_block (), d->block))
+ printf_filtered (" (cannot be evaluated in the current context)");
+ printf_filtered ("\n");
+ fflush (stdout);
+ }
+}
+
+void
+enable_display (args)
+ char *args;
+{
+ register char *p = args;
+ register char *p1;
+ register int num;
+ register struct display *d;
+
+ if (p == 0)
+ {
+ for (d = display_chain; d; d = d->next)
+ d->status = enabled;
+ }
+ else
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9')
+ p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ num = atoi (p);
+
+ for (d = display_chain; d; d = d->next)
+ if (d->number == num)
+ {
+ d->status = enabled;
+ goto win;
+ }
+ printf ("No display number %d.\n", num);
+ win:
+ p = p1;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ }
+}
+
+void
+disable_display_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ register char *p1;
+ register int num;
+ register struct display *d;
+
+ if (p == 0)
+ {
+ for (d = display_chain; d; d = d->next)
+ d->status = disabled;
+ }
+ else
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9')
+ p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ num = atoi (p);
+
+ disable_display (atoi (p));
+
+ p = p1;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ }
+}
+
+
+/* Print the value in stack frame FRAME of a variable
+ specified by a struct symbol. */
+
+void
+print_variable_value (var, frame, stream)
+ struct symbol *var;
+ FRAME frame;
+ FILE *stream;
+{
+ value val = read_var_value (var, frame);
+ value_print (val, stream, 0, Val_pretty_default);
+}
+
+static int
+compare_ints (i, j)
+ int *i, *j;
+{
+ return *i - *j;
+}
+
+/* Print the arguments of a stack frame, given the function FUNC
+ running in that frame (as a symbol), the info on the frame,
+ and the number of args according to the stack frame (or -1 if unknown). */
+
+static void print_frame_nameless_args ();
+
+void
+print_frame_args (func, fi, num, stream)
+ struct symbol *func;
+ struct frame_info *fi;
+ int num;
+ FILE *stream;
+{
+ struct block *b;
+ int nsyms = 0;
+ int first = 1;
+ register int i;
+ register int last_regparm = 0;
+ register struct symbol *lastsym, *sym, *nextsym;
+ register value val;
+ /* Offset of stack argument that is at the highest offset.
+ -1 if we haven't come to a stack argument yet. */
+ CORE_ADDR highest_offset = (CORE_ADDR) -1;
+ register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi);
+
+ if (func)
+ {
+ b = SYMBOL_BLOCK_VALUE (func);
+ nsyms = BLOCK_NSYMS (b);
+ }
+
+ for (i = 0; i < nsyms; i++)
+ {
+ QUIT;
+ sym = BLOCK_SYM (b, i);
+
+ if (SYMBOL_CLASS (sym) != LOC_REGPARM
+ && SYMBOL_CLASS (sym) != LOC_ARG
+ && SYMBOL_CLASS (sym) != LOC_REF_ARG)
+ continue;
+
+ /* Print the next arg. */
+ if (SYMBOL_CLASS (sym) == LOC_REGPARM)
+ val = value_from_register (SYMBOL_TYPE (sym),
+ SYMBOL_VALUE (sym),
+ FRAME_INFO_ID (fi));
+ else
+ {
+ int current_offset = SYMBOL_VALUE (sym);
+ int arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym));
+
+ if (SYMBOL_CLASS (sym) == LOC_REF_ARG)
+ val = value_at (SYMBOL_TYPE (sym),
+ read_memory_integer (addr + current_offset,
+ sizeof (CORE_ADDR)));
+ else
+ val = value_at (SYMBOL_TYPE (sym), addr + current_offset);
+
+ /* Round up address of next arg to multiple of size of int. */
+ current_offset
+ = (((current_offset + sizeof (int) - 1) / sizeof (int))
+ * sizeof (int));
+
+ /* If this is the highest offset seen yet, set highest_offset. */
+ if (highest_offset == (CORE_ADDR)-1
+ || ((current_offset
+ + (arg_size - sizeof (int) + 3) / (sizeof (int)))
+ > highest_offset))
+ highest_offset = current_offset;
+ }
+
+ if (! first)
+ fprintf_filtered (stream, ", ");
+ fputs_filtered (SYMBOL_NAME (sym), stream);
+ fputs_filtered ("=", stream);
+
+/* Nonzero if a LOC_ARG which is a struct is useless. */
+#if !defined (STRUCT_ARG_SYM_GARBAGE)
+#define STRUCT_ARG_SYM_GARBAGE(gcc_p) 0
+#endif
+
+ if (STRUCT_ARG_SYM_GARBAGE (b->gcc_compile_flag)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+ && SYMBOL_CLASS (sym) == LOC_ARG)
+ {
+ /* Try looking up that name. SunOS4 puts out a usable
+ symbol as a local variable (in addition to the one
+ for the arg). */
+ struct symbol *sym2 =
+ lookup_symbol (SYMBOL_NAME (sym), b, VAR_NAMESPACE, 0);
+
+ if (sym2 != NULL)
+ val = value_of_variable (sym2);
+ else
+ {
+ fputs_filtered ("?", stream);
+ first = 0;
+ continue;
+ }
+ }
+
+ value_print (val, stream, 0, Val_no_prettyprint);
+ first = 0;
+ }
+
+ /* Don't print nameless args in situations where we don't know
+ enough about the stack to find them. */
+ if (num != -1)
+ {
+ if (highest_offset != (CORE_ADDR) -1
+ && num * sizeof (int) + FRAME_ARGS_SKIP > highest_offset)
+ print_frame_nameless_args (fi, addr,
+ highest_offset + sizeof (int),
+ num * sizeof (int) + FRAME_ARGS_SKIP,
+ stream);
+ else
+ print_frame_nameless_args (fi, addr, FRAME_ARGS_SKIP,
+ num * sizeof (int) + FRAME_ARGS_SKIP,
+ stream);
+ }
+}
+
+static void
+print_frame_nameless_args (fi, argsaddr, start, end, stream)
+ struct frame_info *fi;
+ CORE_ADDR argsaddr;
+ int start;
+ int end;
+ FILE *stream;
+{
+ extern void (*default_scalar_print)();
+ LONGEST v;
+ int p = start;
+ char *s = "";
+
+ for (p = start; p < end; p += sizeof(int)) {
+ QUIT;
+#if defined(NAMELESS_ARG)
+ v = NAMELESS_ARG(fi, (p - start) / sizeof(int));
+#else
+ v = read_memory_integer (argsaddr + p, sizeof (int));
+#endif
+ fprintf_filtered (stream, s);
+ s = ", ";
+ (*default_scalar_print) (stream, builtin_type_int, v);
+ }
+}
+
+static void
+printf_command (arg)
+ char *arg;
+{
+ register char *f;
+ register char *s = arg;
+ char *string;
+ value *val_args;
+ int nargs = 0;
+ int allocated_args = 20;
+ char *arg_bytes;
+
+ val_args = (value *) xmalloc (allocated_args * sizeof (value));
+
+ if (s == 0)
+ error_no_arg ("format-control string and values to print");
+
+ /* Skip white space before format string */
+ while (*s == ' ' || *s == '\t') s++;
+
+ /* A format string should follow, enveloped in double quotes */
+ if (*s++ != '"')
+ error ("Bad format string, missing '\"'.");
+
+ /* Parse the format-control string and copy it into the string STRING,
+ processing some kinds of escape sequence. */
+
+ f = string = (char *) alloca (strlen (s) + 1);
+ while (*s != '"')
+ {
+ int c = *s++;
+ switch (c)
+ {
+ case '\0':
+ error ("Bad format string, non-terminated '\"'.");
+ /* doesn't return */
+
+ case '\\':
+ switch (c = *s++)
+ {
+ case '\\':
+ *f++ = '\\';
+ break;
+ case 'n':
+ *f++ = '\n';
+ break;
+ case 't':
+ *f++ = '\t';
+ break;
+ case 'r':
+ *f++ = '\r';
+ break;
+ case '"':
+ *f++ = '"';
+ break;
+ default:
+ /* ??? TODO: handle other escape sequences */
+ error ("Unrecognized \\ escape character in format string.");
+ }
+ break;
+
+ default:
+ *f++ = c;
+ }
+ }
+
+ /* Skip over " and following space and comma. */
+ s++;
+ *f++ = '\0';
+ while (*s == ' ' || *s == '\t') s++;
+
+ if (*s != ',' && *s != 0)
+ error ("Invalid argument syntax");
+
+ if (*s == ',') s++;
+ while (*s == ' ' || *s == '\t') s++;
+
+ {
+ /* Now scan the string for %-specs and see what kinds of args they want.
+ argclass[I] classifies the %-specs so we can give vprintf something
+ of the right size. */
+
+ enum argclass {int_arg, string_arg, double_arg, long_long_arg};
+ enum argclass *argclass;
+ int nargs_wanted;
+ int argindex;
+ int lcount;
+ int i;
+
+ argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass);
+ nargs_wanted = 0;
+ f = string;
+ while (*f)
+ if (*f++ == '%')
+ {
+ lcount = 0;
+ while (index ("0123456789.hlL-+ #", *f))
+ {
+ if (*f == 'l' || *f == 'L')
+ lcount++;
+ f++;
+ }
+ if (*f == 's')
+ argclass[nargs_wanted++] = string_arg;
+ else if (*f == 'e' || *f == 'f' || *f == 'g')
+ argclass[nargs_wanted++] = double_arg;
+ else if (lcount > 1)
+ argclass[nargs_wanted++] = long_long_arg;
+ else if (*f != '%')
+ argclass[nargs_wanted++] = int_arg;
+ f++;
+ }
+
+ /* Now, parse all arguments and evaluate them.
+ Store the VALUEs in VAL_ARGS. */
+
+ while (*s != '\0')
+ {
+ char *s1;
+ if (nargs == allocated_args)
+ val_args = (value *) xrealloc (val_args,
+ (allocated_args *= 2)
+ * sizeof (value));
+ s1 = s;
+ val_args[nargs] = parse_to_comma_and_eval (&s1);
+
+ /* If format string wants a float, unchecked-convert the value to
+ floating point of the same size */
+
+ if (argclass[nargs] == double_arg)
+ {
+ if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float))
+ VALUE_TYPE (val_args[nargs]) = builtin_type_float;
+ if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double))
+ VALUE_TYPE (val_args[nargs]) = builtin_type_double;
+ }
+ nargs++;
+ s = s1;
+ if (*s == ',')
+ s++;
+ }
+
+ if (nargs != nargs_wanted)
+ error ("Wrong number of arguments for specified format-string");
+
+ /* Now lay out an argument-list containing the arguments
+ as doubles, integers and C pointers. */
+
+ arg_bytes = (char *) alloca (sizeof (double) * nargs);
+ argindex = 0;
+ for (i = 0; i < nargs; i++)
+ {
+ if (argclass[i] == string_arg)
+ {
+ char *str;
+ int tem, j;
+ tem = value_as_long (val_args[i]);
+
+ /* This is a %s argument. Find the length of the string. */
+ for (j = 0; ; j++)
+ {
+ char c;
+ QUIT;
+ read_memory (tem + j, &c, 1);
+ if (c == 0)
+ break;
+ }
+
+ /* Copy the string contents into a string inside GDB. */
+ str = (char *) alloca (j + 1);
+ read_memory (tem, str, j);
+ str[j] = 0;
+
+ /* Pass address of internal copy as the arg to vprintf. */
+ *((int *) &arg_bytes[argindex]) = (int) str;
+ argindex += sizeof (int);
+ }
+ else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT)
+ {
+ *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]);
+ argindex += sizeof (double);
+ }
+ else
+#ifdef LONG_LONG
+ if (argclass[i] == long_long_arg)
+ {
+ *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]);
+ argindex += sizeof (long long);
+ }
+ else
+#endif
+ {
+ *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]);
+ argindex += sizeof (int);
+ }
+ }
+ }
+ vprintf (string, arg_bytes);
+}
+
+/* Helper function for asdump_command. Finds the bounds of a function
+ for a specified section of text. PC is an address within the
+ function which you want bounds for; *LOW and *HIGH are set to the
+ beginning (inclusive) and end (exclusive) of the function. This
+ function returns 1 on success and 0 on failure. */
+
+static int
+containing_function_bounds (pc, low, high)
+ CORE_ADDR pc, *low, *high;
+{
+ int scan;
+
+ if (!find_pc_partial_function (pc, 0, low))
+ return 0;
+
+ scan = *low;
+ do {
+ scan++;
+ if (!find_pc_partial_function (scan, 0, high))
+ return 0;
+ } while (*low == *high);
+
+ return 1;
+}
+
+/* Dump a specified section of assembly code. With no command line
+ arguments, this command will dump the assembly code for the
+ function surrounding the pc value in the selected frame. With one
+ argument, it will dump the assembly code surrounding that pc value.
+ Two arguments are interpeted as bounds within which to dump
+ assembly. */
+
+static void
+disassemble_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR low, high;
+ CORE_ADDR pc;
+ char *space_index;
+
+ if (!arg)
+ {
+ if (!selected_frame)
+ error ("No frame selected.\n");
+
+ pc = get_frame_pc (selected_frame);
+ if (!containing_function_bounds (pc, &low, &high))
+ error ("No function contains pc specified by selected frame.\n");
+ }
+ else if (!(space_index = (char *) index (arg, ' ')))
+ {
+ /* One argument. */
+ pc = parse_and_eval_address (arg);
+ if (!containing_function_bounds (pc, &low, &high))
+ error ("No function contains specified pc.\n");
+ }
+ else
+ {
+ /* Two arguments. */
+ *space_index = '\0';
+ low = parse_and_eval_address (arg);
+ high = parse_and_eval_address (space_index + 1);
+ }
+
+ printf_filtered ("Dump of assembler code ");
+ if (!space_index)
+ {
+ char *name;
+ find_pc_partial_function (pc, &name, 0);
+ printf_filtered ("for function %s:\n", name);
+ }
+ else
+ printf_filtered ("from 0x%x to 0x%x:\n", low, high);
+
+ /* Dump the specified range. */
+ for (pc = low; pc < high; )
+ {
+ QUIT;
+ print_address (pc, stdout);
+ printf_filtered (":\t");
+ pc += print_insn (pc, stdout);
+ printf_filtered ("\n");
+ }
+ printf_filtered ("End of assembler dump.\n");
+ fflush (stdout);
+}
+
+
+extern struct cmd_list_element *enablelist, *disablelist, *deletelist;
+extern struct cmd_list_element *cmdlist, *setlist;
+
+void
+_initialize_printcmd ()
+{
+ current_display_number = -1;
+
+ add_info ("address", address_info,
+ "Describe where variable VAR is stored.");
+
+ add_com ("x", class_vars, x_command,
+ "Examine memory: x/FMT ADDRESS.\n\
+ADDRESS is an expression for the memory address to examine.\n\
+FMT is a repeat count followed by a format letter and a size letter.\n\
+Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\
+ f(float), a(address), i(instruction), c(char) and s(string).\n\
+Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\
+ g is meaningful only with f, for type double.\n\
+The specified number of objects of the specified size are printed\n\
+according to the format.\n\n\
+Defaults for format and size letters are those previously used.\n\
+Default count is 1. Default address is following last thing printed\n\
+with this command or \"print\".");
+
+ add_com ("disassemble", class_vars, disassemble_command,
+ "Disassemble a specified section of memory.\n\
+Default is the function surrounding the pc of the selected frame.\n\
+With a single argument, the function surrounding that address is dumped.\n\
+Two arguments are taken as a range of memory to dump.");
+
+ add_com ("ptype", class_vars, ptype_command,
+ "Print definition of type TYPE.\n\
+Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\
+or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\
+The selected stack frame's lexical context is used to look up the name.");
+
+ add_com ("whatis", class_vars, whatis_command,
+ "Print data type of expression EXP.");
+
+ add_info ("display", display_info,
+ "Expressions to display when program stops, with code numbers.");
+
+ add_cmd ("undisplay", class_vars, undisplay_command,
+ "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+\"delete display\" has the same effect as this command.\n\
+Do \"info display\" to see current list of code numbers.",
+ &cmdlist);
+
+ add_com ("display", class_vars, display_command,
+ "Print value of expression EXP each time the program stops.\n\
+/FMT may be used before EXP as in the \"print\" command.\n\
+/FMT \"i\" or \"s\" or including a size-letter is allowed,\n\
+as in the \"x\" command, and then EXP is used to get the address to examine\n\
+and examining is done as in the \"x\" command.\n\n\
+With no argument, display all currently requested auto-display expressions.\n\
+Use \"undisplay\" to cancel display requests previously made.");
+
+ add_cmd ("display", class_vars, enable_display,
+ "Enable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to resume displaying.\n\
+No argument means enable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &enablelist);
+
+ add_cmd ("display", class_vars, disable_display_command,
+ "Disable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means disable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &disablelist);
+
+ add_cmd ("display", class_vars, undisplay_command,
+ "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &deletelist);
+
+ add_com ("printf", class_vars, printf_command,
+ "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
+This is useful for formatted output in user-defined commands.");
+ add_com ("output", class_vars, output_command,
+ "Like \"print\" but don't put in value history and don't print newline.\n\
+This is useful in user-defined commands.");
+
+ add_prefix_cmd ("set", class_vars, set_command,
+"Perform an assignment VAR = EXP.\n\
+You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\
+(names starting with $), a register (a few standard names starting with $),\n\
+or an actual variable in the program being debugged. EXP is any expression.\n\
+Use \"set variable\" for variables with names identical to set subcommands.\n\
+\nWith a subcommand, this command modifies parts of the gdb environment",
+ &setlist, "set ", 1, &cmdlist);
+
+ add_cmd ("variable", class_vars, set_command,
+ "Perform an assignment VAR = EXP.\n\
+You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\
+(names starting with $), a register (a few standard names starting with $),\n\
+or an actual variable in the program being debugged. EXP is any expression.\n\
+This may usually be abbreviated to simply \"set\".",
+ &setlist);
+
+ add_com ("print", class_vars, print_command,
+ concat ("Print value of expression EXP.\n\
+Variables accessible are those of the lexical environment of the selected\n\
+stack frame, plus all those whose scope is global or an entire file.\n\
+\n\
+$NUM gets previous value number NUM. $ and $$ are the last two values.\n\
+$$NUM refers to NUM'th value back from the last one.\n\
+Names starting with $ refer to registers (with the values they would have\n\
+if the program were to return to the stack frame now selected, restoring\n\
+all registers saved by frames farther in) or else to debugger\n\
+\"convenience\" variables (any such name not a known register).\n\
+Use assignment expressions to give values to convenience variables.\n",
+ "\n\
+\{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\
+@ is a binary operator for treating consecutive data objects\n\
+anywhere in memory as an array. FOO@NUM gives an array whose first\n\
+element is FOO, whose second element is stored in the space following\n\
+where FOO is stored, etc. FOO must be an expression whose value\n\
+resides in memory.\n",
+ "\n\
+EXP may be preceded with /FMT, where FMT is a format letter\n\
+but no count or size letter (see \"x\" command)."));
+ add_com_alias ("p", "print", class_vars, 1);
+}
diff --git a/gnu/usr.bin/kgdb/regex.c b/gnu/usr.bin/kgdb/regex.c
new file mode 100644
index 000000000000..45c34780f6c2
--- /dev/null
+++ b/gnu/usr.bin/kgdb/regex.c
@@ -0,0 +1,1738 @@
+/* Extended regular expression matching and search library.
+ Copyright (C) 1985, 1989 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+
+/* To test, compile with -Dtest.
+ This Dtestable feature turns this into a self-contained program
+ which reads a pattern, describes how it compiles,
+ then reads a string and searches for it. */
+
+#ifdef emacs
+
+/* The `emacs' switch turns on certain special matching commands
+ that make sense only in emacs. */
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+#else /* not emacs */
+
+#ifdef USG
+#ifndef BSTRING
+#define bcopy(s,d,n) memcpy((d),(s),(n))
+#define bcmp(s1,s2,n) memcmp((s1),(s2),(n))
+#define bzero(s,n) memset((s),0,(n))
+#endif
+#endif
+
+/* Make alloca work the best possible way. */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef sparc
+#include <alloca.h>
+#endif
+#endif
+
+/*
+ * Define the syntax stuff, so we can do the \<...\> things.
+ */
+
+#ifndef Sword /* must be non-zero in some of the tests below... */
+#define Sword 1
+#endif
+
+#define SYNTAX(c) re_syntax_table[c]
+
+#ifdef SYNTAX_TABLE
+
+char *re_syntax_table;
+
+#else
+
+static char re_syntax_table[256];
+
+static void
+init_syntax_once ()
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+
+ bzero (re_syntax_table, sizeof re_syntax_table);
+
+ for (c = 'a'; c <= 'z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = 'A'; c <= 'Z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = '0'; c <= '9'; c++)
+ re_syntax_table[c] = Sword;
+
+ done = 1;
+}
+
+#endif /* SYNTAX_TABLE */
+#endif /* not emacs */
+
+#include "regex.h"
+
+/* Number of failure points to allocate space for initially,
+ when matching. If this number is exceeded, more space is allocated,
+ so it is not a hard limit. */
+
+#ifndef NFAILURES
+#define NFAILURES 80
+#endif /* NFAILURES */
+
+/* width of a byte in bits */
+
+#define BYTEWIDTH 8
+
+#ifndef SIGN_EXTEND_CHAR
+#define SIGN_EXTEND_CHAR(x) (x)
+#endif
+
+static int obscure_syntax = 0;
+
+/* Specify the precise syntax of regexp for compilation.
+ This provides for compatibility for various utilities
+ which historically have different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit-mask containing the two bits
+ RE_NO_BK_PARENS and RE_NO_BK_VBAR. */
+
+int
+re_set_syntax (syntax)
+{
+ int ret;
+
+ ret = obscure_syntax;
+ obscure_syntax = syntax;
+ return ret;
+}
+
+/* re_compile_pattern takes a regular-expression string
+ and converts it into a buffer full of byte commands for matching.
+
+ PATTERN is the address of the pattern string
+ SIZE is the length of it.
+ BUFP is a struct re_pattern_buffer * which points to the info
+ on where to store the byte commands.
+ This structure contains a char * which points to the
+ actual space, which should have been obtained with malloc.
+ re_compile_pattern may use realloc to grow the buffer space.
+
+ The number of bytes of commands can be found out by looking in
+ the struct re_pattern_buffer that bufp pointed to,
+ after re_compile_pattern returns.
+*/
+
+#define PATPUSH(ch) (*b++ = (char) (ch))
+
+#define PATFETCH(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; \
+ if (translate) c = translate[c]; }
+
+#define PATFETCH_RAW(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; }
+
+#define PATUNFETCH p--
+
+#define EXTEND_BUFFER \
+ { char *old_buffer = bufp->buffer; \
+ if (bufp->allocated == (1<<16)) goto too_big; \
+ bufp->allocated *= 2; \
+ if (bufp->allocated > (1<<16)) bufp->allocated = (1<<16); \
+ if (!(bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated))) \
+ goto memory_exhausted; \
+ c = bufp->buffer - old_buffer; \
+ b += c; \
+ if (fixup_jump) \
+ fixup_jump += c; \
+ if (laststart) \
+ laststart += c; \
+ begalt += c; \
+ if (pending_exact) \
+ pending_exact += c; \
+ }
+
+static int store_jump (), insert_jump ();
+
+char *
+re_compile_pattern (pattern, size, bufp)
+ char *pattern;
+ int size;
+ struct re_pattern_buffer *bufp;
+{
+ register char *b = bufp->buffer;
+ register char *p = pattern;
+ char *pend = pattern + size;
+ register unsigned c, c1;
+ char *p1;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ /* address of the count-byte of the most recently inserted "exactn" command.
+ This makes it possible to tell whether a new exact-match character
+ can be added to that command or requires a new "exactn" command. */
+
+ char *pending_exact = 0;
+
+ /* address of the place where a forward-jump should go
+ to the end of the containing expression.
+ Each alternative of an "or", except the last, ends with a forward-jump
+ of this sort. */
+
+ char *fixup_jump = 0;
+
+ /* address of start of the most recently finished expression.
+ This tells postfix * where to find the start of its operand. */
+
+ char *laststart = 0;
+
+ /* In processing a repeat, 1 means zero matches is allowed */
+
+ char zero_times_ok;
+
+ /* In processing a repeat, 1 means many matches is allowed */
+
+ char many_times_ok;
+
+ /* address of beginning of regexp, or inside of last \( */
+
+ char *begalt = b;
+
+ /* Stack of information saved by \( and restored by \).
+ Four stack elements are pushed by each \(:
+ First, the value of b.
+ Second, the value of fixup_jump.
+ Third, the value of regnum.
+ Fourth, the value of begalt. */
+
+ int stackb[40];
+ int *stackp = stackb;
+ int *stacke = stackb + 40;
+ int *stackt;
+
+ /* Counts \('s as they are encountered. Remembered for the matching \),
+ where it becomes the "register number" to put in the stop_memory command */
+
+ int regnum = 1;
+
+ bufp->fastmap_accurate = 0;
+
+#ifndef emacs
+#ifndef SYNTAX_TABLE
+ /*
+ * Initialize the syntax table.
+ */
+ init_syntax_once();
+#endif
+#endif
+
+ if (bufp->allocated == 0)
+ {
+ bufp->allocated = 28;
+ if (bufp->buffer)
+ /* EXTEND_BUFFER loses when bufp->allocated is 0 */
+ bufp->buffer = (char *) realloc (bufp->buffer, 28);
+ else
+ /* Caller did not allocate a buffer. Do it for him */
+ bufp->buffer = (char *) malloc (28);
+ if (!bufp->buffer) goto memory_exhausted;
+ begalt = b = bufp->buffer;
+ }
+
+ while (p != pend)
+ {
+ if (b - bufp->buffer > bufp->allocated - 10)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ PATFETCH (c);
+
+ switch (c)
+ {
+ case '$':
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend)
+ goto normal_char;
+ /* Make operand of last vbar end before this `$'. */
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = 0;
+ PATPUSH (endline);
+ break;
+ }
+
+ /* $ means succeed if at end of line, but only in special contexts.
+ If randomly in the middle of a pattern, it is a normal character. */
+ if (p == pend || *p == '\n'
+ || (obscure_syntax & RE_CONTEXT_INDEP_OPS)
+ || (obscure_syntax & RE_NO_BK_PARENS
+ ? *p == ')'
+ : *p == '\\' && p[1] == ')')
+ || (obscure_syntax & RE_NO_BK_VBAR
+ ? *p == '|'
+ : *p == '\\' && p[1] == '|'))
+ {
+ PATPUSH (endline);
+ break;
+ }
+ goto normal_char;
+
+ case '^':
+ /* ^ means succeed if at beg of line, but only if no preceding pattern. */
+
+ if (laststart && p[-2] != '\n'
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (p != pattern + 1
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ PATPUSH (begline);
+ begalt = b;
+ }
+ else
+ PATPUSH (begline);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern, char not special. */
+ if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ /* If there is a sequence of repetition chars,
+ collapse it down to equivalent to just one. */
+ zero_times_ok = 0;
+ many_times_ok = 0;
+ while (1)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+ if (p == pend)
+ break;
+ PATFETCH (c);
+ if (c == '*')
+ ;
+ else if (!(obscure_syntax & RE_BK_PLUS_QM)
+ && (c == '+' || c == '?'))
+ ;
+ else if ((obscure_syntax & RE_BK_PLUS_QM)
+ && c == '\\')
+ {
+ int c1;
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether 0 matches is allowed,
+ and whether 2 or more matches is allowed. */
+ if (many_times_ok)
+ {
+ /* If more than one repetition is allowed,
+ put in a backward jump at the end. */
+ store_jump (b, maybe_finalize_jump, laststart - 3);
+ b += 3;
+ }
+ insert_jump (on_failure_jump, laststart, b + 3, b);
+ pending_exact = 0;
+ b += 3;
+ if (!zero_times_ok)
+ {
+ /* At least one repetition required: insert before the loop
+ a skip over the initial on-failure-jump instruction */
+ insert_jump (dummy_failure_jump, laststart, laststart + 6, b);
+ b += 3;
+ }
+ break;
+
+ case '.':
+ laststart = b;
+ PATPUSH (anychar);
+ break;
+
+ case '[':
+ while (b - bufp->buffer
+ > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ laststart = b;
+ if (*p == '^')
+ PATPUSH (charset_not), p++;
+ else
+ PATPUSH (charset);
+ p1 = p;
+
+ PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Clear the whole map */
+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Read in characters and ranges, setting map bits */
+ while (1)
+ {
+ PATFETCH (c);
+ if (c == ']' && p != p1 + 1) break;
+ if (*p == '-' && p[1] != ']')
+ {
+ PATFETCH (c1);
+ PATFETCH (c1);
+ while (c <= c1)
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++;
+ }
+ else
+ {
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH);
+ }
+ }
+ /* Discard any bitmap bytes that are all 0 at the end of the map.
+ Decrement the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+ break;
+
+ case '(':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_open;
+
+ case ')':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_close;
+
+ case '\n':
+ if (! (obscure_syntax & RE_NEWLINE_OR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '|':
+ if (! (obscure_syntax & RE_NO_BK_VBAR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '\\':
+ if (p == pend) goto invalid_pattern;
+ PATFETCH_RAW (c);
+ switch (c)
+ {
+ case '(':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_open:
+ if (stackp == stacke) goto nesting_too_deep;
+ if (regnum < RE_NREGS)
+ {
+ PATPUSH (start_memory);
+ PATPUSH (regnum);
+ }
+ *stackp++ = b - bufp->buffer;
+ *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0;
+ *stackp++ = regnum++;
+ *stackp++ = begalt - bufp->buffer;
+ fixup_jump = 0;
+ laststart = 0;
+ begalt = b;
+ break;
+
+ case ')':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_close:
+ if (stackp == stackb) goto unmatched_close;
+ begalt = *--stackp + bufp->buffer;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ if (stackp[-1] < RE_NREGS)
+ {
+ PATPUSH (stop_memory);
+ PATPUSH (stackp[-1]);
+ }
+ stackp -= 2;
+ fixup_jump = 0;
+ if (*stackp)
+ fixup_jump = *stackp + bufp->buffer - 1;
+ laststart = *--stackp + bufp->buffer;
+ break;
+
+ case '|':
+ if (obscure_syntax & RE_NO_BK_VBAR)
+ goto normal_backsl;
+ handle_bar:
+ insert_jump (on_failure_jump, begalt, b + 6, b);
+ pending_exact = 0;
+ b += 3;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = b;
+ b += 3;
+ laststart = 0;
+ begalt = b;
+ break;
+
+#ifdef emacs
+ case '=':
+ PATPUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATPUSH (syntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATPUSH (notsyntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+#endif /* emacs */
+
+ case 'w':
+ laststart = b;
+ PATPUSH (wordchar);
+ break;
+
+ case 'W':
+ laststart = b;
+ PATPUSH (notwordchar);
+ break;
+
+ case '<':
+ PATPUSH (wordbeg);
+ break;
+
+ case '>':
+ PATPUSH (wordend);
+ break;
+
+ case 'b':
+ PATPUSH (wordbound);
+ break;
+
+ case 'B':
+ PATPUSH (notwordbound);
+ break;
+
+ case '`':
+ PATPUSH (begbuf);
+ break;
+
+ case '\'':
+ PATPUSH (endbuf);
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c - '0';
+ if (c1 >= regnum)
+ goto normal_char;
+ for (stackt = stackp - 2; stackt > stackb; stackt -= 4)
+ if (*stackt == c1)
+ goto normal_char;
+ laststart = b;
+ PATPUSH (duplicate);
+ PATPUSH (c1);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+
+ default:
+ normal_backsl:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ if (translate) c = translate[c];
+ goto normal_char;
+ }
+ break;
+
+ default:
+ normal_char:
+ if (!pending_exact || pending_exact + *pending_exact + 1 != b
+ || *pending_exact == 0177 || *p == '*' || *p == '^'
+ || ((obscure_syntax & RE_BK_PLUS_QM)
+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+ : (*p == '+' || *p == '?')))
+ {
+ laststart = b;
+ PATPUSH (exactn);
+ pending_exact = b;
+ PATPUSH (0);
+ }
+ PATPUSH (c);
+ (*pending_exact)++;
+ }
+ }
+
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+
+ if (stackp != stackb) goto unmatched_open;
+
+ bufp->used = b - bufp->buffer;
+ return 0;
+
+ invalid_pattern:
+ return "Invalid regular expression";
+
+ unmatched_open:
+ return "Unmatched \\(";
+
+ unmatched_close:
+ return "Unmatched \\)";
+
+ end_of_pattern:
+ return "Premature end of regular expression";
+
+ nesting_too_deep:
+ return "Nesting too deep";
+
+ too_big:
+ return "Regular expression too big";
+
+ memory_exhausted:
+ return "Memory exhausted";
+}
+
+/* Store where `from' points a jump operation to jump to where `to' points.
+ `opcode' is the opcode to store. */
+
+static int
+store_jump (from, opcode, to)
+ char *from, *to;
+ char opcode;
+{
+ from[0] = opcode;
+ from[1] = (to - (from + 3)) & 0377;
+ from[2] = (to - (from + 3)) >> 8;
+}
+
+/* Open up space at char FROM, and insert there a jump to TO.
+ CURRENT_END gives te end of the storage no in use,
+ so we know how much data to copy up.
+ OP is the opcode of the jump to insert.
+
+ If you call this function, you must zero out pending_exact. */
+
+static int
+insert_jump (op, from, to, current_end)
+ char op;
+ char *from, *to, *current_end;
+{
+ register char *pto = current_end + 3;
+ register char *pfrom = current_end;
+ while (pfrom != from)
+ *--pto = *--pfrom;
+ store_jump (from, op, to);
+}
+
+/* Given a pattern, compute a fastmap from it.
+ The fastmap records which of the (1 << BYTEWIDTH) possible characters
+ can start a string that matches the pattern.
+ This fastmap is used by re_search to skip quickly over totally implausible text.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data area
+ as bufp->fastmap.
+ The other components of bufp describe the pattern to be used. */
+
+void
+re_compile_fastmap (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *pattern = (unsigned char *) bufp->buffer;
+ int size = bufp->used;
+ register char *fastmap = bufp->fastmap;
+ register unsigned char *p = pattern;
+ register unsigned char *pend = pattern + size;
+ register int j, k;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ unsigned char *stackb[NFAILURES];
+ unsigned char **stackp = stackb;
+
+ bzero (fastmap, (1 << BYTEWIDTH));
+ bufp->fastmap_accurate = 1;
+ bufp->can_be_null = 0;
+
+ while (p)
+ {
+ if (p == pend)
+ {
+ bufp->can_be_null = 1;
+ break;
+ }
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+ case exactn:
+ if (translate)
+ fastmap[translate[p[1]]] = 1;
+ else
+ fastmap[p[1]] = 1;
+ break;
+
+ case begline:
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ continue;
+
+ case endline:
+ if (translate)
+ fastmap[translate['\n']] = 1;
+ else
+ fastmap['\n'] = 1;
+ if (bufp->can_be_null != 1)
+ bufp->can_be_null = 2;
+ break;
+
+ case finalize_jump:
+ case maybe_finalize_jump:
+ case jump:
+ case dummy_failure_jump:
+ bufp->can_be_null = 1;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (j > 0)
+ continue;
+ /* Jump backward reached implies we just went through
+ the body of a loop and matched nothing.
+ Opcode jumped to should be an on_failure_jump.
+ Just treat it like an ordinary jump.
+ For a * loop, it has pushed its failure point already;
+ if so, discard that as redundant. */
+ if ((enum regexpcode) *p != on_failure_jump)
+ continue;
+ p++;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (stackp != stackb && *stackp == p)
+ stackp--;
+ continue;
+
+ case on_failure_jump:
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *++stackp = p + j;
+ continue;
+
+ case start_memory:
+ case stop_memory:
+ p++;
+ continue;
+
+ case duplicate:
+ bufp->can_be_null = 1;
+ fastmap['\n'] = 1;
+ case anychar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (j != '\n')
+ fastmap[j] = 1;
+ if (bufp->can_be_null)
+ return;
+ /* Don't return; check the alternative paths
+ so we can set can_be_null if appropriate. */
+ break;
+
+ case wordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == Sword)
+ fastmap[j] = 1;
+ break;
+
+ case notwordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != Sword)
+ fastmap[j] = 1;
+ break;
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+#endif /* emacs */
+
+ case charset:
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+
+ case charset_not:
+ /* Chars beyond end of map must be allowed */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+ }
+
+ /* Get here means we have successfully found the possible starting characters
+ of one path of the pattern. We need not follow this path any farther.
+ Instead, look at the next alternative remembered in the stack. */
+ if (stackp != stackb)
+ p = *stackp--;
+ else
+ break;
+ }
+}
+
+/* Like re_search_2, below, but only one string is specified. */
+
+int
+re_search (pbufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, startpos, range;
+ struct re_registers *regs;
+{
+ return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size);
+}
+
+/* Like re_match_2 but tries first a match starting at index STARTPOS,
+ then at STARTPOS + 1, and so on.
+ RANGE is the number of places to try before giving up.
+ If RANGE is negative, the starting positions tried are
+ STARTPOS, STARTPOS - 1, etc.
+ It is up to the caller to make sure that range is not so large
+ as to take the starting position outside of the input strings.
+
+The value returned is the position at which the match was found,
+ or -1 if no match was found,
+ or -2 if error (such as failure stack overflow). */
+
+int
+re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ char *string1, *string2;
+ int size1, size2;
+ int startpos;
+ register int range;
+ struct re_registers *regs;
+ int mstop;
+{
+ register char *fastmap = pbufp->fastmap;
+ register unsigned char *translate = (unsigned char *) pbufp->translate;
+ int total = size1 + size2;
+ int val;
+
+ /* Update the fastmap now if not correct already */
+ if (fastmap && !pbufp->fastmap_accurate)
+ re_compile_fastmap (pbufp);
+
+ /* Don't waste time in a long search for a pattern
+ that says it is anchored. */
+ if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf
+ && range > 0)
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+ while (1)
+ {
+ /* If a fastmap is supplied, skip quickly over characters
+ that cannot possibly be the start of a match.
+ Note, however, that if the pattern can possibly match
+ the null string, we must test it at each starting point
+ so that we take the first null string we get. */
+
+ if (fastmap && startpos < total && pbufp->can_be_null != 1)
+ {
+ if (range > 0)
+ {
+ register int lim = 0;
+ register unsigned char *p;
+ int irange = range;
+ if (startpos < size1 && startpos + range >= size1)
+ lim = range - (size1 - startpos);
+
+ p = ((unsigned char *)
+ &(startpos >= size1 ? string2 - size1 : string1)[startpos]);
+
+ if (translate)
+ {
+ while (range > lim && !fastmap[translate[*p++]])
+ range--;
+ }
+ else
+ {
+ while (range > lim && !fastmap[*p++])
+ range--;
+ }
+ startpos += irange - range;
+ }
+ else
+ {
+ register unsigned char c;
+ if (startpos >= size1)
+ c = string2[startpos - size1];
+ else
+ c = string1[startpos];
+ c &= 0xff;
+ if (translate ? !fastmap[translate[c]] : !fastmap[c])
+ goto advance;
+ }
+ }
+
+ if (range >= 0 && startpos == total
+ && fastmap && pbufp->can_be_null == 0)
+ return -1;
+
+ val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, regs, mstop);
+ if (0 <= val)
+ {
+ if (val == -2)
+ return -2;
+ return startpos;
+ }
+
+#ifdef C_ALLOCA
+ alloca (0);
+#endif /* C_ALLOCA */
+
+ advance:
+ if (!range) break;
+ if (range > 0) range--, startpos++; else range++, startpos--;
+ }
+ return -1;
+}
+
+#ifndef emacs /* emacs never uses this */
+int
+re_match (pbufp, string, size, pos, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, pos;
+ struct re_registers *regs;
+{
+ return re_match_2 (pbufp, 0, 0, string, size, pos, regs, size);
+}
+#endif /* emacs */
+
+/* Maximum size of failure stack. Beyond this, overflow is an error. */
+
+int re_max_failures = 2000;
+
+static int bcmp_translate();
+/* Match the pattern described by PBUFP
+ against data which is the virtual concatenation of STRING1 and STRING2.
+ SIZE1 and SIZE2 are the sizes of the two data strings.
+ Start the match at position POS.
+ Do not consider matching past the position MSTOP.
+
+ If pbufp->fastmap is nonzero, then it had better be up to date.
+
+ The reason that the data to match are specified as two components
+ which are to be regarded as concatenated
+ is so this function can be used directly on the contents of an Emacs buffer.
+
+ -1 is returned if there is no match. -2 is returned if there is
+ an error (such as match stack overflow). Otherwise the value is the length
+ of the substring which was matched. */
+
+int
+re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ unsigned char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int mstop;
+{
+ register unsigned char *p = (unsigned char *) pbufp->buffer;
+ register unsigned char *pend = p + pbufp->used;
+ /* End of first string */
+ unsigned char *end1;
+ /* End of second string */
+ unsigned char *end2;
+ /* Pointer just past last char to consider matching */
+ unsigned char *end_match_1, *end_match_2;
+ register unsigned char *d, *dend;
+ register int mcnt;
+ unsigned char *translate = (unsigned char *) pbufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further down the line
+ pushes a failure point on this stack. It consists of two char *'s.
+ The first one pushed is where to resume scanning the pattern;
+ the second pushed is where to resume scanning the strings.
+ If the latter is zero, the failure point is a "dummy".
+ If a failure happens and the innermost failure point is dormant,
+ it discards that failure point and tries the next one. */
+
+ unsigned char *initial_stack[2 * NFAILURES];
+ unsigned char **stackb = initial_stack;
+ unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES];
+
+ /* Information on the "contents" of registers.
+ These are pointers into the input strings; they record
+ just what was matched (on this attempt) by some part of the pattern.
+ The start_memory command stores the start of a register's contents
+ and the stop_memory command stores the end.
+
+ At that point, regstart[regnum] points to the first character in the register,
+ regend[regnum] points to the first character beyond the end of the register,
+ regstart_seg1[regnum] is true iff regstart[regnum] points into string1,
+ and regend_seg1[regnum] is true iff regend[regnum] points into string1. */
+
+ unsigned char *regstart[RE_NREGS];
+ unsigned char *regend[RE_NREGS];
+ unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS];
+
+ /* Set up pointers to ends of strings.
+ Don't allow the second string to be empty unless both are empty. */
+ if (!size2)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings */
+ if (mstop <= size1)
+ {
+ end_match_1 = string1 + mstop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + mstop - size1;
+ }
+
+ /* Initialize \) text positions to -1
+ to mark ones that no \( or \) has been seen for. */
+
+ for (mcnt = 0; mcnt < sizeof (regend) / sizeof (*regend); mcnt++)
+ regend[mcnt] = (unsigned char *) -1;
+
+ /* `p' scans through the pattern as `d' scans through the data.
+ `dend' is the end of the input string that `d' points within.
+ `d' is advanced into the following input string whenever necessary,
+ but this happens before fetching;
+ therefore, at the beginning of the loop,
+ `d' can be pointing at the end of a string,
+ but it cannot equal string2. */
+
+ if (pos <= size1)
+ d = string1 + pos, dend = end_match_1;
+ else
+ d = string2 + pos - size1, dend = end_match_2;
+
+/* Write PREFETCH; just before fetching a character with *d. */
+#define PREFETCH \
+ while (d == dend) \
+ { if (dend == end_match_2) goto fail; /* end of string2 => failure */ \
+ d = string2; /* end of string1 => advance to string2. */ \
+ dend = end_match_2; }
+
+ /* This loop loops over pattern commands.
+ It exits by returning from the function if match is complete,
+ or it drops through if match fails at this starting point in the input data. */
+
+ while (1)
+ {
+ if (p == pend)
+ /* End of pattern means we have succeeded! */
+ {
+ /* If caller wants register contents data back, convert it to indices */
+ if (regs)
+ {
+ regs->start[0] = pos;
+ if (dend == end_match_1)
+ regs->end[0] = d - string1;
+ else
+ regs->end[0] = d - string2 + size1;
+ for (mcnt = 1; mcnt < RE_NREGS; mcnt++)
+ {
+ if (regend[mcnt] == (unsigned char *) -1)
+ {
+ regs->start[mcnt] = -1;
+ regs->end[mcnt] = -1;
+ continue;
+ }
+ if (regstart_seg1[mcnt])
+ regs->start[mcnt] = regstart[mcnt] - string1;
+ else
+ regs->start[mcnt] = regstart[mcnt] - string2 + size1;
+ if (regend_seg1[mcnt])
+ regs->end[mcnt] = regend[mcnt] - string1;
+ else
+ regs->end[mcnt] = regend[mcnt] - string2 + size1;
+ }
+ }
+ if (dend == end_match_1)
+ return (d - string1 - pos);
+ else
+ return d - string2 + size1 - pos;
+ }
+
+ /* Otherwise match next pattern command */
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+
+ /* \( is represented by a start_memory, \) by a stop_memory.
+ Both of those commands contain a "register number" argument.
+ The text matched within the \( and \) is recorded under that number.
+ Then, \<digit> turns into a `duplicate' command which
+ is followed by the numeric value of <digit> as the register number. */
+
+ case start_memory:
+ regstart[*p] = d;
+ regstart_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case stop_memory:
+ regend[*p] = d;
+ regend_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case duplicate:
+ {
+ int regno = *p++; /* Get which register to match against */
+ register unsigned char *d2, *dend2;
+
+ d2 = regstart[regno];
+ dend2 = ((regstart_seg1[regno] == regend_seg1[regno])
+ ? regend[regno] : end_match_1);
+ while (1)
+ {
+ /* Advance to next segment in register contents, if necessary */
+ while (d2 == dend2)
+ {
+ if (dend2 == end_match_2) break;
+ if (dend2 == regend[regno]) break;
+ d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */
+ }
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* Advance to next segment in data being matched, if necessary */
+ PREFETCH;
+
+ /* mcnt gets # consecutive chars to compare */
+ mcnt = dend - d;
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+ /* Compare that many; failure if mismatch, else skip them. */
+ if (translate ? bcmp_translate (d, d2, mcnt, translate) : bcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+ }
+ }
+ break;
+
+ case anychar:
+ /* fetch a data character */
+ PREFETCH;
+ /* Match anything but a newline. */
+ if ((translate ? translate[*d++] : *d++) == '\n')
+ goto fail;
+ break;
+
+ case charset:
+ case charset_not:
+ {
+ /* Nonzero for charset_not */
+ int not = 0;
+ register int c;
+ if (*(p - 1) == (unsigned char) charset_not)
+ not = 1;
+
+ /* fetch a data character */
+ PREFETCH;
+
+ if (translate)
+ c = translate [*d];
+ else
+ c = *d;
+
+ if (c < *p * BYTEWIDTH
+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ p += 1 + *p;
+
+ if (!not) goto fail;
+ d++;
+ break;
+ }
+
+ case begline:
+ if (d == string1 || d[-1] == '\n')
+ break;
+ goto fail;
+
+ case endline:
+ if (d == end2
+ || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n'))
+ break;
+ goto fail;
+
+ /* "or" constructs ("|") are handled by starting each alternative
+ with an on_failure_jump that points to the start of the next alternative.
+ Each alternative except the last ends with a jump to the joining point.
+ (Actually, each jump except for the last one really jumps
+ to the following jump, because tensioning the jumps is a hassle.) */
+
+ /* The start of a stupid repeat has an on_failure_jump that points
+ past the end of the repeat text.
+ This makes a failure point so that, on failure to match a repetition,
+ matching restarts past as many repetitions have been found
+ with no way to fail and look for another one. */
+
+ /* A smart repeat is similar but loops back to the on_failure_jump
+ so that each repetition makes another failure point. */
+
+ case on_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx;
+ if (stacke - stackb > re_max_failures * 2)
+ return -2;
+ stackx = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *stackp++ = mcnt + p;
+ *stackp++ = d;
+ break;
+
+ /* The end of a smart repeat has an maybe_finalize_jump back.
+ Change it either to a finalize_jump or an ordinary jump. */
+
+ case maybe_finalize_jump:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ {
+ register unsigned char *p2 = p;
+ /* Compare what follows with the begining of the repeat.
+ If we can establish that there is nothing that they would
+ both match, we can change to finalize_jump */
+ while (p2 != pend
+ && (*p2 == (unsigned char) stop_memory
+ || *p2 == (unsigned char) start_memory))
+ p2++;
+ if (p2 == pend)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (*p2 == (unsigned char) exactn
+ || *p2 == (unsigned char) endline)
+ {
+ register int c = *p2 == (unsigned char) endline ? '\n' : p2[2];
+ register unsigned char *p1 = p + mcnt;
+ /* p1[0] ... p1[2] are an on_failure_jump.
+ Examine what follows that */
+ if (p1[3] == (unsigned char) exactn && p1[5] != c)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (p1[3] == (unsigned char) charset
+ || p1[3] == (unsigned char) charset_not)
+ {
+ int not = p1[3] == (unsigned char) charset_not;
+ if (c < p1[4] * BYTEWIDTH
+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+ /* not is 1 if c would match */
+ /* That means it is not safe to finalize */
+ if (!not)
+ p[-3] = (unsigned char) finalize_jump;
+ }
+ }
+ }
+ p -= 2;
+ if (p[-1] != (unsigned char) finalize_jump)
+ {
+ p[-1] = (unsigned char) jump;
+ goto nofinalize;
+ }
+
+ /* The end of a stupid repeat has a finalize-jump
+ back to the start, where another failure point will be made
+ which will point after all the repetitions found so far. */
+
+ case finalize_jump:
+ stackp -= 2;
+
+ case jump:
+ nofinalize:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += mcnt + 1; /* The 1 compensates for missing ++ above */
+ break;
+
+ case dummy_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx
+ = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ *stackp++ = 0;
+ *stackp++ = 0;
+ goto nofinalize;
+
+ case wordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ break;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ break;
+ goto fail;
+
+ case notwordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ goto fail;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ goto fail;
+ break;
+
+ case wordbeg:
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */
+ goto fail;
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ break;
+ goto fail;
+
+ case wordend:
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ goto fail;
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */
+ break;
+ goto fail;
+
+#ifdef emacs
+ case before_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ <= point)
+ goto fail;
+ break;
+
+ case at_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ == point)
+ goto fail;
+ break;
+
+ case after_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ >= point)
+ goto fail;
+ break;
+
+ case wordchar:
+ mcnt = (int) Sword;
+ goto matchsyntax;
+
+ case syntaxspec:
+ mcnt = *p++;
+ matchsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail;
+ break;
+
+ case notwordchar:
+ mcnt = (int) Sword;
+ goto matchnotsyntax;
+
+ case notsyntaxspec:
+ mcnt = *p++;
+ matchnotsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail;
+ break;
+#else
+ case wordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) == 0) goto fail;
+ break;
+
+ case notwordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) != 0) goto fail;
+ break;
+#endif /* not emacs */
+
+ case begbuf:
+ if (d == string1) /* Note, d cannot equal string2 */
+ break; /* unless string1 == string2. */
+ goto fail;
+
+ case endbuf:
+ if (d == end2 || (d == end1 && size2 == 0))
+ break;
+ goto fail;
+
+ case exactn:
+ /* Match the next few pattern characters exactly.
+ mcnt is how many characters to match. */
+ mcnt = *p++;
+ if (translate)
+ {
+ do
+ {
+ PREFETCH;
+ if (translate[*d++] != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH;
+ if (*d++ != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ break;
+ }
+ continue; /* Successfully matched one pattern command; keep matching */
+
+ /* Jump here if any matching operation fails. */
+ fail:
+ if (stackp != stackb)
+ /* A restart point is known. Restart there and pop it. */
+ {
+ if (!stackp[-2])
+ { /* If innermost failure point is dormant, flush it and keep looking */
+ stackp -= 2;
+ goto fail;
+ }
+ d = *--stackp;
+ p = *--stackp;
+ if (d >= string1 && d <= end1)
+ dend = end_match_1;
+ }
+ else break; /* Matching at this starting point really fails! */
+ }
+ return -1; /* Failure to match */
+}
+
+static int
+bcmp_translate (s1, s2, len, translate)
+ unsigned char *s1, *s2;
+ register int len;
+ unsigned char *translate;
+{
+ register unsigned char *p1 = s1, *p2 = s2;
+ while (len)
+ {
+ if (translate [*p1++] != translate [*p2++]) return 1;
+ len--;
+ }
+ return 0;
+}
+
+/* Entry points compatible with bsd4.2 regex library */
+
+#ifndef emacs
+
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+ char *s;
+{
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return "No previous regular expression";
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ if (!(re_comp_buf.buffer = (char *) malloc (200)))
+ return "Memory exhausted";
+ re_comp_buf.allocated = 200;
+ if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH)))
+ return "Memory exhausted";
+ }
+ return re_compile_pattern (s, strlen (s), &re_comp_buf);
+}
+
+int
+re_exec (s)
+ char *s;
+{
+ int len = strlen (s);
+ return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0);
+}
+
+#endif /* emacs */
+
+#ifdef test
+
+#include <stdio.h>
+
+/* Indexed by a character, gives the upper case equivalent of the character */
+
+static char upcase[0400] =
+ { 000, 001, 002, 003, 004, 005, 006, 007,
+ 010, 011, 012, 013, 014, 015, 016, 017,
+ 020, 021, 022, 023, 024, 025, 026, 027,
+ 030, 031, 032, 033, 034, 035, 036, 037,
+ 040, 041, 042, 043, 044, 045, 046, 047,
+ 050, 051, 052, 053, 054, 055, 056, 057,
+ 060, 061, 062, 063, 064, 065, 066, 067,
+ 070, 071, 072, 073, 074, 075, 076, 077,
+ 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+ };
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char pat[80];
+ struct re_pattern_buffer buf;
+ int i;
+ char c;
+ char fastmap[(1 << BYTEWIDTH)];
+
+ /* Allow a command argument to specify the style of syntax. */
+ if (argc > 1)
+ obscure_syntax = atoi (argv[1]);
+
+ buf.allocated = 40;
+ buf.buffer = (char *) malloc (buf.allocated);
+ buf.fastmap = fastmap;
+ buf.translate = upcase;
+
+ while (1)
+ {
+ gets (pat);
+
+ if (*pat)
+ {
+ re_compile_pattern (pat, strlen(pat), &buf);
+
+ for (i = 0; i < buf.used; i++)
+ printchar (buf.buffer[i]);
+
+ putchar ('\n');
+
+ printf ("%d allocated, %d used.\n", buf.allocated, buf.used);
+
+ re_compile_fastmap (&buf);
+ printf ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (fastmap[i]) printchar (i);
+ putchar ('\n');
+ }
+
+ gets (pat); /* Now read the string to match against */
+
+ i = re_match (&buf, pat, strlen (pat), 0, 0);
+ printf ("Match value %d.\n", i);
+ }
+}
+
+#ifdef NOTDEF
+print_buf (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ int i;
+
+ printf ("buf is :\n----------------\n");
+ for (i = 0; i < bufp->used; i++)
+ printchar (bufp->buffer[i]);
+
+ printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used);
+
+ printf ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->fastmap[i])
+ printchar (i);
+ printf ("\nAllowed by translate: ");
+ if (bufp->translate)
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->translate[i])
+ printchar (i);
+ printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't");
+ printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not");
+}
+#endif
+
+printchar (c)
+ char c;
+{
+ if (c < 041 || c >= 0177)
+ {
+ putchar ('\\');
+ putchar (((c >> 6) & 3) + '0');
+ putchar (((c >> 3) & 7) + '0');
+ putchar ((c & 7) + '0');
+ }
+ else
+ putchar (c);
+}
+
+error (string)
+ char *string;
+{
+ puts (string);
+ exit (1);
+}
+
+#endif /* test */
diff --git a/gnu/usr.bin/kgdb/regex.h b/gnu/usr.bin/kgdb/regex.h
new file mode 100644
index 000000000000..d0d8a82835b6
--- /dev/null
+++ b/gnu/usr.bin/kgdb/regex.h
@@ -0,0 +1,185 @@
+/* Definitions for data structures callers pass the regex library.
+ Copyright (C) 1985, 1989 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+
+/* Define number of parens for which we record the beginnings and ends.
+ This affects how much space the `struct re_registers' type takes up. */
+#ifndef RE_NREGS
+#define RE_NREGS 10
+#endif
+
+/* These bits are used in the obscure_syntax variable to choose among
+ alternative regexp syntaxes. */
+
+/* 1 means plain parentheses serve as grouping, and backslash
+ parentheses are needed for literal searching.
+ 0 means backslash-parentheses are grouping, and plain parentheses
+ are for literal searching. */
+#define RE_NO_BK_PARENS 1
+
+/* 1 means plain | serves as the "or"-operator, and \| is a literal.
+ 0 means \| serves as the "or"-operator, and | is a literal. */
+#define RE_NO_BK_VBAR 2
+
+/* 0 means plain + or ? serves as an operator, and \+, \? are literals.
+ 1 means \+, \? are operators and plain +, ? are literals. */
+#define RE_BK_PLUS_QM 4
+
+/* 1 means | binds tighter than ^ or $.
+ 0 means the contrary. */
+#define RE_TIGHT_VBAR 8
+
+/* 1 means treat \n as an _OR operator
+ 0 means treat it as a normal character */
+#define RE_NEWLINE_OR 16
+
+/* 0 means that a special characters (such as *, ^, and $) always have
+ their special meaning regardless of the surrounding context.
+ 1 means that special characters may act as normal characters in some
+ contexts. Specifically, this applies to:
+ ^ - only special at the beginning, or after ( or |
+ $ - only special at the end, or before ) or |
+ *, +, ? - only special when not after the beginning, (, or | */
+#define RE_CONTEXT_INDEP_OPS 32
+
+/* Now define combinations of bits for the standard possibilities. */
+#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS)
+#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR)
+#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
+#define RE_SYNTAX_EMACS 0
+
+/* This data structure is used to represent a compiled pattern. */
+
+struct re_pattern_buffer
+ {
+ char *buffer; /* Space holding the compiled pattern commands. */
+ int allocated; /* Size of space that buffer points to */
+ int used; /* Length of portion of buffer actually occupied */
+ char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
+ /* re_search uses the fastmap, if there is one,
+ to skip quickly over totally implausible characters */
+ char *translate; /* Translate table to apply to all characters before comparing.
+ Or zero for no translation.
+ The translation is applied to a pattern when it is compiled
+ and to data when it is matched. */
+ char fastmap_accurate;
+ /* Set to zero when a new pattern is stored,
+ set to one when the fastmap is updated from it. */
+ char can_be_null; /* Set to one by compiling fastmap
+ if this pattern might match the null string.
+ It does not necessarily match the null string
+ in that case, but if this is zero, it cannot.
+ 2 as value means can match null string
+ but at end of range or before a character
+ listed in the fastmap. */
+ };
+
+/* Structure to store "register" contents data in.
+
+ Pass the address of such a structure as an argument to re_match, etc.,
+ if you want this information back.
+
+ start[i] and end[i] record the string matched by \( ... \) grouping i,
+ for i from 1 to RE_NREGS - 1.
+ start[0] and end[0] record the entire string matched. */
+
+struct re_registers
+ {
+ int start[RE_NREGS];
+ int end[RE_NREGS];
+ };
+
+/* These are the command codes that appear in compiled regular expressions, one per byte.
+ Some command codes are followed by argument bytes.
+ A command code can specify any interpretation whatever for its arguments.
+ Zero-bytes may appear in the compiled regular expression. */
+
+enum regexpcode
+ {
+ unused,
+ exactn, /* followed by one byte giving n, and then by n literal bytes */
+ begline, /* fails unless at beginning of line */
+ endline, /* fails unless at end of line */
+ jump, /* followed by two bytes giving relative address to jump to */
+ on_failure_jump, /* followed by two bytes giving relative address of place
+ to resume at in case of failure. */
+ finalize_jump, /* Throw away latest failure point and then jump to address. */
+ maybe_finalize_jump, /* Like jump but finalize if safe to do so.
+ This is used to jump back to the beginning
+ of a repeat. If the command that follows
+ this jump is clearly incompatible with the
+ one at the beginning of the repeat, such that
+ we can be sure that there is no use backtracking
+ out of repetitions already completed,
+ then we finalize. */
+ dummy_failure_jump, /* jump, and push a dummy failure point.
+ This failure point will be thrown away
+ if an attempt is made to use it for a failure.
+ A + construct makes this before the first repeat. */
+ anychar, /* matches any one character */
+ charset, /* matches any one char belonging to specified set.
+ First following byte is # bitmap bytes.
+ Then come bytes for a bit-map saying which chars are in.
+ Bits in each byte are ordered low-bit-first.
+ A character is in the set if its bit is 1.
+ A character too large to have a bit in the map
+ is automatically not in the set */
+ charset_not, /* similar but match any character that is NOT one of those specified */
+ start_memory, /* starts remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ stop_memory, /* stops remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ duplicate, /* match a duplicate of something remembered.
+ Followed by one byte containing the index of the memory register. */
+ before_dot, /* Succeeds if before dot */
+ at_dot, /* Succeeds if at dot */
+ after_dot, /* Succeeds if after dot */
+ begbuf, /* Succeeds if at beginning of buffer */
+ endbuf, /* Succeeds if at end of buffer */
+ wordchar, /* Matches any word-constituent character */
+ notwordchar, /* Matches any char that is not a word-constituent */
+ wordbeg, /* Succeeds if at word beginning */
+ wordend, /* Succeeds if at word end */
+ wordbound, /* Succeeds if at a word boundary */
+ notwordbound, /* Succeeds if not at a word boundary */
+ syntaxspec, /* Matches any character whose syntax is specified.
+ followed by a byte which contains a syntax code, Sword or such like */
+ notsyntaxspec /* Matches any character whose syntax differs from the specified. */
+ };
+
+extern char *re_compile_pattern ();
+/* Is this really advertised? */
+extern void re_compile_fastmap ();
+extern int re_search (), re_search_2 ();
+extern int re_match (), re_match_2 ();
+
+/* 4.2 bsd compatibility (yuck) */
+extern char *re_comp ();
+extern int re_exec ();
+
+#ifdef SYNTAX_TABLE
+extern char *re_syntax_table;
+#endif
diff --git a/gnu/usr.bin/kgdb/remote-sl.c b/gnu/usr.bin/kgdb/remote-sl.c
new file mode 100644
index 000000000000..4c72197f1ae1
--- /dev/null
+++ b/gnu/usr.bin/kgdb/remote-sl.c
@@ -0,0 +1,10 @@
+/*
+ * The binary remote protocol is still under development at LBL;
+ * the current version can't be released.
+ * Sorry, folks...
+ */
+int
+sl_open()
+{
+ return -1;
+}
diff --git a/gnu/usr.bin/kgdb/remote.c b/gnu/usr.bin/kgdb/remote.c
new file mode 100644
index 000000000000..e1c2181cc18e
--- /dev/null
+++ b/gnu/usr.bin/kgdb/remote.c
@@ -0,0 +1,626 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * /home/ncvs/src/gnu/usr.bin/kgdb/remote.c,v 1.1 1993/06/29 09:47:34 nate Exp;
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)remote.c 6.5 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+#include "param.h"
+
+#include <stdio.h>
+#include <varargs.h>
+
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include "kgdb_proto.h"
+
+static FILE *kiodebug;
+static int icache = 1;
+extern int kernel_debugging;
+
+static int remote_cache_valid;
+static int remote_instub;
+
+static void remote_signal();
+static void remote_debug();
+static void print_msg();
+
+static int remote_mtu;
+static int (*send_msg)();
+static int (*recv_msg)();
+static void (*closelink)();
+
+static u_char *inbuffer;
+static u_char *outbuffer;
+
+/*
+ * Statistics.
+ */
+static int remote_ierrs;
+static int remote_oerrs;
+static int remote_seqerrs;
+static int remote_spurious;
+
+#define PUTCMD(cmd) m_xchg(cmd, (u_char *)0, 0, (u_char *)0, (int *)0)
+
+/*
+ * Send an outbound message to the remote machine and read the reply.
+ * Either or both message buffers may be NULL.
+ */
+static int
+m_xchg(type, out, outlen, in, inlen)
+ int type;
+ u_char *out;
+ int outlen;
+ u_char *in;
+ int *inlen;
+{
+ register int err, (*send)() = send_msg, (*recv)() = recv_msg;
+ int ack;
+ static int seqbit = 0;
+
+ if (!remote_instub) {
+ remote_instub = 1;
+ PUTCMD(KGDB_EXEC);
+ }
+
+ seqbit ^= KGDB_SEQ;
+ while (1) {
+ err = (*send)(type | seqbit, out, outlen);
+ if (err) {
+ ++remote_oerrs;
+ if (kiodebug)
+ remote_debug("send error %d\n", err);
+ }
+ if (kiodebug)
+ print_msg(type | seqbit, out, outlen, 'O');
+
+ recv:
+ err = (*recv)(&ack, in, inlen);
+ if (err) {
+ ++remote_ierrs;
+ if (kiodebug)
+ remote_debug("recv error %d\n", err);
+ remote_cache_valid = 0;
+ } else if (kiodebug)
+ print_msg(ack, in, inlen ? *inlen : 0, 'I');
+
+ if (err)
+ continue;
+
+ if ((ack & KGDB_ACK) == 0 || KGDB_CMD(ack) != KGDB_CMD(type)) {
+ ++remote_spurious;
+ continue;
+ }
+ if ((ack & KGDB_SEQ) ^ seqbit) {
+ ++remote_seqerrs;
+ goto recv;
+ }
+ return ack;
+ }
+}
+
+/*
+ * Wait for the specified message type. Discard anything else.
+ * (this is used by 'remote-signal' to help us resync with other side.)
+ */
+static void
+m_recv(type, in, inlen)
+ int type;
+ u_char *in;
+ int *inlen;
+{
+ int reply, err;
+
+ while (1) {
+ err = (*recv_msg)(&reply, in, inlen);
+ if (err) {
+ ++remote_ierrs;
+ if (kiodebug)
+ remote_debug("recv error %d\n", err);
+ } else if (kiodebug)
+ print_msg(reply, in, inlen ? *inlen : 0, 'I');
+
+ if (KGDB_CMD(reply) == type)
+ return;
+ ++remote_spurious;
+ }
+}
+
+/*
+ * Send a message. Do not wait for *any* response from the other side.
+ * Some other thread of control will pick up the ack that will be generated.
+ */
+static void
+m_send(type, buf, len)
+ int type;
+ u_char *buf;
+ int len;
+{
+ int err;
+
+ if (!remote_instub) {
+ remote_instub = 1;
+ PUTCMD(KGDB_EXEC);
+ }
+
+ err = (*send_msg)(type, buf, len);
+ if (err) {
+ ++remote_ierrs;
+ if (kiodebug)
+ remote_debug("[send error %d] ", err);
+ }
+ if (kiodebug)
+ print_msg(type, buf, len, 'O');
+}
+
+/*
+ * Open a connection to a remote debugger.
+ * NAME is the filename used for communication.
+ */
+void
+remote_open(name, from_tty)
+ char *name;
+ int from_tty;
+{
+ int bufsize;
+
+ remote_debugging = 0;
+ if (sl_open(name, &send_msg, &recv_msg, &closelink, &remote_mtu,
+ &bufsize))
+ return;
+ if (from_tty)
+ printf("Remote debugging using %s\n", name);
+ remote_debugging = 1;
+
+ remote_cache_valid = 0;
+
+ inbuffer = (u_char *)malloc(bufsize);
+ outbuffer = (u_char *)malloc(bufsize);
+
+ remote_signal();
+
+ remote_ierrs = 0;
+ remote_oerrs = 0;
+ remote_spurious = 0;
+}
+
+/*
+ * Close the open connection to the remote debugger. Use this when you want
+ * to detach and do something else with your gdb.
+ */
+void
+remote_close(from_tty)
+ int from_tty;
+{
+ if (!remote_debugging)
+ error("remote debugging not enabled");
+
+ remote_debugging = 0;
+ /*
+ * Take remote machine out of debug mode.
+ */
+ (void)PUTCMD(KGDB_KILL);
+ (*closelink)();
+ if (from_tty)
+ printf("Ending remote debugging\n");
+
+ free((char *)inbuffer);
+ free((char *)outbuffer);
+}
+
+/*
+ * Tell the remote machine to resume.
+ */
+int
+remote_resume(step, signal)
+ int step, signal;
+{
+ if (!step) {
+ (void)PUTCMD(KGDB_CONT);
+ remote_instub = 0;
+ } else {
+#ifdef NO_SINGLE_STEP
+ single_step(0);
+#else
+ (void)PUTCMD(KGDB_STEP);
+#endif
+ }
+}
+
+/*
+ * Wait until the remote machine stops, then return, storing status in STATUS
+ * just as `wait' would.
+ */
+int
+remote_wait(status)
+ WAITTYPE *status;
+{
+ int len;
+
+ WSETEXIT((*status), 0);
+ /*
+ * When the machine stops, it will send us a KGDB_SIGNAL message,
+ * so we wait for one of these.
+ */
+ m_recv(KGDB_SIGNAL, inbuffer, &len);
+ WSETSTOP((*status), inbuffer[0]);
+}
+
+/*
+ * Register context as of last remote_fetch_registers().
+ */
+static char reg_cache[REGISTER_BYTES];
+
+/*
+ * Read the remote registers into the block REGS.
+ */
+void
+remote_fetch_registers(regs)
+ char *regs;
+{
+ int regno, len, rlen, ack;
+ u_char *cp, *ep;
+
+ regno = -1;
+ do {
+ outbuffer[0] = regno + 1;
+ ack = m_xchg(remote_cache_valid ?
+ KGDB_REG_R|KGDB_DELTA : KGDB_REG_R,
+ outbuffer, 1, inbuffer, &len);
+ cp = inbuffer;
+ ep = cp + len;
+ while (cp < ep) {
+ regno = *cp++;
+ rlen = REGISTER_RAW_SIZE(regno);
+ bcopy((char *)cp,
+ &reg_cache[REGISTER_BYTE(regno)], rlen);
+ cp += rlen;
+ }
+ } while (ack & KGDB_MORE);
+
+ remote_cache_valid = 1;
+ bcopy(reg_cache, regs, REGISTER_BYTES);
+}
+
+/*
+ * Store the remote registers from the contents of the block REGS.
+ */
+void
+remote_store_registers(regs)
+ char *regs;
+{
+ u_char *cp, *ep;
+ int regno, off, rlen;
+
+ cp = outbuffer;
+ ep = cp + remote_mtu;
+
+ for (regno = 0; regno < NUM_REGS; ++regno) {
+ off = REGISTER_BYTE(regno);
+ rlen = REGISTER_RAW_SIZE(regno);
+ if (!remote_cache_valid ||
+ bcmp(&regs[off], &reg_cache[off], rlen) != 0) {
+ if (cp + rlen + 1 >= ep) {
+ (void)m_xchg(KGDB_REG_W,
+ outbuffer, cp - outbuffer,
+ (u_char *)0, (int *)0);
+ cp = outbuffer;
+ }
+ *cp++ = regno;
+ bcopy(&regs[off], cp, rlen);
+ cp += rlen;
+ }
+ }
+ if (cp != outbuffer)
+ (void)m_xchg(KGDB_REG_W, outbuffer, cp - outbuffer,
+ (u_char *)0, (int *)0);
+ bcopy(regs, reg_cache, REGISTER_BYTES);
+}
+
+/*
+ * Store a chunk of memory into the remote host.
+ * 'remote_addr' is the address in the remote memory space.
+ * 'cp' is the address of the buffer in our space, and 'len' is
+ * the number of bytes. Returns an errno status.
+ */
+int
+remote_write_inferior_memory(remote_addr, cp, len)
+ CORE_ADDR remote_addr;
+ u_char *cp;
+ int len;
+{
+ int cnt;
+
+ while (len > 0) {
+ cnt = min(len, remote_mtu - 4);
+ bcopy((char *)&remote_addr, outbuffer, 4);
+ bcopy(cp, outbuffer + 4, cnt);
+ (void)m_xchg(KGDB_MEM_W, outbuffer, cnt + 4, inbuffer, &len);
+
+ if (inbuffer[0])
+ return inbuffer[0];
+
+ remote_addr += cnt;
+ cp += cnt;
+ len -= cnt;
+ }
+ return 0;
+}
+
+/*
+ * Read memory data directly from the remote machine.
+ * 'remote_addr' is the address in the remote memory space.
+ * 'cp' is the address of the buffer in our space, and 'len' is
+ * the number of bytes. Returns an errno status.
+ */
+static int
+remote_read_memory(remote_addr, cp, len)
+ CORE_ADDR remote_addr;
+ u_char *cp;
+ int len;
+{
+ int cnt, inlen;
+
+ while (len > 0) {
+ cnt = min(len, remote_mtu - 1);
+ outbuffer[0] = cnt;
+ bcopy((char *)&remote_addr, (char *)&outbuffer[1], 4);
+
+ (void)m_xchg(KGDB_MEM_R, outbuffer, 5, inbuffer, &inlen);
+
+ if (inbuffer[0] != 0)
+ return inbuffer[0];
+
+ if (cnt != inlen - 1)
+ /* XXX */
+ error("remote_read_memory() request botched");
+
+ bcopy((char *)&inbuffer[1], (char *)cp, cnt);
+
+ remote_addr += cnt;
+ cp += cnt;
+ len -= cnt;
+ }
+ return 0;
+}
+
+int
+remote_read_inferior_memory(remote_addr, cp, len)
+ CORE_ADDR remote_addr;
+ char *cp;
+ int len;
+{
+ int stat = 0;
+
+ if (icache) {
+ extern CORE_ADDR text_start, text_end;
+ CORE_ADDR xferend = remote_addr + len;
+
+ if (remote_addr < text_end && text_start < xferend) {
+ /*
+ * at least part of this xfer is in the text
+ * space -- xfer the overlap from the exec file.
+ */
+ if (remote_addr >= text_start && xferend < text_end)
+ return (xfer_core_file(remote_addr, cp, len));
+ if (remote_addr >= text_start) {
+ int i = text_end - remote_addr;
+
+ if (stat = xfer_core_file(remote_addr, cp, i))
+ return (stat);
+ remote_addr += i;
+ cp += i;
+ len -= i;
+ } else if (xferend <= text_end) {
+ int i = xferend - text_start;
+
+ len = text_start - remote_addr;
+ if (stat = xfer_core_file(text_start,
+ cp + len, i))
+ return (stat);
+ }
+ }
+ }
+ return remote_read_memory(remote_addr, cp, len);
+}
+
+/*
+ * Signal the remote machine. The remote end might be idle or it might
+ * already be in debug mode -- we need to handle both case. Thus, we use
+ * the framing character as the wakeup byte, and send a SIGNAL packet.
+ * If the remote host is idle, the framing character will wake it up.
+ * If it is in the kgdb stub, then we will get a SIGNAL reply.
+ */
+static void
+remote_signal()
+{
+ if (!remote_debugging)
+ printf("Remote debugging not enabled.\n");
+ else {
+ remote_instub = 0;
+ m_send(KGDB_SIGNAL, (u_char *)0, 0);
+ }
+}
+
+static void
+remote_signal_command()
+{
+ extern int stop_after_attach;
+
+ if (!remote_debugging)
+ error("Not debugging remote.");
+ remote_cache_valid = 0;
+ remote_signal();
+ restart_remote();
+}
+
+/*
+ * Print a message for debugging.
+ */
+static void
+print_msg(type, buf, len, dir)
+ int type;
+ u_char *buf;
+ int len;
+ int dir;
+{
+ int i;
+ char *s;
+
+ switch (KGDB_CMD(type)) {
+ case KGDB_MEM_R: s = "memr"; break;
+ case KGDB_MEM_W: s = "memw"; break;
+ case KGDB_REG_R: s = "regr"; break;
+ case KGDB_REG_W: s = "regw"; break;
+ case KGDB_CONT: s = "cont"; break;
+ case KGDB_STEP: s = "step"; break;
+ case KGDB_KILL: s = "kill"; break;
+ case KGDB_SIGNAL: s = "sig "; break;
+ case KGDB_EXEC: s = "exec"; break;
+ default: s = "unk "; break;
+ }
+ remote_debug("%c %c%c%c%c %s (%02x): ", dir,
+ (type & KGDB_ACK) ? 'A' : '.',
+ (type & KGDB_DELTA) ? 'D' : '.',
+ (type & KGDB_MORE) ? 'M' : '.',
+ (type & KGDB_SEQ) ? '-' : '+',
+ s, type);
+ if (buf)
+ for (i = 0; i < len; ++i)
+ remote_debug("%02x", buf[i]);
+ remote_debug("\n");
+}
+
+static void
+set_remote_text_refs_command(arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ icache = !parse_binary_operation("set remote-text-refs", arg);
+}
+
+static void
+remote_debug_command(arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char *name;
+
+ if (kiodebug != 0 && kiodebug != stderr)
+ (void)fclose(kiodebug);
+
+ if (arg == 0) {
+ kiodebug = 0;
+ printf("Remote debugging off.\n");
+ return;
+ }
+ if (arg[0] == '-') {
+ kiodebug = stderr;
+ name = "stderr";
+ } else {
+ kiodebug = fopen(arg, "w");
+ if (kiodebug == 0) {
+ printf("Cannot open '%s'.\n", arg);
+ return;
+ }
+ name = arg;
+ }
+ printf("Remote debugging output routed to %s.\n", name);
+}
+
+/* ARGSUSED */
+static void
+remote_info(arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf("Using %s for text references.\n",
+ icache? "local executable" : "remote");
+ printf("Protocol debugging is %s.\n", kiodebug? "on" : "off");
+ printf("%d spurious input messages.\n", remote_spurious);
+ printf("%d input errors; %d output errors; %d sequence errors.\n",
+ remote_ierrs, remote_oerrs, remote_seqerrs);
+}
+
+/* VARARGS */
+static void
+remote_debug(va_alist)
+ va_dcl
+{
+ register char *cp;
+ va_list ap;
+
+ va_start(ap);
+ cp = va_arg(ap, char *);
+ (void)vfprintf(kiodebug, cp, ap);
+ va_end(ap);
+ fflush(kiodebug);
+}
+
+extern struct cmd_list_element *setlist;
+
+void
+_initialize_remote()
+{
+ add_com("remote-signal", class_run, remote_signal_command,
+ "If remote debugging, send interrupt signal to remote.");
+ add_cmd("remote-text-refs", class_support,
+ set_remote_text_refs_command,
+"Enable/disable use of local executable for text segment references.\n\
+If on, all memory read/writes go to remote.\n\
+If off, text segment reads use the local executable.",
+ &setlist);
+
+ add_com("remote-debug", class_run, remote_debug_command,
+"With a file name argument, enables output of remote protocol debugging\n\
+messages to said file. If file is `-', stderr is used.\n\
+With no argument, remote debugging is disabled.");
+
+ add_info("remote", remote_info,
+ "Show current settings of remote debugging options.");
+}
+
diff --git a/gnu/usr.bin/kgdb/source.c b/gnu/usr.bin/kgdb/source.c
new file mode 100644
index 000000000000..bb65e1ca9483
--- /dev/null
+++ b/gnu/usr.bin/kgdb/source.c
@@ -0,0 +1,1166 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)source.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* List lines of source files for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+
+#ifdef USG
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+/* Path of directories to search for source files.
+ Same format as the PATH environment variable's value. */
+
+static char *source_path;
+
+/* Symtab of default file for listing lines of. */
+
+struct symtab *current_source_symtab;
+
+/* Default next line to list. */
+
+int current_source_line;
+
+/* Line number of last line printed. Default for various commands.
+ current_source_line is usually, but not always, the same as this. */
+
+static int last_line_listed;
+
+/* First line number listed by last listing command. */
+
+static int first_line_listed;
+
+
+struct symtab *psymtab_to_symtab ();
+
+/* Set the source file default for the "list" command, specifying a
+ symtab. Sigh. Behaivior specification: If it is called with a
+ non-zero argument, that is the symtab to select. If it is not,
+ first lookup "main"; if it exists, use the symtab and line it
+ defines. If not, take the last symtab in the symtab_list (if it
+ exists) or the last symtab in the psytab_list (if *it* exists). If
+ none of this works, report an error. */
+
+void
+select_source_symtab (s)
+ register struct symtab *s;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct partial_symtab *ps, *cs_pst;
+
+ if (s)
+ {
+ current_source_symtab = s;
+ current_source_line = 1;
+ return;
+ }
+
+ /* Make the default place to list be the function `main'
+ if one exists. */
+ if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0))
+ {
+ sals = decode_line_spec ("main", 1);
+ sal = sals.sals[0];
+ free (sals.sals);
+ current_source_symtab = sal.symtab;
+ current_source_line = max (sal.line - 9, 1);
+ return;
+ }
+
+ /* All right; find the last file in the symtab list (ignoring .h's). */
+
+ if (s = symtab_list)
+ {
+ do
+ {
+ char *name = s->filename;
+ int len = strlen (name);
+ if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
+ current_source_symtab = s;
+ s = s->next;
+ }
+ while (s);
+ current_source_line = 1;
+ }
+ else if (partial_symtab_list)
+ {
+ ps = partial_symtab_list;
+ while (ps)
+ {
+ char *name = ps->filename;
+ int len = strlen (name);
+ if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
+ cs_pst = ps;
+ ps = ps->next;
+ }
+ if (cs_pst)
+ if (cs_pst->readin)
+ fatal ("Internal: select_source_symtab: readin pst found and no symtabs.");
+ else
+ current_source_symtab = psymtab_to_symtab (cs_pst);
+ else
+ current_source_symtab = 0;
+ current_source_line = 1;
+ }
+}
+
+static void
+directories_info ()
+{
+ printf ("Source directories searched: %s\n", source_path);
+}
+
+void
+init_source_path ()
+{
+ register struct symtab *s;
+
+ source_path = savestring (current_directory, strlen (current_directory));
+
+ /* Forget what we learned about line positions in source files;
+ must check again now since files may be found in
+ a different directory now. */
+ for (s = symtab_list; s; s = s->next)
+ if (s->line_charpos != 0)
+ {
+ free (s->line_charpos);
+ s->line_charpos = 0;
+ }
+}
+
+void
+directory_command (dirname, from_tty)
+ char *dirname;
+ int from_tty;
+{
+ char *old = source_path;
+
+ dont_repeat ();
+
+ if (dirname == 0)
+ {
+ if (query ("Reinitialize source path to %s? ", current_directory))
+ {
+ init_source_path ();
+ free (old);
+ }
+ }
+ else
+ {
+ dirname = tilde_expand (dirname);
+ make_cleanup (free, dirname);
+
+ do
+ {
+ char *name = dirname;
+ register char *p;
+ struct stat st;
+
+ {
+ char *colon = index (name, ':');
+ char *space = index (name, ' ');
+ char *tab = index (name, '\t');
+ if (colon == 0 && space == 0 && tab == 0)
+ p = dirname = name + strlen (name);
+ else
+ {
+ p = 0;
+ if (colon != 0 && (p == 0 || colon < p))
+ p = colon;
+ if (space != 0 && (p == 0 || space < p))
+ p = space;
+ if (tab != 0 && (p == 0 || tab < p))
+ p = tab;
+ dirname = p + 1;
+ while (*dirname == ':' || *dirname == ' ' || *dirname == '\t')
+ ++dirname;
+ }
+ }
+
+ if (p[-1] == '/')
+ /* Sigh. "foo/" => "foo" */
+ --p;
+ *p = '\0';
+
+ while (p[-1] == '.')
+ {
+ if (p - name == 1)
+ {
+ /* "." => getwd (). */
+ name = current_directory;
+ goto append;
+ }
+ else if (p[-2] == '/')
+ {
+ if (p - name == 2)
+ {
+ /* "/." => "/". */
+ *--p = '\0';
+ goto append;
+ }
+ else
+ {
+ /* "...foo/." => "...foo". */
+ p -= 2;
+ *p = '\0';
+ continue;
+ }
+ }
+ else
+ break;
+ }
+
+ if (*name != '/')
+ name = concat (current_directory, "/", name);
+ else
+ name = savestring (name, p - name);
+ make_cleanup (free, name);
+
+ if (stat (name, &st) < 0)
+ perror_with_name (name);
+ if ((st.st_mode & S_IFMT) != S_IFDIR)
+ error ("%s is not a directory.", name);
+
+ append:
+ {
+ register unsigned int len = strlen (name);
+
+ p = source_path;
+ while (1)
+ {
+ if (!strncmp (p, name, len)
+ && (p[len] == '\0' || p[len] == ':'))
+ {
+ if (from_tty)
+ printf ("\"%s\" is already in the source path.\n", name);
+ break;
+ }
+ p = index (p, ':');
+ if (p != 0)
+ ++p;
+ else
+ break;
+ }
+ if (p == 0)
+ {
+ source_path = concat (old, ":", name);
+ free (old);
+ old = source_path;
+ }
+ }
+ } while (*dirname != '\0');
+ if (from_tty)
+ directories_info ();
+ }
+}
+
+/* Open a file named STRING, searching path PATH (dir names sep by colons)
+ using mode MODE and protection bits PROT in the calls to open.
+ If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
+ (ie pretend the first element of PATH is ".")
+ If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
+ the actual file opened (this string will always start with a "/"
+
+ If a file is found, return the descriptor.
+ Otherwise, return -1, with errno set for the last name we tried to open. */
+
+/* >>>> This should only allow files of certain types,
+ >>>> eg executable, non-directory */
+int
+openp (path, try_cwd_first, string, mode, prot, filename_opened)
+ char *path;
+ int try_cwd_first;
+ char *string;
+ int mode;
+ int prot;
+ char **filename_opened;
+{
+ register int fd;
+ register char *filename;
+ register char *p, *p1;
+ register int len;
+
+ if (!path)
+ path = ".";
+
+ /* ./foo => foo */
+ while (string[0] == '.' && string[1] == '/')
+ string += 2;
+
+ if (try_cwd_first || string[0] == '/')
+ {
+ filename = string;
+ fd = open (filename, mode, prot);
+ if (fd >= 0 || string[0] == '/')
+ goto done;
+ }
+
+ filename = (char *) alloca (strlen (path) + strlen (string) + 2);
+ fd = -1;
+ for (p = path; p; p = p1 ? p1 + 1 : 0)
+ {
+ p1 = (char *) index (p, ':');
+ if (p1)
+ len = p1 - p;
+ else
+ len = strlen (p);
+
+ strncpy (filename, p, len);
+ filename[len] = 0;
+ strcat (filename, "/");
+ strcat (filename, string);
+
+ fd = open (filename, mode, prot);
+ if (fd >= 0) break;
+ }
+
+ done:
+ if (filename_opened)
+ if (fd < 0)
+ *filename_opened = (char *) 0;
+ else if (filename[0] == '/')
+ *filename_opened = savestring (filename, strlen (filename));
+ else
+ {
+ *filename_opened = concat (current_directory, "/", filename);
+ }
+
+ return fd;
+}
+
+/* Create and initialize the table S->line_charpos that records
+ the positions of the lines in the source file, which is assumed
+ to be open on descriptor DESC.
+ All set S->nlines to the number of such lines. */
+
+static void
+find_source_lines (s, desc)
+ struct symtab *s;
+ int desc;
+{
+ struct stat st;
+ register char *data, *p, *end;
+ int nlines = 0;
+ int lines_allocated = 1000;
+ int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
+ extern int exec_mtime;
+
+ if (fstat (desc, &st) < 0)
+ perror_with_name (s->filename);
+ if (get_exec_file (0) != 0 && exec_mtime < st.st_mtime)
+ printf ("Source file is more recent than executable.\n");
+
+ data = (char *) alloca (st.st_size);
+ if (myread (desc, data, st.st_size) < 0)
+ perror_with_name (s->filename);
+ end = data + st.st_size;
+ p = data;
+ line_charpos[0] = 0;
+ nlines = 1;
+ while (p != end)
+ {
+ if (*p++ == '\n'
+ /* A newline at the end does not start a new line. */
+ && p != end)
+ {
+ if (nlines == lines_allocated)
+ {
+ lines_allocated *= 2;
+ line_charpos = (int *) xrealloc (line_charpos,
+ sizeof (int) * lines_allocated);
+ }
+ line_charpos[nlines++] = p - data;
+ }
+ }
+ s->nlines = nlines;
+ s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
+}
+
+/* Return the character position of a line LINE in symtab S.
+ Return 0 if anything is invalid. */
+
+int
+source_line_charpos (s, line)
+ struct symtab *s;
+ int line;
+{
+ if (!s) return 0;
+ if (!s->line_charpos || line <= 0) return 0;
+ if (line > s->nlines)
+ line = s->nlines;
+ return s->line_charpos[line - 1];
+}
+
+/* Return the line number of character position POS in symtab S. */
+
+int
+source_charpos_line (s, chr)
+ register struct symtab *s;
+ register int chr;
+{
+ register int line = 0;
+ register int *lnp;
+
+ if (s == 0 || s->line_charpos == 0) return 0;
+ lnp = s->line_charpos;
+ /* Files are usually short, so sequential search is Ok */
+ while (line < s->nlines && *lnp <= chr)
+ {
+ line++;
+ lnp++;
+ }
+ if (line >= s->nlines)
+ line = s->nlines;
+ return line;
+}
+
+/* Get full pathname and line number positions for a symtab.
+ Return nonzero if line numbers may have changed.
+ Set *FULLNAME to actual name of the file as found by `openp',
+ or to 0 if the file is not found. */
+
+int
+get_filename_and_charpos (s, line, fullname)
+ struct symtab *s;
+ int line;
+ char **fullname;
+{
+ register int desc, linenums_changed = 0;
+
+ desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
+ if (desc < 0)
+ {
+ if (fullname)
+ *fullname = NULL;
+ return 0;
+ }
+ if (fullname)
+ *fullname = s->fullname;
+ if (s->line_charpos == 0) linenums_changed = 1;
+ if (linenums_changed) find_source_lines (s, desc);
+ close (desc);
+ return linenums_changed;
+}
+
+/* Print text describing the full name of the source file S
+ and the line number LINE and its corresponding character position.
+ The text starts with two Ctrl-z so that the Emacs-GDB interface
+ can easily find it.
+
+ MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
+
+ Return 1 if successful, 0 if could not find the file. */
+
+int
+identify_source_line (s, line, mid_statement)
+ struct symtab *s;
+ int line;
+ int mid_statement;
+{
+ if (s->line_charpos == 0)
+ get_filename_and_charpos (s, line, 0);
+ if (s->fullname == 0)
+ return 0;
+ printf ("\032\032%s:%d:%d:%s:0x%x\n", s->fullname,
+ line, s->line_charpos[line - 1],
+ mid_statement ? "middle" : "beg",
+ get_frame_pc (get_current_frame()));
+ current_source_line = line;
+ first_line_listed = line;
+ last_line_listed = line;
+ current_source_symtab = s;
+ return 1;
+}
+
+/* Print source lines from the file of symtab S,
+ starting with line number LINE and stopping before line number STOPLINE. */
+
+void
+print_source_lines (s, line, stopline, noerror)
+ struct symtab *s;
+ int line, stopline;
+ int noerror;
+{
+ register int c;
+ register int desc;
+ register FILE *stream;
+ int nlines = stopline - line;
+
+ desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
+ if (desc < 0)
+ {
+ extern int errno;
+ if (noerror && line + 1 == stopline)
+ {
+ /* can't find the file - tell user where we are anyway */
+ current_source_symtab = s;
+ current_source_line = line;
+ first_line_listed = line;
+ last_line_listed = line;
+ printf_filtered ("%d\t(%s)\n", current_source_line++, s->filename);
+ }
+ else
+ {
+ if (! noerror)
+ perror_with_name (s->filename);
+ print_sys_errmsg (s->filename, errno);
+ }
+ return;
+ }
+
+ if (s->line_charpos == 0)
+ find_source_lines (s, desc);
+
+ if (line < 1 || line > s->nlines)
+ {
+ close (desc);
+ error ("Line number %d out of range; %s has %d lines.",
+ line, s->filename, s->nlines);
+ }
+
+ if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (s->filename);
+ }
+
+ current_source_symtab = s;
+ current_source_line = line;
+ first_line_listed = line;
+
+ stream = fdopen (desc, "r");
+ clearerr (stream);
+
+ while (nlines-- > 0)
+ {
+ c = fgetc (stream);
+ if (c == EOF) break;
+ last_line_listed = current_source_line;
+ printf_filtered ("%d\t", current_source_line++);
+ do
+ {
+ if (c < 040 && c != '\t' && c != '\n')
+ printf_filtered ("^%c", c + 0100);
+ else if (c == 0177)
+ printf_filtered ("^?");
+ else
+ printf_filtered ("%c", c);
+ } while (c != '\n' && (c = fgetc (stream)) >= 0);
+ }
+
+ fclose (stream);
+}
+
+
+
+/*
+ C++
+ Print a list of files and line numbers which a user may choose from
+ in order to list a function which was specified ambiguously
+ (as with `list classname::overloadedfuncname', for example).
+ The vector in SALS provides the filenames and line numbers.
+ */
+static void
+ambiguous_line_spec (sals)
+ struct symtabs_and_lines *sals;
+{
+ int i;
+
+ for (i = 0; i < sals->nelts; ++i)
+ printf("file: \"%s\", line number: %d\n",
+ sals->sals[i].symtab->filename, sals->sals[i].line);
+}
+
+
+static void
+file_command(arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct symbol *sym;
+ char *arg1;
+ int linenum_beg = 0;
+ char *p;
+
+ if (symtab_list == 0 && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+
+ /* Pull in a current source symtab if necessary */
+ if (arg == 0 || arg[0] == 0) {
+ if (current_source_symtab == 0)
+ select_source_symtab(0);
+ else
+ printf("%s\n", current_source_symtab->filename);
+ return;
+ }
+ arg1 = arg;
+ sals = decode_line_1 (&arg1, 0, 0, 0);
+
+ if (! sals.nelts)
+ return; /* C++ */
+
+ if (sals.nelts > 1)
+ {
+ ambiguous_line_spec (&sals);
+ free (sals.sals);
+ return;
+ }
+
+ sal = sals.sals[0];
+ free (sals.sals);
+
+ /* Record whether the BEG arg is all digits. */
+
+ for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; ++p)
+ ;
+ linenum_beg = (p == arg1);
+
+ /* if line was specified by address,
+ print exactly which line, and which file.
+ In this case, sal.symtab == 0 means address is outside
+ of all known source files, not that user failed to give a filename. */
+ if (*arg == '*')
+ {
+ if (sal.symtab == 0)
+ error ("No source file for address 0x%x.", sal.pc);
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ printf ("0x%x is in %s (%s, line %d).\n",
+ sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
+ else
+ printf ("0x%x is in %s, line %d.\n",
+ sal.pc, sal.symtab->filename, sal.line);
+ }
+
+ /* If line was not specified by just a line number,
+ and it does not imply a symtab, it must be an undebuggable symbol
+ which means no source code. */
+
+ if (sal.symtab == 0)
+ {
+ if (! linenum_beg)
+ error ("No line number known for %s.", arg);
+ else
+ error ("No default source file yet. Do \"help list\".");
+ }
+ else
+ {
+ current_source_symtab = sal.symtab;
+ current_source_line = sal.line;
+ first_line_listed = sal.line;
+ }
+}
+
+#define PUSH_STACK_SIZE 32
+static struct {
+ struct symtab *symtab;
+ int line;
+} push_stack[PUSH_STACK_SIZE];
+
+static unsigned int push_stack_ptr;
+
+static void
+push_to_file_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtab *cursym = current_source_symtab;
+ int curline = current_source_line;
+ register unsigned int i;
+
+ file_command(arg, from_tty);
+
+ /* if we got back, command was successful */
+ i = push_stack_ptr;
+ push_stack[i].symtab = cursym;
+ push_stack[i].line = curline;
+ push_stack_ptr = (i + 1) & (PUSH_STACK_SIZE - 1);
+}
+
+static void
+pop_file_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register unsigned int i = push_stack_ptr;
+
+ /* if there's something on the stack, pop it & clear the slot. */
+ i = (i + (PUSH_STACK_SIZE - 1)) & (PUSH_STACK_SIZE - 1);
+ if (push_stack[i].symtab) {
+ current_source_symtab = push_stack[i].symtab;
+ first_line_listed = current_source_line = push_stack[i].line;
+ push_stack[i].symtab = NULL;
+ push_stack_ptr = i;
+ }
+}
+
+
+static void
+list_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtabs_and_lines sals, sals_end;
+ struct symtab_and_line sal, sal_end;
+ struct symbol *sym;
+ char *arg1;
+ int no_end = 1;
+ int dummy_end = 0;
+ int dummy_beg = 0;
+ int linenum_beg = 0;
+ char *p;
+
+ if (symtab_list == 0 && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+
+ /* Pull in a current source symtab if necessary */
+ if (current_source_symtab == 0 &&
+ (arg == 0 || arg[0] == '+' || arg[0] == '-'))
+ select_source_symtab (0);
+
+ /* "l" or "l +" lists next ten lines. */
+
+ if (arg == 0 || !strcmp (arg, "+"))
+ {
+ if (current_source_symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ print_source_lines (current_source_symtab, current_source_line,
+ current_source_line + 10, 0);
+ return;
+ }
+
+ /* "l -" lists previous ten lines, the ones before the ten just listed. */
+ if (!strcmp (arg, "-"))
+ {
+ if (current_source_symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ print_source_lines (current_source_symtab,
+ max (first_line_listed - 10, 1),
+ first_line_listed, 0);
+ return;
+ }
+
+ /* Now if there is only one argument, decode it in SAL
+ and set NO_END.
+ If there are two arguments, decode them in SAL and SAL_END
+ and clear NO_END; however, if one of the arguments is blank,
+ set DUMMY_BEG or DUMMY_END to record that fact. */
+
+ arg1 = arg;
+ if (*arg1 == ',')
+ dummy_beg = 1;
+ else
+ {
+ sals = decode_line_1 (&arg1, 0, 0, 0);
+
+ if (! sals.nelts) return; /* C++ */
+ if (sals.nelts > 1)
+ {
+ ambiguous_line_spec (&sals);
+ free (sals.sals);
+ return;
+ }
+
+ sal = sals.sals[0];
+ free (sals.sals);
+ }
+
+ /* Record whether the BEG arg is all digits. */
+
+ for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
+ linenum_beg = (p == arg1);
+
+ while (*arg1 == ' ' || *arg1 == '\t')
+ arg1++;
+ if (*arg1 == ',')
+ {
+ no_end = 0;
+ arg1++;
+ while (*arg1 == ' ' || *arg1 == '\t')
+ arg1++;
+ if (*arg1 == 0)
+ dummy_end = 1;
+ else
+ {
+ if (dummy_beg)
+ sals_end = decode_line_1 (&arg1, 0, 0, 0);
+ else
+ sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
+ if (sals_end.nelts == 0)
+ return;
+ if (sals_end.nelts > 1)
+ {
+ ambiguous_line_spec (&sals_end);
+ free (sals_end.sals);
+ return;
+ }
+ sal_end = sals_end.sals[0];
+ free (sals_end.sals);
+ }
+ }
+
+ if (*arg1)
+ error ("Junk at end of line specification.");
+
+ if (!no_end && !dummy_beg && !dummy_end
+ && sal.symtab != sal_end.symtab)
+ error ("Specified start and end are in different files.");
+ if (dummy_beg && dummy_end)
+ error ("Two empty args do not say what lines to list.");
+
+ /* if line was specified by address,
+ first print exactly which line, and which file.
+ In this case, sal.symtab == 0 means address is outside
+ of all known source files, not that user failed to give a filename. */
+ if (*arg == '*')
+ {
+ if (sal.symtab == 0)
+ error ("No source file for address 0x%x.", sal.pc);
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ printf ("0x%x is in %s (%s, line %d).\n",
+ sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
+ else
+ printf ("0x%x is in %s, line %d.\n",
+ sal.pc, sal.symtab->filename, sal.line);
+ }
+
+ /* If line was not specified by just a line number,
+ and it does not imply a symtab, it must be an undebuggable symbol
+ which means no source code. */
+
+ if (! linenum_beg && sal.symtab == 0)
+ error ("No line number known for %s.", arg);
+
+ /* If this command is repeated with RET,
+ turn it into the no-arg variant. */
+
+ if (from_tty)
+ *arg = 0;
+
+ if (dummy_beg && sal_end.symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ if (dummy_beg)
+ print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1),
+ sal_end.line + 1, 0);
+ else if (sal.symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ else if (no_end)
+ print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5, 0);
+ else
+ print_source_lines (sal.symtab, sal.line,
+ dummy_end ? sal.line + 10 : sal_end.line + 1,
+ 0);
+}
+
+/* Print info on range of pc's in a specified line. */
+
+static void
+line_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ int start_pc, end_pc;
+ int i;
+
+ if (arg == 0)
+ {
+ sal.symtab = current_source_symtab;
+ sal.line = last_line_listed;
+ sals.nelts = 1;
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ sals.sals[0] = sal;
+ }
+ else
+ {
+ sals = decode_line_spec_1 (arg, 0);
+
+ /* If this command is repeated with RET,
+ turn it into the no-arg variant. */
+ if (from_tty)
+ *arg = 0;
+ }
+
+ /* C++ More than one line may have been specified, as when the user
+ specifies an overloaded function name. Print info on them all. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ sal = sals.sals[i];
+
+ if (sal.symtab == 0)
+ error ("No source file specified.");
+
+ if (sal.line > 0
+ && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
+ {
+ if (start_pc == end_pc)
+ printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n",
+ sal.line, sal.symtab->filename, start_pc);
+ else
+ printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n",
+ sal.line, sal.symtab->filename, start_pc, end_pc);
+ /* x/i should display this line's code. */
+ set_next_address (start_pc);
+ /* Repeating "info line" should do the following line. */
+ last_line_listed = sal.line + 1;
+ }
+ else
+ printf ("Line number %d is out of range for \"%s\".\n",
+ sal.line, sal.symtab->filename);
+ }
+}
+
+/* Commands to search the source file for a regexp. */
+
+static void
+forward_search_command (regex, from_tty)
+ char *regex;
+{
+ register int c;
+ register int desc;
+ register FILE *stream;
+ int line = last_line_listed + 1;
+ char *msg;
+
+ msg = (char *) re_comp (regex);
+ if (msg)
+ error (msg);
+
+ if (current_source_symtab == 0)
+ select_source_symtab (0);
+
+ /* Search from last_line_listed+1 in current_source_symtab */
+
+ desc = openp (source_path, 0, current_source_symtab->filename,
+ O_RDONLY, 0, &current_source_symtab->fullname);
+ if (desc < 0)
+ perror_with_name (current_source_symtab->filename);
+
+ if (current_source_symtab->line_charpos == 0)
+ find_source_lines (current_source_symtab, desc);
+
+ if (line < 1 || line > current_source_symtab->nlines)
+ {
+ close (desc);
+ error ("Expression not found");
+ }
+
+ if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (current_source_symtab->filename);
+ }
+
+ stream = fdopen (desc, "r");
+ clearerr (stream);
+ while (1) {
+ char buf[4096]; /* Should be reasonable??? */
+ register char *p = buf;
+
+ c = fgetc (stream);
+ if (c == EOF)
+ break;
+ do {
+ *p++ = c;
+ } while (c != '\n' && (c = fgetc (stream)) >= 0);
+
+ /* we now have a source line in buf, null terminate and match */
+ *p = 0;
+ if (re_exec (buf) > 0)
+ {
+ /* Match! */
+ fclose (stream);
+ print_source_lines (current_source_symtab,
+ line, line+1, 0);
+ current_source_line = max (line - 5, 1);
+ return;
+ }
+ line++;
+ }
+
+ printf ("Expression not found\n");
+ fclose (stream);
+}
+
+static void
+reverse_search_command (regex, from_tty)
+ char *regex;
+{
+ register int c;
+ register int desc;
+ register FILE *stream;
+ int line = last_line_listed - 1;
+ char *msg;
+
+ msg = (char *) re_comp (regex);
+ if (msg)
+ error (msg);
+
+ if (current_source_symtab == 0)
+ select_source_symtab (0);
+
+ /* Search from last_line_listed-1 in current_source_symtab */
+
+ desc = openp (source_path, 0, current_source_symtab->filename,
+ O_RDONLY, 0, &current_source_symtab->fullname);
+ if (desc < 0)
+ perror_with_name (current_source_symtab->filename);
+
+ if (current_source_symtab->line_charpos == 0)
+ find_source_lines (current_source_symtab, desc);
+
+ if (line < 1 || line > current_source_symtab->nlines)
+ {
+ close (desc);
+ error ("Expression not found");
+ }
+
+ if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (current_source_symtab->filename);
+ }
+
+ stream = fdopen (desc, "r");
+ clearerr (stream);
+ while (1)
+ {
+ char buf[4096]; /* Should be reasonable??? */
+ register char *p = buf;
+
+ c = fgetc (stream);
+ if (c == EOF)
+ break;
+ do {
+ *p++ = c;
+ } while (c != '\n' && (c = fgetc (stream)) >= 0);
+
+ /* We now have a source line in buf; null terminate and match. */
+ *p = 0;
+ if (re_exec (buf) > 0)
+ {
+ /* Match! */
+ fclose (stream);
+ print_source_lines (current_source_symtab,
+ line, line+1, 0);
+ current_source_line = max (line - 5, 1);
+ return;
+ }
+ line--;
+ if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
+ {
+ fclose (stream);
+ perror_with_name (current_source_symtab->filename);
+ }
+ }
+
+ printf ("Expression not found\n");
+ fclose (stream);
+ return;
+}
+
+void
+_initialize_source ()
+{
+ current_source_symtab = 0;
+ init_source_path ();
+
+ add_com ("directory", class_files, directory_command,
+ "Add directory DIR to end of search path for source files.\n\
+With no argument, reset the search path to just the working directory\n\
+and forget cached info on line positions in source files.");
+
+ add_info ("directories", directories_info,
+ "Current search path for finding source files.");
+
+ add_info ("line", line_info,
+ "Core addresses of the code for a source line.\n\
+Line can be specified as\n\
+ LINENUM, to list around that line in current file,\n\
+ FILE:LINENUM, to list around that line in that file,\n\
+ FUNCTION, to list around beginning of that function,\n\
+ FILE:FUNCTION, to distinguish among like-named static functions.\n\
+Default is to describe the last source line that was listed.\n\n\
+This sets the default address for \"x\" to the line's first instruction\n\
+so that \"x/i\" suffices to start examining the machine code.\n\
+The address is also stored as the value of \"$_\".");
+
+ add_com ("forward-search", class_files, forward_search_command,
+ "Search for regular expression (see regex(3)) from last line listed.");
+ add_com_alias ("search", "forward-search", class_files, 0);
+
+ add_com ("reverse-search", class_files, reverse_search_command,
+ "Search backward for regular expression (see regex(3)) from last line listed.");
+
+ add_com ("list", class_files, list_command,
+ "List specified function or line.\n\
+With no argument, lists ten more lines after or around previous listing.\n\
+\"list -\" lists the ten lines before a previous ten-line listing.\n\
+One argument specifies a line, and ten lines are listed around that line.\n\
+Two arguments with comma between specify starting and ending lines to list.\n\
+Lines can be specified in these ways:\n\
+ LINENUM, to list around that line in current file,\n\
+ FILE:LINENUM, to list around that line in that file,\n\
+ FUNCTION, to list around beginning of that function,\n\
+ FILE:FUNCTION, to distinguish among like-named static functions.\n\
+ *ADDRESS, to list around the line containing that address.\n\
+With two args if one is empty it stands for ten lines away from the other arg.");
+ add_com ("file", class_files, file_command,
+ "Select current file, function and line for display or list.\n\
+Specification can have the form:\n\
+ LINENUM, to select that line in current file,\n\
+ FILE:LINENUM, to select that line in that file,\n\
+ FUNCTION, to select beginning of that function,\n\
+ FILE:FUNCTION, to distinguish among like-named static functions.\n\
+ *ADDRESS, to select the line containing that address.");
+ add_com ("push-to-file", class_files, push_to_file_command,
+ "Like \"file\" command but remembers current file & line on a stack.\n\
+Can later return to current file with \"pop-file\" command.\n\
+Up to 32 file positions can be pushed on stack.");
+ add_com ("pop-file", class_files, pop_file_command,
+ "Pops back to file position saved by most recent \"push-to-file\".\n\
+If everything has been popped from stack, command does nothing.");
+}
+
diff --git a/gnu/usr.bin/kgdb/stab.def b/gnu/usr.bin/kgdb/stab.def
new file mode 100644
index 000000000000..b81cda4bdc31
--- /dev/null
+++ b/gnu/usr.bin/kgdb/stab.def
@@ -0,0 +1,115 @@
+/* Table of DBX symbol codes for the GNU system.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Global variable. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_GSYM, 0x20, "GSYM")
+
+/* Function name for BSD Fortran. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_FNAME, 0x22, "FNAME")
+
+/* Function name or text-segment variable for C. Value is its address.
+ Desc is supposedly starting line number, but GCC doesn't set it
+ and DBX seems not to miss it. */
+__define_stab (N_FUN, 0x24, "FUN")
+
+/* Data-segment variable with internal linkage. Value is its address. */
+__define_stab (N_STSYM, 0x26, "STSYM")
+
+/* BSS-segment variable with internal linkage. Value is its address. */
+__define_stab (N_LCSYM, 0x28, "LCSYM")
+
+/* Name of main routine. Only the name is significant.
+ This is not used in C. */
+__define_stab (N_MAIN, 0x2a, "MAIN")
+
+/* Register variable. Value is number of register. */
+__define_stab (N_RSYM, 0x40, "RSYM")
+
+/* Structure or union element. Value is offset in the structure. */
+__define_stab (N_SSYM, 0x60, "SSYM")
+
+/* Parameter variable. Value is offset from argument pointer.
+ (On most machines the argument pointer is the same as the frame pointer. */
+__define_stab (N_PSYM, 0xa0, "PSYM")
+
+/* Automatic variable in the stack. Value is offset from frame pointer.
+ Also used for type descriptions. */
+__define_stab (N_LSYM, 0x80, "LSYM")
+
+/* Alternate entry point. Value is its address. */
+__define_stab (N_ENTRY, 0xa4, "ENTRY")
+
+/* Name of main source file.
+ Value is starting text address of the compilation. */
+__define_stab (N_SO, 0x64, "SO")
+
+/* Name of sub-source file.
+ Value is starting text address of the compilation. */
+__define_stab (N_SOL, 0x84, "SOL")
+
+/* Line number in text segment. Desc is the line number;
+ value is corresponding address. */
+__define_stab (N_SLINE, 0x44, "SLINE")
+/* Similar, for data segment. */
+__define_stab (N_DSLINE, 0x46, "DSLINE")
+/* Similar, for bss segment. */
+__define_stab (N_BSLINE, 0x48, "BSLINE")
+
+/* Beginning of an include file. Only Sun uses this.
+ In an object file, only the name is significant.
+ The Sun linker puts data into some of the other fields. */
+__define_stab (N_BINCL, 0x82, "BINCL")
+/* End of an include file. No name.
+ These two act as brackets around the file's output.
+ In an object file, there is no significant data in this entry.
+ The Sun linker puts data into some of the fields. */
+__define_stab (N_EINCL, 0xa2, "EINCL")
+/* Place holder for deleted include file.
+ This appears only in output from the Sun linker. */
+__define_stab (N_EXCL, 0xc2, "EXCL")
+
+/* Beginning of lexical block.
+ The desc is the nesting level in lexical blocks.
+ The value is the address of the start of the text for the block.
+ The variables declared inside the block *precede* the N_LBRAC symbol. */
+__define_stab (N_LBRAC, 0xc0, "LBRAC")
+/* End of a lexical block. Desc matches the N_LBRAC's desc.
+ The value is the address of the end of the text for the block. */
+__define_stab (N_RBRAC, 0xe0, "RBRAC")
+
+/* Begin named common block. Only the name is significant. */
+__define_stab (N_BCOMM, 0xe2, "BCOMM")
+/* Begin named common block. Only the name is significant
+ (and it should match the N_BCOMM). */
+__define_stab (N_ECOMM, 0xe4, "ECOMM")
+/* End common (local name): value is address.
+ I'm not sure how this is used. */
+__define_stab (N_ECOML, 0xe8, "ECOML")
+/* Second symbol entry containing a length-value for the preceding entry.
+ The value is the length. */
+__define_stab (N_LENG, 0xfe, "LENG")
+
+/* Global symbol in Pascal.
+ Supposedly the value is its line number; I'm skeptical. */
+__define_stab (N_PC, 0x30, "PC")
+
+/* Modula-2 compilation unit. Can someone say what info it contains? */
+__define_stab (N_M2C, 0x42, "M2C")
+/* Modula-2 scope information. Can someone say what info it contains? */
+__define_stab (N_SCOPE, 0xc4, "SCOPE")
diff --git a/gnu/usr.bin/kgdb/stack.c b/gnu/usr.bin/kgdb/stack.c
new file mode 100644
index 000000000000..91218aae3656
--- /dev/null
+++ b/gnu/usr.bin/kgdb/stack.c
@@ -0,0 +1,960 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)stack.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Print and select stack frames for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* modified by rjc Thu Nov 1 16:46:57 1990, fixed return_command so that
+ it can return values, it still has problems when running on pmax,
+ cannot write register 65 */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "value.h"
+
+
+/* Thie "selected" stack frame is used by default for local and arg access.
+ May be zero, for no selected frame. */
+
+FRAME selected_frame;
+
+/* Level of the selected frame:
+ 0 for innermost, 1 for its caller, ...
+ or -1 for frame specified by address with no defined level. */
+
+int selected_frame_level;
+
+/* Nonzero means print the full filename and linenumber
+ when a frame is printed, and do so in a format programs can parse. */
+
+int frame_file_full_name = 0;
+
+static void select_calling_frame ();
+
+void print_frame_info ();
+
+/* Print a stack frame briefly. FRAME should be the frame id
+ and LEVEL should be its level in the stack (or -1 for level not defined).
+ This prints the level, the function executing, the arguments,
+ and the file name and line number.
+ If the pc is not at the beginning of the source line,
+ the actual pc is printed at the beginning.
+
+ If SOURCE is 1, print the source line as well.
+ If SOURCE is -1, print ONLY the source line. */
+
+static void
+print_stack_frame (frame, level, source)
+ FRAME frame;
+ int level;
+ int source;
+{
+ struct frame_info *fi;
+
+ fi = get_frame_info (frame);
+
+ print_frame_info (fi, level, source, 1);
+}
+
+/* Flag which will indicate when the frame has been changed
+ by and "up" or "down" command. */
+static int frame_changed;
+
+void
+print_frame_info (fi, level, source, args)
+ struct frame_info *fi;
+ register int level;
+ int source;
+ int args;
+{
+ struct symtab_and_line sal;
+ struct symbol *func;
+ register char *funname = 0;
+ int numargs;
+ struct partial_symtab *pst;
+
+ /* Don't give very much information if we haven't readin the
+ symbol table yet. */
+ pst = find_pc_psymtab (fi->pc);
+ if (pst && !pst->readin)
+ {
+ /* Abbreviated information. */
+ char *fname;
+
+ if (!find_pc_partial_function (fi->pc, &fname, 0))
+ fname = "??";
+
+ printf_filtered ("#%-2d ", level);
+ printf_filtered ("0x%x in ", fi->pc);
+
+ fputs_demangled(fname, stdout, -1);
+ fputs_filtered(" (...)\n", stdout);
+
+ return;
+ }
+
+ sal = find_pc_line (fi->pc, fi->next_frame);
+ func = find_pc_function (fi->pc);
+ if (func)
+ {
+ /* In certain pathological cases, the symtabs give the wrong
+ function (when we are in the first function in a file which
+ is compiled without debugging symbols, the previous function
+ is compiled with debugging symbols, and the "foo.o" symbol
+ that is supposed to tell us where the file with debugging symbols
+ ends has been truncated by ar because it is longer than 15
+ characters).
+
+ So look in the misc_function_vector as well, and if it comes
+ up with a larger address for the function use that instead.
+ I don't think this can ever cause any problems;
+ there shouldn't be any
+ misc_function_vector symbols in the middle of a function. */
+ int misc_index = find_pc_misc_function (fi->pc);
+ if (misc_index >= 0
+ && (misc_function_vector[misc_index].address
+ > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
+ {
+ /* In this case we have no way of knowing the source file
+ and line number, so don't print them. */
+ sal.symtab = 0;
+ /* We also don't know anything about the function besides
+ its address and name. */
+ func = 0;
+ funname = misc_function_vector[misc_index].name;
+ }
+ else
+ funname = SYMBOL_NAME (func);
+ }
+ else
+ {
+ register int misc_index = find_pc_misc_function (fi->pc);
+ if (misc_index >= 0)
+ funname = misc_function_vector[misc_index].name;
+ }
+
+ if (frame_changed || source >= 0 || !sal.symtab)
+ {
+ if (level >= 0)
+ printf_filtered ("#%-2d ", level);
+ else if (frame_changed)
+ printf ("#%-2d ", 0);
+ if (fi->pc != sal.pc || !sal.symtab)
+ printf_filtered ("0x%x in ", fi->pc);
+ fputs_demangled(funname ? funname : "??", stdout, -1);
+ printf_filtered(" (");
+ if (args)
+ {
+ if (func)
+ numargs = -1;
+ else
+ FRAME_NUM_ARGS (numargs, fi);
+
+ print_frame_args (func, fi, numargs, stdout);
+ }
+ printf_filtered (")");
+ if (sal.symtab)
+ printf_filtered (" (%s line %d)", sal.symtab->filename, sal.line);
+ printf_filtered ("\n");
+ }
+
+ if ((frame_changed || source != 0) && sal.symtab)
+ {
+ int done = 0;
+ int mid_statement = source < 0 && fi->pc != sal.pc;
+ if (frame_file_full_name)
+ done = identify_source_line (sal.symtab, sal.line, mid_statement);
+ if (!done)
+ {
+ if (mid_statement)
+ printf_filtered ("0x%x\t", fi->pc);
+ print_source_lines (sal.symtab, sal.line, sal.line + 1, 1);
+ }
+ current_source_line = max (sal.line - 5, 1);
+ }
+ frame_changed = 0;
+ if (source != 0)
+ set_default_breakpoint (1, fi->pc, sal.symtab, sal.line);
+
+ fflush (stdout);
+}
+
+/* Call here to print info on selected frame, after a trap. */
+
+void
+print_sel_frame (just_source)
+ int just_source;
+{
+ print_stack_frame (selected_frame, -1, just_source ? -1 : 1);
+}
+
+/* Print info on the selected frame, including level number
+ but not source. */
+
+void
+print_selected_frame ()
+{
+ print_stack_frame (selected_frame, selected_frame_level, 0);
+}
+
+void flush_cached_frames ();
+
+#ifdef FRAME_SPECIFICATION_DYADIC
+extern FRAME setup_arbitrary_frame ();
+#endif
+
+/*
+ * Read a frame specification in whatever the appropriate format is.
+ */
+static FRAME
+parse_frame_specification (frame_exp)
+ char *frame_exp;
+{
+ int numargs = 0;
+ int arg1, arg2;
+
+ if (frame_exp)
+ {
+ char *addr_string, *p;
+ struct cleanup *tmp_cleanup;
+ struct frame_info *fci;
+
+ while (*frame_exp == ' ') frame_exp++;
+ for (p = frame_exp; *p && *p != ' '; p++)
+ ;
+
+ if (*frame_exp)
+ {
+ numargs = 1;
+ addr_string = savestring(frame_exp, p - frame_exp);
+
+ {
+ tmp_cleanup = make_cleanup (free, addr_string);
+ arg1 = parse_and_eval_address (addr_string);
+ do_cleanups (tmp_cleanup);
+ }
+
+ while (*p == ' ') p++;
+
+ if (*p)
+ {
+ numargs = 2;
+ arg2 = parse_and_eval_address (p);
+ }
+ }
+ }
+
+ switch (numargs)
+ {
+ case 0:
+ return selected_frame;
+ /* NOTREACHED */
+ case 1:
+ {
+ int level = arg1;
+ FRAME fid = find_relative_frame (get_current_frame (), &level);
+ FRAME tfid;
+
+ if (level == 0)
+ /* find_relative_frame was successful */
+ return fid;
+
+ /* If (s)he specifies the frame with an address, he deserves what
+ (s)he gets. Still, give the highest one that matches. */
+
+ for (fid = get_current_frame ();
+ fid && FRAME_FP (fid) != arg1;
+ fid = get_prev_frame (fid))
+ ;
+
+ if (fid)
+ while ((tfid = get_prev_frame (fid)) &&
+ (FRAME_FP (tfid) == arg1))
+ fid = tfid;
+
+#ifdef FRAME_SPECIFICATION_DYADIC
+ if (!fid)
+ error ("Incorrect number of args in frame specification");
+
+ return fid;
+#else
+ return create_new_frame (arg1, 0);
+#endif
+ }
+ /* NOTREACHED */
+ case 2:
+ /* Must be addresses */
+#ifndef FRAME_SPECIFICATION_DYADIC
+ error ("Incorrect number of args in frame specification");
+#else
+ return setup_arbitrary_frame (arg1, arg2);
+#endif
+ /* NOTREACHED */
+ }
+ fatal ("Internal: Error in parsing in parse_frame_specification");
+ /* NOTREACHED */
+}
+
+/* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
+ that if it is unsure about the answer, it returns Frame_unknown
+ instead of guessing (this happens on the VAX, for example).
+
+ On most machines, we never have to guess about the args address,
+ so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */
+#if !defined (FRAME_ARGS_ADDRESS_CORRECT)
+#define FRAME_ARGS_ADDRESS_CORRECT FRAME_ARGS_ADDRESS
+#endif
+
+/* Print verbosely the selected frame or the frame at address ADDR.
+ This means absolutely all information in the frame is printed. */
+
+static void
+frame_info (addr_exp)
+ char *addr_exp;
+{
+ FRAME frame;
+ struct frame_info *fi;
+ struct frame_saved_regs fsr;
+ struct symtab_and_line sal;
+ struct symbol *func;
+ FRAME calling_frame;
+ int i, count;
+ char *funname = 0;
+
+ if (!(have_inferior_p () || have_core_file_p ()))
+ error ("No inferior or core file.");
+
+ frame = parse_frame_specification (addr_exp);
+ if (!frame)
+ error ("Invalid frame specified.");
+
+ fi = get_frame_info (frame);
+ get_frame_saved_regs (fi, &fsr);
+ sal = find_pc_line (fi->pc, fi->next_frame);
+ func = get_frame_function (frame);
+ if (func)
+ funname = SYMBOL_NAME (func);
+ else
+ {
+ register int misc_index = find_pc_misc_function (fi->pc);
+ if (misc_index >= 0)
+ funname = misc_function_vector[misc_index].name;
+ }
+ calling_frame = get_prev_frame (frame);
+
+ if (!addr_exp && selected_frame_level >= 0)
+ printf ("Stack level %d, frame at 0x%x:\n pc = 0x%x",
+ selected_frame_level, FRAME_FP(frame), fi->pc);
+ else
+ printf ("Stack frame at 0x%x:\n pc = 0x%x",
+ FRAME_FP(frame), fi->pc);
+
+ if (funname)
+ printf (" in %s", funname);
+ if (sal.symtab)
+ printf (" (%s line %d)", sal.symtab->filename, sal.line);
+ printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame));
+ if (calling_frame)
+ printf (" called by frame at 0x%x", FRAME_FP (calling_frame));
+ if (fi->next_frame && calling_frame)
+ printf (",");
+ if (fi->next_frame)
+ printf (" caller of frame at 0x%x", fi->next_frame);
+ if (fi->next_frame || calling_frame)
+ printf ("\n");
+
+ {
+ /* Address of the argument list for this frame, or Frame_unknown. */
+ CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi);
+ /* Number of args for this frame, or -1 if unknown. */
+ int numargs;
+
+ if (arg_list != Frame_unknown)
+ {
+ printf (" Arglist at 0x%x,", arg_list);
+
+ FRAME_NUM_ARGS (numargs, fi);
+ if (numargs < 0)
+ printf (" args: ");
+ else if (numargs == 0)
+ printf (" no args.");
+ else if (numargs == 1)
+ printf (" 1 arg: ");
+ else
+ printf (" %d args: ", numargs);
+ print_frame_args (func, fi, numargs, stdout);
+ printf ("\n");
+ }
+ }
+
+ /* The sp is special; what's returned isn't the save address, but
+ actually the value of the previous frame's sp. */
+ printf (" Previous frame's sp is 0x%x\n", fsr.regs[SP_REGNUM]);
+ count = 0;
+ for (i = 0; i < NUM_REGS; i++)
+ if (fsr.regs[i] && i != SP_REGNUM)
+ {
+ if (count % 4 != 0)
+ printf (", ");
+ else
+ {
+ if (count == 0)
+ printf (" Saved registers:");
+ printf ("\n ");
+ }
+ printf ("%s at 0x%x", reg_names[i], fsr.regs[i]);
+ count++;
+ }
+ if (count)
+ printf ("\n");
+}
+
+#if 0
+/* Set a limit on the number of frames printed by default in a
+ backtrace. */
+
+static int backtrace_limit;
+
+static void
+set_backtrace_limit_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ int count = parse_and_eval_address (count_exp);
+
+ if (count < 0)
+ error ("Negative argument not meaningful as backtrace limit.");
+
+ backtrace_limit = count;
+}
+
+static void
+backtrace_limit_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (arg)
+ error ("\"Info backtrace-limit\" takes no arguments.");
+
+ printf ("Backtrace limit: %d.\n", backtrace_limit);
+}
+#endif
+
+/* Print briefly all stack frames or just the innermost COUNT frames. */
+
+static void
+backtrace_command (count_exp)
+ char *count_exp;
+{
+ struct frame_info *fi;
+ register int count;
+ register FRAME frame;
+ register int i;
+ register FRAME trailing;
+ register int trailing_level;
+
+ /* The following code must do two things. First, it must
+ set the variable TRAILING to the frame from which we should start
+ printing. Second, it must set the variable count to the number
+ of frames which we should print, or -1 if all of them. */
+ trailing = get_current_frame ();
+ trailing_level = 0;
+ if (count_exp)
+ {
+ count = parse_and_eval_address (count_exp);
+ if (count < 0)
+ {
+ FRAME current;
+
+ count = -count;
+
+ current = trailing;
+ while (current && count--)
+ current = get_prev_frame (current);
+
+ /* Will stop when CURRENT reaches the top of the stack. TRAILING
+ will be COUNT below it. */
+ while (current)
+ {
+ trailing = get_prev_frame (trailing);
+ current = get_prev_frame (current);
+ trailing_level++;
+ }
+
+ count = -1;
+ }
+ }
+ else
+ count = -1;
+
+ for (i = 0, frame = trailing;
+ frame && count--;
+ i++, frame = get_prev_frame (frame))
+ {
+ QUIT;
+ fi = get_frame_info (frame);
+ print_frame_info (fi, trailing_level + i, 0, 1);
+ }
+
+ /* If we've stopped before the end, mention that. */
+ if (frame)
+ printf_filtered ("(More stack frames follow...)\n");
+}
+
+/* Print the local variables of a block B active in FRAME.
+ Return 1 if any variables were printed; 0 otherwise. */
+
+static int
+print_block_frame_locals (b, frame, stream)
+ struct block *b;
+ register FRAME frame;
+ register FILE *stream;
+{
+ int nsyms;
+ register int i;
+ register struct symbol *sym;
+ register int values_printed = 0;
+
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ if (SYMBOL_CLASS (sym) == LOC_LOCAL
+ || SYMBOL_CLASS (sym) == LOC_REGISTER
+ || SYMBOL_CLASS (sym) == LOC_STATIC)
+ {
+ values_printed = 1;
+ fputs_filtered (SYMBOL_NAME (sym), stream);
+ fputs_filtered (" = ", stream);
+ print_variable_value (sym, frame, stream);
+ fprintf_filtered (stream, "\n");
+ fflush (stream);
+ }
+ }
+ return values_printed;
+}
+
+/* Print on STREAM all the local variables in frame FRAME,
+ including all the blocks active in that frame
+ at its current pc.
+
+ Returns 1 if the job was done,
+ or 0 if nothing was printed because we have no info
+ on the function running in FRAME. */
+
+static int
+print_frame_local_vars (frame, stream)
+ register FRAME frame;
+ register FILE *stream;
+{
+ register struct block *block = get_frame_block (frame);
+ register int values_printed = 0;
+
+ if (block == 0)
+ {
+ fprintf_filtered (stream, "No symbol table info available.\n");
+ fflush (stream);
+ return 0;
+ }
+
+ while (block != 0)
+ {
+ if (print_block_frame_locals (block, frame, stream))
+ values_printed = 1;
+ /* After handling the function's top-level block, stop.
+ Don't continue to its superblock, the block of
+ per-file symbols. */
+ if (BLOCK_FUNCTION (block))
+ break;
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ if (!values_printed)
+ {
+ fprintf_filtered (stream, "No locals.\n");
+ fflush (stream);
+ }
+
+ return 1;
+}
+
+static void
+locals_info ()
+{
+ if (!have_inferior_p () && !have_core_file_p ())
+ error ("No inferior or core file.");
+
+ print_frame_local_vars (selected_frame, stdout);
+}
+
+static int
+print_frame_arg_vars (frame, stream)
+ register FRAME frame;
+ register FILE *stream;
+{
+ struct symbol *func = get_frame_function (frame);
+ register struct block *b;
+ int nsyms;
+ register int i;
+ register struct symbol *sym;
+ register int values_printed = 0;
+
+ if (func == 0)
+ {
+ fprintf_filtered (stream, "No symbol table info available.\n");
+ fflush (stream);
+ return 0;
+ }
+
+ b = SYMBOL_BLOCK_VALUE (func);
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ if (SYMBOL_CLASS (sym) == LOC_ARG
+ || SYMBOL_CLASS (sym) == LOC_REF_ARG
+ || SYMBOL_CLASS (sym) == LOC_REGPARM)
+ {
+ values_printed = 1;
+ fputs_filtered (SYMBOL_NAME (sym), stream);
+ fputs_filtered (" = ", stream);
+ print_variable_value (sym, frame, stream);
+ fprintf_filtered (stream, "\n");
+ fflush (stream);
+ }
+ }
+
+ if (!values_printed)
+ {
+ fprintf_filtered (stream, "No arguments.\n");
+ fflush (stream);
+ }
+
+ return 1;
+}
+
+static void
+args_info ()
+{
+ if (!have_inferior_p () && !have_core_file_p ())
+ error ("No inferior or core file.");
+ print_frame_arg_vars (selected_frame, stdout);
+}
+
+/* Select frame FRAME, and note that its stack level is LEVEL.
+ LEVEL may be -1 if an actual level number is not known. */
+
+void
+select_frame (frame, level)
+ FRAME frame;
+ int level;
+{
+ selected_frame = frame;
+ selected_frame_level = level;
+ /* Ensure that symbols for this frame are readin. */
+ if (frame)
+ find_pc_symtab (get_frame_info (frame)->pc);
+}
+
+/* Store the selected frame and its level into *FRAMEP and *LEVELP. */
+
+void
+record_selected_frame (frameaddrp, levelp)
+ FRAME_ADDR *frameaddrp;
+ int *levelp;
+{
+ *frameaddrp = FRAME_FP (selected_frame);
+ *levelp = selected_frame_level;
+}
+
+/* Return the symbol-block in which the selected frame is executing.
+ Can return zero under various legitimate circumstances. */
+
+struct block *
+get_selected_block ()
+{
+ if (!have_inferior_p () && !have_core_file_p ())
+ return 0;
+
+ if (!selected_frame)
+ return get_current_block ();
+ return get_frame_block (selected_frame);
+}
+
+/* Find a frame a certain number of levels away from FRAME.
+ LEVEL_OFFSET_PTR points to an int containing the number of levels.
+ Positive means go to earlier frames (up); negative, the reverse.
+ The int that contains the number of levels is counted toward
+ zero as the frames for those levels are found.
+ If the top or bottom frame is reached, that frame is returned,
+ but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates
+ how much farther the original request asked to go. */
+
+FRAME
+find_relative_frame (frame, level_offset_ptr)
+ register FRAME frame;
+ register int* level_offset_ptr;
+{
+ register FRAME prev;
+ register FRAME frame1, frame2;
+
+ /* Going up is simple: just do get_prev_frame enough times
+ or until initial frame is reached. */
+ while (*level_offset_ptr > 0)
+ {
+ prev = get_prev_frame (frame);
+ if (prev == 0)
+ break;
+ (*level_offset_ptr)--;
+ frame = prev;
+ }
+ /* Going down could be done by iterating get_frame_info to
+ find the next frame, but that would be quadratic
+ since get_frame_info must scan all the way from the current frame.
+ The following algorithm is linear. */
+ if (*level_offset_ptr < 0)
+ {
+ /* First put frame1 at innermost frame
+ and frame2 N levels up from there. */
+ frame1 = get_current_frame ();
+ frame2 = frame1;
+ while (*level_offset_ptr < 0 && frame2 != frame)
+ {
+ frame2 = get_prev_frame (frame2);
+ (*level_offset_ptr) ++;
+ }
+ /* Then slide frame1 and frame2 up in synchrony
+ and when frame2 reaches our starting point
+ frame1 must be N levels down from there. */
+ while (frame2 != frame)
+ {
+ frame1 = get_prev_frame (frame1);
+ frame2 = get_prev_frame (frame2);
+ }
+ return frame1;
+ }
+ return frame;
+}
+
+/* The "frame" command. With no arg, print selected frame briefly.
+ With arg LEVEL_EXP, select the frame at level LEVEL if it is a
+ valid level. Otherwise, treat level_exp as an address expression
+ and print it. See parse_frame_specification for more info on proper
+ frame expressions. */
+
+static void
+frame_command (level_exp, from_tty)
+ char *level_exp;
+ int from_tty;
+{
+ register FRAME frame, frame1;
+ unsigned int level = 0;
+
+ if (!have_inferior_p () && ! have_core_file_p ())
+ error ("No inferior or core file.");
+
+ frame = parse_frame_specification (level_exp);
+
+ for (frame1 = get_prev_frame (0);
+ frame1 && frame1 != frame;
+ frame1 = get_prev_frame (frame1))
+ level++;
+
+ if (!frame1)
+ level = 0;
+
+ frame_changed = level;
+ select_frame (frame, level);
+
+ if (!from_tty)
+ return;
+
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* Select the frame up one or COUNT stack levels
+ from the previously selected frame, and print it briefly. */
+
+static void
+up_command (count_exp)
+ char *count_exp;
+{
+ register FRAME frame;
+ int count = 1, count1;
+ if (count_exp)
+ count = parse_and_eval_address (count_exp);
+ count1 = count;
+
+ if (!have_inferior_p () && !have_core_file_p ())
+ error ("No inferior or core file.");
+
+ frame = find_relative_frame (selected_frame, &count1);
+ if (count1 != 0 && count_exp == 0)
+ error ("Initial frame selected; you cannot go up.");
+ select_frame (frame, selected_frame_level + count - count1);
+
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ frame_changed++;
+}
+
+/* Select the frame down one or COUNT stack levels
+ from the previously selected frame, and print it briefly. */
+
+static void
+down_command (count_exp)
+ char *count_exp;
+{
+ register FRAME frame;
+ int count = -1, count1;
+ if (count_exp)
+ count = - parse_and_eval_address (count_exp);
+ count1 = count;
+
+ frame = find_relative_frame (selected_frame, &count1);
+ if (count1 != 0 && count_exp == 0)
+ error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
+ select_frame (frame, selected_frame_level + count - count1);
+
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ frame_changed--;
+}
+
+static void
+return_command (retval_exp, from_tty)
+ char *retval_exp;
+ int from_tty;
+{
+ value return_value;
+ struct symbol *thisfun = get_frame_function (selected_frame);
+ FRAME_ADDR selected_frame_addr = FRAME_FP (selected_frame);
+
+ /* If interactive, require confirmation. */
+
+ if (from_tty)
+ {
+ if (thisfun != 0)
+ {
+ if (!query ("Make %s return now? ", SYMBOL_NAME (thisfun)))
+ error ("Not confirmed.");
+ }
+ else
+ if (!query ("Make selected stack frame return now? "))
+ error ("Not confirmed.");
+ }
+
+ /* Do the real work. Pop until the specified frame is current. We
+ use this method because the selected_frame is not valid after
+ a POP_FRAME. Note that this will not work if the selected frame
+ shares it's fp with another frame. */
+
+ while (selected_frame_addr != FRAME_FP (get_current_frame()))
+ POP_FRAME;
+
+ /* get the return value while still in this frame */
+ if (retval_exp)
+ return_value = parse_and_eval (retval_exp);
+
+ /* Then pop that frame. */
+ POP_FRAME;
+
+ /* Store the return value if there was one */
+
+ if (retval_exp)
+ set_return_value (return_value);
+
+ /* If interactive, print the frame that is now current. */
+
+ if (from_tty)
+ frame_command ("0", 1);
+}
+
+extern struct cmd_list_element *setlist;
+
+void
+_initialize_stack ()
+{
+#if 0
+ backtrace_limit = 30;
+#endif
+
+ add_com ("return", class_stack, return_command,
+ "Make selected stack frame return to its caller.\n\
+Control remains in the debugger, but when you continue\n\
+execution will resume in the frame above the one now selected.\n\
+If an argument is given, it is an expression for the value to return.");
+
+ add_com ("up", class_stack, up_command,
+ "Select and print stack frame that called this one.\n\
+An argument says how many frames up to go.");
+
+ add_com ("down", class_stack, down_command,
+ "Select and print stack frame called by this one.\n\
+An argument says how many frames down to go.");
+ add_com_alias ("do", "down", class_stack, 1);
+
+ add_com ("frame", class_stack, frame_command,
+ "Select and print a stack frame.\n\
+With no argument, print the selected stack frame. (See also \"info frame\").\n\
+An argument specifies the frame to select.\n\
+It can be a stack frame number or the address of the frame.\n\
+With argument, nothing is printed if input is coming from\n\
+a command file or a user-defined command.");
+
+ add_com_alias ("f", "frame", class_stack, 1);
+
+ add_com ("backtrace", class_stack, backtrace_command,
+ "Print backtrace of all stack frames, or innermost COUNT frames.\n\
+With a negative argument, print outermost -COUNT frames.");
+ add_com_alias ("bt", "backtrace", class_stack, 0);
+ add_com_alias ("where", "backtrace", class_alias, 0);
+ add_info ("stack", backtrace_command,
+ "Backtrace of the stack, or innermost COUNT frames.");
+ add_info_alias ("s", "stack", 1);
+ add_info ("frame", frame_info,
+ "All about selected stack frame, or frame at ADDR.");
+ add_info_alias ("f", "frame", 1);
+ add_info ("locals", locals_info,
+ "Local variables of current stack frame.");
+ add_info ("args", args_info,
+ "Argument variables of current stack frame.");
+
+#if 0
+ add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command,
+ "Specify maximum number of frames for \"backtrace\" to print by default.",
+ &setlist);
+ add_info ("backtrace-limit", backtrace_limit_info,
+ "The maximum number of frames for \"backtrace\" to print by default.");
+#endif
+}
+
diff --git a/gnu/usr.bin/kgdb/symmisc.c b/gnu/usr.bin/kgdb/symmisc.c
new file mode 100644
index 000000000000..bb4eb50674d6
--- /dev/null
+++ b/gnu/usr.bin/kgdb/symmisc.c
@@ -0,0 +1,584 @@
+/* Do various things to symbol tables (other than lookup)), for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "defs.h"
+#include "symtab.h"
+
+#include <stdio.h>
+#include <obstack.h>
+
+static void free_symtab ();
+
+
+/* Free all the symtabs that are currently installed,
+ and all storage associated with them.
+ Leaves us in a consistent state with no symtabs installed. */
+
+void
+free_all_symtabs ()
+{
+ register struct symtab *s, *snext;
+
+ /* All values will be invalid because their types will be! */
+
+ clear_value_history ();
+ clear_displays ();
+ clear_internalvars ();
+ clear_breakpoints ();
+ set_default_breakpoint (0, 0, 0, 0);
+
+ current_source_symtab = 0;
+
+ for (s = symtab_list; s; s = snext)
+ {
+ snext = s->next;
+ free_symtab (s);
+ }
+ symtab_list = 0;
+ obstack_free (symbol_obstack, 0);
+ obstack_init (symbol_obstack);
+
+ if (misc_function_vector)
+ free (misc_function_vector);
+ misc_function_count = 0;
+ misc_function_vector = 0;
+}
+
+/* Free a struct block <- B and all the symbols defined in that block. */
+
+static void
+free_symtab_block (b)
+ struct block *b;
+{
+ register int i, n;
+ n = BLOCK_NSYMS (b);
+ for (i = 0; i < n; i++)
+ {
+ free (SYMBOL_NAME (BLOCK_SYM (b, i)));
+ free (BLOCK_SYM (b, i));
+ }
+ free (b);
+}
+
+/* Free all the storage associated with the struct symtab <- S.
+ Note that some symtabs have contents malloc'ed structure by structure,
+ while some have contents that all live inside one big block of memory,
+ and some share the contents of another symbol table and so you should
+ not free the contents on their behalf (except sometimes the linetable,
+ which maybe per symtab even when the rest is not).
+ It is s->free_code that says which alternative to use. */
+
+static void
+free_symtab (s)
+ register struct symtab *s;
+{
+ register int i, n;
+ register struct blockvector *bv;
+ register struct type *type;
+ register struct typevector *tv;
+
+ switch (s->free_code)
+ {
+ case free_nothing:
+ /* All the contents are part of a big block of memory
+ and some other symtab is in charge of freeing that block.
+ Therefore, do nothing. */
+ break;
+
+ case free_contents:
+ /* Here all the contents were malloc'ed structure by structure
+ and must be freed that way. */
+ /* First free the blocks (and their symbols. */
+ bv = BLOCKVECTOR (s);
+ n = BLOCKVECTOR_NBLOCKS (bv);
+ for (i = 0; i < n; i++)
+ free_symtab_block (BLOCKVECTOR_BLOCK (bv, i));
+ /* Free the blockvector itself. */
+ free (bv);
+ /* Free the type vector. */
+ tv = TYPEVECTOR (s);
+ free (tv);
+ /* Also free the linetable. */
+
+ case free_linetable:
+ /* Everything will be freed either by our `free_ptr'
+ or by some other symbatb, except for our linetable.
+ Free that now. */
+ free (LINETABLE (s));
+ break;
+ }
+
+ /* If there is a single block of memory to free, free it. */
+ if (s->free_ptr)
+ free (s->free_ptr);
+
+ if (s->line_charpos)
+ free (s->line_charpos);
+ free (s->filename);
+ free (s);
+}
+
+/* Convert a raw symbol-segment to a struct symtab,
+ and relocate its internal pointers so that it is valid. */
+
+/* This is how to relocate one pointer, given a name for it.
+ Works independent of the type of object pointed to. */
+#define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0)
+
+/* This is the inverse of RELOCATE. We use it when storing
+ a core address into a slot that has yet to be relocated. */
+#define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0)
+
+/* During the process of relocation, this holds the amount to relocate by
+ (the address of the file's symtab data, in core in the debugger). */
+static int relocation;
+
+#define CORE_RELOCATE(slot) \
+ ((slot) += (((slot) < data_start) ? text_relocation \
+ : ((slot) < bss_start) ? data_relocation : bss_relocation))
+
+#define TEXT_RELOCATE(slot) ((slot) += text_relocation)
+
+/* Relocation amounts for addresses in the program's core image. */
+static int text_relocation, data_relocation, bss_relocation;
+
+/* Boundaries that divide program core addresses into text, data and bss;
+ used to determine which relocation amount to use. */
+static int data_start, bss_start;
+
+static void relocate_typevector ();
+static void relocate_blockvector ();
+static void relocate_type ();
+static void relocate_block ();
+static void relocate_symbol ();
+static void relocate_source ();
+
+/* Relocate a file's symseg so that all the pointers are valid C pointers.
+ Value is a `struct symtab'; but it is not suitable for direct
+ insertion into the `symtab_list' because it describes several files. */
+
+static struct symtab *
+relocate_symtab (root)
+ struct symbol_root *root;
+{
+ struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab));
+ bzero (sp, sizeof (struct symtab));
+
+ relocation = (int) root;
+ text_relocation = root->textrel;
+ data_relocation = root->datarel;
+ bss_relocation = root->bssrel;
+ data_start = root->databeg;
+ bss_start = root->bssbeg;
+
+ sp->filename = root->filename;
+ sp->ldsymoff = root->ldsymoff;
+ sp->language = root->language;
+ sp->compilation = root->compilation;
+ sp->version = root->version;
+ sp->blockvector = root->blockvector;
+ sp->typevector = root->typevector;
+
+ RELOCATE (TYPEVECTOR (sp));
+ RELOCATE (BLOCKVECTOR (sp));
+ RELOCATE (sp->version);
+ RELOCATE (sp->compilation);
+ RELOCATE (sp->filename);
+
+ relocate_typevector (TYPEVECTOR (sp));
+ relocate_blockvector (BLOCKVECTOR (sp));
+
+ return sp;
+}
+
+static void
+relocate_blockvector (blp)
+ register struct blockvector *blp;
+{
+ register int nblocks = BLOCKVECTOR_NBLOCKS (blp);
+ register int i;
+ for (i = 0; i < nblocks; i++)
+ RELOCATE (BLOCKVECTOR_BLOCK (blp, i));
+ for (i = 0; i < nblocks; i++)
+ relocate_block (BLOCKVECTOR_BLOCK (blp, i));
+}
+
+static void
+relocate_block (bp)
+ register struct block *bp;
+{
+ register int nsyms = BLOCK_NSYMS (bp);
+ register int i;
+
+ TEXT_RELOCATE (BLOCK_START (bp));
+ TEXT_RELOCATE (BLOCK_END (bp));
+
+ /* These two should not be recursively processed.
+ The superblock need not be because all blocks are
+ processed from relocate_blockvector.
+ The function need not be because it will be processed
+ under the block which is its scope. */
+ RELOCATE (BLOCK_SUPERBLOCK (bp));
+ RELOCATE (BLOCK_FUNCTION (bp));
+
+ for (i = 0; i < nsyms; i++)
+ RELOCATE (BLOCK_SYM (bp, i));
+
+ for (i = 0; i < nsyms; i++)
+ relocate_symbol (BLOCK_SYM (bp, i));
+}
+
+static void
+relocate_symbol (sp)
+ register struct symbol *sp;
+{
+ RELOCATE (SYMBOL_NAME (sp));
+ if (SYMBOL_CLASS (sp) == LOC_BLOCK)
+ {
+ RELOCATE (SYMBOL_BLOCK_VALUE (sp));
+ /* We can assume the block that belongs to this symbol
+ is not relocated yet, since it comes after
+ the block that contains this symbol. */
+ BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp;
+ UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)));
+ }
+ else if (SYMBOL_CLASS (sp) == LOC_STATIC)
+ CORE_RELOCATE (SYMBOL_VALUE (sp));
+ else if (SYMBOL_CLASS (sp) == LOC_LABEL)
+ TEXT_RELOCATE (SYMBOL_VALUE (sp));
+ RELOCATE (SYMBOL_TYPE (sp));
+}
+
+static void
+relocate_typevector (tv)
+ struct typevector *tv;
+{
+ register int ntypes = TYPEVECTOR_NTYPES (tv);
+ register int i;
+
+ for (i = 0; i < ntypes; i++)
+ RELOCATE (TYPEVECTOR_TYPE (tv, i));
+ for (i = 0; i < ntypes; i++)
+ relocate_type (TYPEVECTOR_TYPE (tv, i));
+}
+
+/* We cannot come up with an a priori spanning tree
+ for the network of types, since types can be used
+ for many symbols and also as components of other types.
+ Therefore, we need to be able to mark types that we
+ already have relocated (or are already in the middle of relocating)
+ as in a garbage collector. */
+
+static void
+relocate_type (tp)
+ register struct type *tp;
+{
+ register int nfields = TYPE_NFIELDS (tp);
+ register int i;
+
+ RELOCATE (TYPE_NAME (tp));
+ RELOCATE (TYPE_TARGET_TYPE (tp));
+ RELOCATE (TYPE_FIELDS (tp));
+ RELOCATE (TYPE_POINTER_TYPE (tp));
+
+ for (i = 0; i < nfields; i++)
+ {
+ RELOCATE (TYPE_FIELD_TYPE (tp, i));
+ RELOCATE (TYPE_FIELD_NAME (tp, i));
+ }
+}
+
+static void
+relocate_sourcevector (svp)
+ register struct sourcevector *svp;
+{
+ register int nfiles = svp->length;
+ register int i;
+ for (i = 0; i < nfiles; i++)
+ RELOCATE (svp->source[i]);
+ for (i = 0; i < nfiles; i++)
+ relocate_source (svp->source[i]);
+}
+
+static void
+relocate_source (sp)
+ register struct source *sp;
+{
+ register int nitems = sp->contents.nitems;
+ register int i;
+
+ RELOCATE (sp->name);
+ for (i = 0; i < nitems; i++)
+ TEXT_RELOCATE (sp->contents.item[i].pc);
+}
+
+/* Read symsegs from file named NAME open on DESC,
+ make symtabs from them, and return a chain of them.
+ These symtabs are not suitable for direct use in `symtab_list'
+ because each one describes a single object file, perhaps many source files.
+ `symbol_file_command' takes each of these, makes many real symtabs
+ from it, and then frees it.
+
+ We assume DESC is prepositioned at the end of the string table,
+ just before the symsegs if there are any. */
+
+struct symtab *
+read_symsegs (desc, name)
+ int desc;
+ char *name;
+{
+ struct symbol_root root;
+ register char *data;
+ register struct symtab *sp, *sp1, *chain = 0;
+ register int len;
+
+ while (1)
+ {
+ len = myread (desc, &root, sizeof root);
+ if (len == 0 || root.format == 0)
+ break;
+ /* format 1 was ok for the original gdb, but since the size of the
+ type structure changed when C++ support was added, it can no
+ longer be used. Accept only format 2. */
+ if (root.format != 2 ||
+ root.length < sizeof root)
+ error ("\nInvalid symbol segment format code");
+ data = (char *) xmalloc (root.length);
+ bcopy (&root, data, sizeof root);
+ len = myread (desc, data + sizeof root,
+ root.length - sizeof root);
+ sp = relocate_symtab (data);
+ RELOCATE (((struct symbol_root *)data)->sourcevector);
+ relocate_sourcevector (((struct symbol_root *)data)->sourcevector);
+ sp->next = chain;
+ chain = sp;
+ sp->linetable = (struct linetable *) ((struct symbol_root *)data)->sourcevector;
+ }
+
+ return chain;
+}
+
+static int block_depth ();
+void print_spaces ();
+static void print_symbol ();
+
+void
+print_symtabs (filename)
+ char *filename;
+{
+ FILE *outfile;
+ register struct symtab *s;
+ register int i, j;
+ int len, line, blen;
+ register struct linetable *l;
+ struct blockvector *bv;
+ register struct block *b;
+ int depth;
+ struct cleanup *cleanups;
+ extern int fclose();
+
+ if (filename == 0)
+ error_no_arg ("file to write symbol data in");
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ outfile = fopen (filename, "w");
+ if (outfile == 0)
+ perror_with_name (filename);
+
+ cleanups = make_cleanup (fclose, outfile);
+ immediate_quit++;
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ /* First print the line table. */
+ fprintf (outfile, "Symtab for file %s\n\n", s->filename);
+ fprintf (outfile, "Line table:\n\n");
+ l = LINETABLE (s);
+ len = l->nitems;
+ for (i = 0; i < len; i++)
+ fprintf (outfile, " line %d at %x\n", l->item[i].line,
+ l->item[i].pc);
+ /* Now print the block info. */
+ fprintf (outfile, "\nBlockvector:\n\n");
+ bv = BLOCKVECTOR (s);
+ len = BLOCKVECTOR_NBLOCKS (bv);
+ for (i = 0; i < len; i++)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ depth = block_depth (b) * 2;
+ print_spaces (depth, outfile);
+ fprintf (outfile, "block #%03d (object 0x%x) ", i, b);
+ fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b));
+ if (BLOCK_SUPERBLOCK (b))
+ fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b));
+ if (BLOCK_FUNCTION (b))
+ fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
+ fputc ('\n', outfile);
+ blen = BLOCK_NSYMS (b);
+ for (j = 0; j < blen; j++)
+ {
+ print_symbol (BLOCK_SYM (b, j), depth + 1, outfile);
+ }
+ }
+
+ fprintf (outfile, "\n\n");
+ }
+
+ immediate_quit--;
+ do_cleanups (cleanups);
+}
+
+static void
+print_symbol (symbol, depth, outfile)
+ struct symbol *symbol;
+ int depth;
+ FILE *outfile;
+{
+ print_spaces (depth, outfile);
+ if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
+ {
+ fprintf (outfile, "label %s at 0x%x\n", SYMBOL_NAME (symbol),
+ SYMBOL_VALUE (symbol));
+ return;
+ }
+ if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
+ {
+ if (TYPE_NAME (SYMBOL_TYPE (symbol)))
+ {
+ type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+ }
+ else
+ {
+ fprintf (outfile, "%s %s = ",
+ (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
+ ? "enum"
+ : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
+ ? "struct" : "union")),
+ SYMBOL_NAME (symbol));
+ type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+ }
+ fprintf (outfile, ";\n");
+ }
+ else
+ {
+ if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
+ fprintf (outfile, "typedef ");
+ if (SYMBOL_TYPE (symbol))
+ {
+ type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol),
+ outfile, 1, depth);
+ fprintf (outfile, "; ");
+ }
+ else
+ fprintf (outfile, "%s ", SYMBOL_NAME (symbol));
+
+ switch (SYMBOL_CLASS (symbol))
+ {
+ case LOC_CONST:
+ fprintf (outfile, "const %d (0x%x),",
+ SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_CONST_BYTES:
+ fprintf (outfile, "const %d hex bytes:",
+ TYPE_LENGTH (SYMBOL_TYPE (symbol)));
+ {
+ int i;
+ for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
+ fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]);
+ fprintf (outfile, ",");
+ }
+ break;
+
+ case LOC_STATIC:
+ fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REGISTER:
+ fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_ARG:
+ fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REF_ARG:
+ fprintf (outfile, "reference arg at 0x%x,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REGPARM:
+ fprintf (outfile, "parameter register %d,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_LOCAL:
+ fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_TYPEDEF:
+ break;
+
+ case LOC_LABEL:
+ fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_BLOCK:
+ fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
+ SYMBOL_VALUE (symbol),
+ BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
+ break;
+ }
+ }
+ fprintf (outfile, "\n");
+}
+
+/* Return the nexting depth of a block within other blocks in its symtab. */
+
+static int
+block_depth (block)
+ struct block *block;
+{
+ register int i = 0;
+ while (block = BLOCK_SUPERBLOCK (block)) i++;
+ return i;
+}
+
+/*
+ * Free all partial_symtab storage.
+ */
+void
+free_all_psymtabs()
+{
+ obstack_free (psymbol_obstack, 0);
+ obstack_init (psymbol_obstack);
+ partial_symtab_list = (struct partial_symtab *) 0;
+}
+
+void
+_initialize_symmisc ()
+{
+ symtab_list = (struct symtab *) 0;
+ partial_symtab_list = (struct partial_symtab *) 0;
+
+ add_com ("printsyms", class_obscure, print_symtabs,
+ "Print dump of current symbol definitions to file OUTFILE.");
+}
+
diff --git a/gnu/usr.bin/kgdb/symseg.h b/gnu/usr.bin/kgdb/symseg.h
new file mode 100644
index 000000000000..6a61a1791a20
--- /dev/null
+++ b/gnu/usr.bin/kgdb/symseg.h
@@ -0,0 +1,523 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ *
+ * @(#)symseg.h 6.3 (Berkeley) 5/8/91
+ */
+
+/* GDB symbol table format definitions.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+ Hacked by Michael Tiemann (tiemann@mcc.com)
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Format of GDB symbol table data.
+ There is one symbol segment for each source file or
+ independant compilation. These segments are simply concatenated
+ to form the GDB symbol table. A zero word where the beginning
+ of a segment is expected indicates there are no more segments.
+
+Format of a symbol segment:
+
+ The symbol segment begins with a word containing 1
+ if it is in the format described here. Other formats may
+ be designed, with other code numbers.
+
+ The segment contains many objects which point at each other.
+ The pointers are offsets in bytes from the beginning of the segment.
+ Thus, each segment can be loaded into core and its pointers relocated
+ to make valid in-core pointers.
+
+ All the data objects in the segment can be found indirectly from
+ one of them, the root object, of type `struct symbol_root'.
+ It appears at the beginning of the segment.
+
+ The total size of the segment, in bytes, appears as the `length'
+ field of this object. This size includes the size of the
+ root object.
+
+ All the object data types are defined here to contain pointer types
+ appropriate for in-core use on a relocated symbol segment.
+ Casts to and from type int are required for working with
+ unrelocated symbol segments such as are found in the file.
+
+ The ldsymaddr word is filled in by the loader to contain
+ the offset (in bytes) within the ld symbol table
+ of the first nonglobal symbol from this compilation.
+ This makes it possible to match those symbols
+ (which contain line number information) reliably with
+ the segment they go with.
+
+ Core addresses within the program that appear in the symbol segment
+ are not relocated by the loader. They are inserted by the assembler
+ and apply to addresses as output by the assembler, so GDB must
+ relocate them when it loads the symbol segment. It gets the information
+ on how to relocate from the textrel, datarel, bssrel, databeg and bssbeg
+ words of the root object.
+
+ The words textrel, datarel and bssrel
+ are filled in by ld with the amounts to relocate within-the-file
+ text, data and bss addresses by; databeg and bssbeg can be
+ used to tell which kind of relocation an address needs. */
+
+enum language {language_c};
+
+struct symbol_root
+{
+ int format; /* Data format version */
+ int length; /* # bytes in this symbol segment */
+ int ldsymoff; /* Offset in ld symtab of this file's syms */
+ int textrel; /* Relocation for text addresses */
+ int datarel; /* Relocation for data addresses */
+ int bssrel; /* Relocation for bss addresses */
+ char *filename; /* Name of main source file compiled */
+ char *filedir; /* Name of directory it was reached from */
+ struct blockvector *blockvector; /* Vector of all symbol-naming blocks */
+ struct typevector *typevector; /* Vector of all data types */
+ enum language language; /* Code identifying the language used */
+ char *version; /* Version info. Not fully specified */
+ char *compilation; /* Compilation info. Not fully specified */
+ int databeg; /* Address within the file of data start */
+ int bssbeg; /* Address within the file of bss start */
+ struct sourcevector *sourcevector; /* Vector of line-number info */
+};
+
+/* All data types of symbols in the compiled program
+ are represented by `struct type' objects.
+ All of these objects are pointed to by the typevector.
+ The type vector may have empty slots that contain zero. */
+
+struct typevector
+{
+ int length; /* Number of types described */
+ struct type *type[1];
+};
+
+/* Different kinds of data types are distinguished by the `code' field. */
+
+enum type_code
+{
+ TYPE_CODE_UNDEF, /* Not used; catches errors */
+ TYPE_CODE_PTR, /* Pointer type */
+ TYPE_CODE_ARRAY, /* Array type, lower bound zero */
+ TYPE_CODE_STRUCT, /* C struct or Pascal record */
+ TYPE_CODE_UNION, /* C union or Pascal variant part */
+ TYPE_CODE_ENUM, /* Enumeration type */
+ TYPE_CODE_FUNC, /* Function type */
+ TYPE_CODE_INT, /* Integer type */
+ TYPE_CODE_FLT, /* Floating type */
+ TYPE_CODE_VOID, /* Void type (values zero length) */
+ TYPE_CODE_SET, /* Pascal sets */
+ TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
+ TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
+
+ /* C++ */
+ TYPE_CODE_MEMBER, /* Member type */
+ TYPE_CODE_METHOD, /* Method type */
+ TYPE_CODE_REF, /* C++ Reference types */
+};
+
+/* This appears in a type's flags word for an unsigned integer type. */
+#define TYPE_FLAG_UNSIGNED 1
+/* This appears in a type's flags word
+ if it is a (pointer to a|function returning a)* built in scalar type.
+ These types are never freed. */
+#define TYPE_FLAG_PERM 4
+/* This appears in a type's flags word if it is a stub type (eg. if
+ someone referenced a type that wasn't definined in a source file
+ via (struct sir_not_appearing_in_this_film *)). */
+#define TYPE_FLAG_STUB 8
+/* Set when a class has a constructor defined */
+#define TYPE_FLAG_HAS_CONSTRUCTOR 256
+/* Set when a class has a destructor defined */
+#define TYPE_FLAG_HAS_DESTRUCTOR 512
+/* Indicates that this type is a public baseclass of another class,
+ i.e. that all its public methods are available in the derived
+ class. */
+#define TYPE_FLAG_VIA_PUBLIC 1024
+/* Indicates that this type is a virtual baseclass of another class,
+ i.e. that if this class is inherited more than once by another
+ class, only one set of member variables will be included. */
+#define TYPE_FLAG_VIA_VIRTUAL 2048
+
+struct type
+{
+ /* Code for kind of type */
+ enum type_code code;
+ /* Name of this type, or zero if none.
+ This is used for printing only.
+ Type names specified as input are defined by symbols. */
+ char *name;
+ /* Length in bytes of storage for a value of this type */
+ int length;
+ /* For a pointer type, describes the type of object pointed to.
+ For an array type, describes the type of the elements.
+ For a function or method type, describes the type of the value.
+ For a range type, describes the type of the full range.
+ Unused otherwise. */
+ struct type *target_type;
+ /* Type that is a pointer to this type.
+ Zero if no such pointer-to type is known yet.
+ The debugger may add the address of such a type
+ if it has to construct one later. */
+ struct type *pointer_type;
+ /* C++: also need a reference type. */
+ struct type *reference_type;
+ struct type **arg_types;
+
+ /* Type that is a function returning this type.
+ Zero if no such function type is known here.
+ The debugger may add the address of such a type
+ if it has to construct one later. */
+ struct type *function_type;
+
+/* Handling of pointers to members:
+ TYPE_MAIN_VARIANT is used for pointer and pointer
+ to member types. Normally it the value of the address of its
+ containing type. However, for pointers to members, we must be
+ able to allocate pointer to member types and look them up
+ from some place of reference.
+ NEXT_VARIANT is the next element in the chain. */
+ struct type *main_variant, *next_variant;
+
+ /* Flags about this type. */
+ short flags;
+ /* Number of fields described for this type */
+ short nfields;
+ /* For structure and union types, a description of each field.
+ For set and pascal array types, there is one "field",
+ whose type is the domain type of the set or array.
+ For range types, there are two "fields",
+ the minimum and maximum values (both inclusive).
+ For enum types, each possible value is described by one "field".
+
+ Using a pointer to a separate array of fields
+ allows all types to have the same size, which is useful
+ because we can allocate the space for a type before
+ we know what to put in it. */
+ struct field
+ {
+ /* Position of this field, counting in bits from start of
+ containing structure. For a function type, this is the
+ position in the argument list of this argument.
+ For a range bound or enum value, this is the value itself. */
+ int bitpos;
+ /* Size of this field, in bits, or zero if not packed.
+ For an unpacked field, the field's type's length
+ says how many bytes the field occupies. */
+ int bitsize;
+ /* In a struct or enum type, type of this field.
+ In a function type, type of this argument.
+ In an array type, the domain-type of the array. */
+ struct type *type;
+ /* Name of field, value or argument.
+ Zero for range bounds and array domains. */
+ char *name;
+ } *fields;
+
+ /* C++ */
+ int *private_field_bits;
+ int *protected_field_bits;
+
+ /* Number of methods described for this type */
+ short nfn_fields;
+ /* Number of base classes this type derives from. */
+ short n_baseclasses;
+
+ /* Number of methods described for this type plus all the
+ methods that it derives from. */
+ int nfn_fields_total;
+
+ /* For classes, structures, and unions, a description of each field,
+ which consists of an overloaded name, followed by the types of
+ arguments that the method expects, and then the name after it
+ has been renamed to make it distinct. */
+ struct fn_fieldlist
+ {
+ /* The overloaded name. */
+ char *name;
+ /* The number of methods with this name. */
+ int length;
+ /* The list of methods. */
+ struct fn_field
+ {
+#if 0
+ /* The overloaded name */
+ char *name;
+#endif
+ /* The return value of the method */
+ struct type *type;
+ /* The argument list */
+ struct type **args;
+ /* The name after it has been processed */
+ char *physname;
+ /* If this is a virtual function, the offset into the vtbl-1,
+ else 0. */
+ int voffset;
+ } *fn_fields;
+
+ int *private_fn_field_bits;
+ int *protected_fn_field_bits;
+
+ } *fn_fieldlists;
+
+ unsigned char via_protected;
+ unsigned char via_public;
+
+ /* For types with virtual functions, VPTR_BASETYPE is the base class which
+ defined the virtual function table pointer. VPTR_FIELDNO is
+ the field number of that pointer in the structure.
+
+ For types that are pointer to member types, VPTR_BASETYPE
+ ifs the type that this pointer is a member of.
+
+ Unused otherwise. */
+ struct type *vptr_basetype;
+
+ int vptr_fieldno;
+
+ /* If this type has a base class, put it here.
+ If this type is a pointer type, the chain of member pointer
+ types goes here.
+ Unused otherwise.
+
+ Contrary to all maxims of C style and common sense, the baseclasses
+ are indexed from 1 to N_BASECLASSES rather than 0 to N_BASECLASSES-1
+ (i.e. BASECLASSES points to one *before* the first element of
+ the array). */
+ struct type **baseclasses;
+};
+
+/* All of the name-scope contours of the program
+ are represented by `struct block' objects.
+ All of these objects are pointed to by the blockvector.
+
+ Each block represents one name scope.
+ Each lexical context has its own block.
+
+ The first two blocks in the blockvector are special.
+ The first one contains all the symbols defined in this compilation
+ whose scope is the entire program linked together.
+ The second one contains all the symbols whose scope is the
+ entire compilation excluding other separate compilations.
+ In C, these correspond to global symbols and static symbols.
+
+ Each block records a range of core addresses for the code that
+ is in the scope of the block. The first two special blocks
+ give, for the range of code, the entire range of code produced
+ by the compilation that the symbol segment belongs to.
+
+ The blocks appear in the blockvector
+ in order of increasing starting-address,
+ and, within that, in order of decreasing ending-address.
+
+ This implies that within the body of one function
+ the blocks appear in the order of a depth-first tree walk. */
+
+struct blockvector
+{
+ /* Number of blocks in the list. */
+ int nblocks;
+ /* The blocks themselves. */
+ struct block *block[1];
+};
+
+struct block
+{
+ /* Addresses in the executable code that are in this block.
+ Note: in an unrelocated symbol segment in a file,
+ these are always zero. They can be filled in from the
+ N_LBRAC and N_RBRAC symbols in the loader symbol table. */
+ int startaddr, endaddr;
+ /* The symbol that names this block,
+ if the block is the body of a function;
+ otherwise, zero.
+ Note: In an unrelocated symbol segment in an object file,
+ this field may be zero even when the block has a name.
+ That is because the block is output before the name
+ (since the name resides in a higher block).
+ Since the symbol does point to the block (as its value),
+ it is possible to find the block and set its name properly. */
+ struct symbol *function;
+ /* The `struct block' for the containing block, or 0 if none. */
+ /* Note that in an unrelocated symbol segment in an object file
+ this pointer may be zero when the correct value should be
+ the second special block (for symbols whose scope is one compilation).
+ This is because the compiler ouptuts the special blocks at the
+ very end, after the other blocks. */
+ struct block *superblock;
+ /* A flag indicating whether or not the fucntion corresponding
+ to this block was compiled with gcc or not. If there is no
+ function corresponding to this block, this meaning of this flag
+ is undefined. (In practice it will be 1 if the block was created
+ while processing a file compiled with gcc and 0 when not). */
+ unsigned char gcc_compile_flag;
+ /* Number of local symbols. */
+ int nsyms;
+ /* The symbols. */
+ struct symbol *sym[1];
+};
+
+/* Represent one symbol name; a variable, constant, function or typedef. */
+
+/* Different name spaces for symbols. Looking up a symbol specifies
+ a namespace and ignores symbol definitions in other name spaces.
+
+ VAR_NAMESPACE is the usual namespace.
+ In C, this contains variables, function names, typedef names
+ and enum type values.
+
+ STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
+ Thus, if `struct foo' is used in a C program,
+ it produces a symbol named `foo' in the STRUCT_NAMESPACE.
+
+ LABEL_NAMESPACE may be used for names of labels (for gotos);
+ currently it is not used and labels are not recorded at all. */
+
+/* For a non-global symbol allocated statically,
+ the correct core address cannot be determined by the compiler.
+ The compiler puts an index number into the symbol's value field.
+ This index number can be matched with the "desc" field of
+ an entry in the loader symbol table. */
+
+enum namespace
+{
+ UNDEF_NAMESPACE, VAR_NAMESPACE, STRUCT_NAMESPACE, LABEL_NAMESPACE,
+};
+
+/* An address-class says where to find the value of the symbol in core. */
+
+enum address_class
+{
+ LOC_UNDEF, /* Not used; catches errors */
+ LOC_CONST, /* Value is constant int */
+ LOC_STATIC, /* Value is at fixed address */
+ LOC_REGISTER, /* Value is in register */
+ LOC_ARG, /* Value is at spec'd position in arglist */
+ LOC_REF_ARG, /* Value address is at spec'd position in */
+ /* arglist. */
+ LOC_REGPARM, /* Value is at spec'd position in register window */
+ LOC_LOCAL, /* Value is at spec'd pos in stack frame */
+ LOC_TYPEDEF, /* Value not used; definition in SYMBOL_TYPE
+ Symbols in the namespace STRUCT_NAMESPACE
+ all have this class. */
+ LOC_LABEL, /* Value is address in the code */
+ LOC_BLOCK, /* Value is address of a `struct block'.
+ Function names have this class. */
+ LOC_EXTERNAL, /* Value is at address not in this compilation.
+ This is used for .comm symbols
+ and for extern symbols within functions.
+ Inside GDB, this is changed to LOC_STATIC once the
+ real address is obtained from a loader symbol. */
+ LOC_CONST_BYTES /* Value is a constant byte-sequence. */
+};
+
+struct symbol
+{
+ /* Symbol name */
+ char *name;
+ /* Name space code. */
+ enum namespace namespace;
+ /* Address class */
+ enum address_class class;
+ /* Data type of value */
+ struct type *type;
+ /* constant value, or address if static, or register number,
+ or offset in arguments, or offset in stack frame. */
+ union
+ {
+ long value;
+ struct block *block; /* for LOC_BLOCK */
+ char *bytes; /* for LOC_CONST_BYTES */
+ }
+ value;
+};
+
+struct partial_symbol
+{
+ /* Symbol name */
+ char *name;
+ /* Name space code. */
+ enum namespace namespace;
+ /* Address class (for info_symbols) */
+ enum address_class class;
+ /* Associated partial symbol table */
+ struct partial_symtab *pst;
+ /* Value (only used for static functions currently). Done this
+ way so that we can use the struct symbol macros.
+ Note that the address of a function is SYMBOL_VALUE (pst)
+ in a partial symbol table, but BLOCK_START (SYMBOL_BLOCK_VALUE (st))
+ in a symbol table. */
+ union
+ {
+ long value;
+ }
+ value;
+};
+
+/*
+ * Vectors of all partial symbols read in from file; actually declared
+ * and used in dbxread.c.
+ */
+extern struct psymbol_allocation_list {
+ struct partial_symbol *list, *next;
+ int size;
+} global_psymbols, static_psymbols;
+
+
+/* Source-file information.
+ This describes the relation between source files and line numbers
+ and addresses in the program text. */
+
+struct sourcevector
+{
+ int length; /* Number of source files described */
+ struct source *source[1]; /* Descriptions of the files */
+};
+
+/* Each item represents a line-->pc (or the reverse) mapping. This is
+ somewhat more wasteful of space than one might wish, but since only
+ the files which are actually debugged are read in to core, we don't
+ waste much space.
+
+ Each item used to be an int; either minus a line number, or a
+ program counter. If it represents a line number, that is the line
+ described by the next program counter value. If it is positive, it
+ is the program counter at which the code for the next line starts. */
+
+struct linetable_entry
+{
+ int line;
+ CORE_ADDR pc;
+};
+
+struct linetable
+{
+ int nitems;
+ struct linetable_entry item[1];
+};
+
+/* All the information on one source file. */
+
+struct source
+{
+ char *name; /* Name of file */
+ struct linetable contents;
+};
diff --git a/gnu/usr.bin/kgdb/symtab.c b/gnu/usr.bin/kgdb/symtab.c
new file mode 100644
index 000000000000..1d732b5cbb92
--- /dev/null
+++ b/gnu/usr.bin/kgdb/symtab.c
@@ -0,0 +1,2473 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ *
+ * /home/ncvs/src/gnu/usr.bin/kgdb/symtab.c,v 1.2 1993/12/01 16:44:43 ats Exp;
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)symtab.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Symbol table lookup for the GNU debugger, GDB.
+ Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+
+#include <obstack.h>
+#include <assert.h>
+
+char *index ();
+extern char *cplus_demangle ();
+extern struct value * value_of_this ();
+
+/* Allocate an obstack to hold objects that should be freed
+ when we load a new symbol table.
+ This includes the symbols made by dbxread
+ and the types that are not permanent. */
+
+struct obstack obstack1;
+
+struct obstack *symbol_obstack = &obstack1;
+
+/* This obstack will be used for partial_symbol objects. It can
+ probably actually be the same as the symbol_obstack above, but I'd
+ like to keep them seperate for now. If I want to later, I'll
+ replace one with the other. */
+
+struct obstack obstack2;
+
+struct obstack *psymbol_obstack = &obstack2;
+
+/* These variables point to the objects
+ representing the predefined C data types. */
+
+struct type *builtin_type_void;
+struct type *builtin_type_char;
+struct type *builtin_type_short;
+struct type *builtin_type_int;
+struct type *builtin_type_long;
+#ifdef LONG_LONG
+struct type *builtin_type_long_long;
+#endif
+struct type *builtin_type_unsigned_char;
+struct type *builtin_type_unsigned_short;
+struct type *builtin_type_unsigned_int;
+struct type *builtin_type_unsigned_long;
+#ifdef LONG_LONG
+struct type *builtin_type_unsigned_long_long;
+#endif
+struct type *builtin_type_float;
+struct type *builtin_type_double;
+
+/* Block in which the most recently searched-for symbol was found.
+ Might be better to make this a parameter to lookup_symbol and
+ value_of_this. */
+struct block *block_found;
+
+/* Functions */
+static int find_line_common ();
+int lookup_misc_func ();
+struct partial_symtab *lookup_partial_symtab ();
+struct symtab *psymtab_to_symtab ();
+static struct partial_symbol *lookup_partial_symbol ();
+
+/* Check for a symtab of a specific name; first in symtabs, then in
+ psymtabs. *If* there is no '/' in the name, a match after a '/'
+ in the symtab filename will also work. */
+
+static struct symtab *
+lookup_symtab_1 (name)
+ char *name;
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register char *slash = index (name, '/');
+ register int len = strlen (name);
+
+ for (s = symtab_list; s; s = s->next)
+ if (!strcmp (name, s->filename))
+ return s;
+
+ for (ps = partial_symtab_list; ps; ps = ps->next)
+ if (!strcmp (name, ps->filename))
+ {
+ if (ps->readin)
+ fatal ("Internal: readin pst found when no symtab found.");
+ s = psymtab_to_symtab (ps);
+ return s;
+ }
+
+ if (!slash)
+ {
+ for (s = symtab_list; s; s = s->next)
+ {
+ int l = strlen (s->filename);
+
+ if (s->filename[l - len -1] == '/'
+ && !strcmp (s->filename + l - len, name))
+ return s;
+ }
+
+ for (ps = partial_symtab_list; ps; ps = ps->next)
+ {
+ int l = strlen (ps->filename);
+
+ if (ps->filename[l - len - 1] == '/'
+ && !strcmp (ps->filename + l - len, name))
+ {
+ if (ps->readin)
+ fatal ("Internal: readin pst found when no symtab found.");
+ s = psymtab_to_symtab (ps);
+ return s;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Lookup the symbol table of a source file named NAME. Try a couple
+ of variations if the first lookup doesn't work. */
+
+struct symtab *
+lookup_symtab (name)
+ char *name;
+{
+ register struct symtab *s;
+ register char *copy;
+
+ s = lookup_symtab_1 (name);
+ if (s) return s;
+
+ /* If name not found as specified, see if adding ".c" helps. */
+
+ copy = (char *) alloca (strlen (name) + 3);
+ strcpy (copy, name);
+ strcat (copy, ".c");
+ s = lookup_symtab_1 (copy);
+ if (s) return s;
+
+ /* We didn't find anything; die. */
+ return 0;
+}
+
+/* Lookup the partial symbol table of a source file named NAME. This
+ only returns true on an exact match (ie. this semantics are
+ different from lookup_symtab. */
+
+struct partial_symtab *
+lookup_partial_symtab (name)
+char *name;
+{
+ register struct partial_symtab *s;
+ register char *copy;
+
+ for (s = partial_symtab_list; s; s = s->next)
+ if (!strcmp (name, s->filename))
+ return s;
+
+ return 0;
+}
+
+/* Lookup a typedef or primitive type named NAME,
+ visible in lexical block BLOCK.
+ If NOERR is nonzero, return zero if NAME is not suitably defined. */
+
+struct type *
+lookup_typename (name, block, noerr)
+ char *name;
+ struct block *block;
+ int noerr;
+{
+ register struct symbol *sym = lookup_symbol (name, block, VAR_NAMESPACE, 0);
+ if (sym == 0 || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ {
+ if (!strcmp (name, "int"))
+ return builtin_type_int;
+ if (!strcmp (name, "long"))
+ return builtin_type_long;
+ if (!strcmp (name, "short"))
+ return builtin_type_short;
+ if (!strcmp (name, "char"))
+ return builtin_type_char;
+ if (!strcmp (name, "float"))
+ return builtin_type_float;
+ if (!strcmp (name, "double"))
+ return builtin_type_double;
+ if (!strcmp (name, "void"))
+ return builtin_type_void;
+
+ if (noerr)
+ return 0;
+ error ("No type named %s.", name);
+ }
+ return SYMBOL_TYPE (sym);
+}
+
+struct type *
+lookup_unsigned_typename (name)
+ char *name;
+{
+ if (!strcmp (name, "int"))
+ return builtin_type_unsigned_int;
+ if (!strcmp (name, "long"))
+ return builtin_type_unsigned_long;
+ if (!strcmp (name, "short"))
+ return builtin_type_unsigned_short;
+ if (!strcmp (name, "char"))
+ return builtin_type_unsigned_char;
+ error ("No type named unsigned %s.", name);
+}
+
+/* Lookup a structure type named "struct NAME",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_struct (name, block)
+ char *name;
+ struct block *block;
+{
+ register struct symbol *sym
+ = lookup_symbol (name, block, STRUCT_NAMESPACE, 0);
+
+ if (sym == 0)
+ error ("No struct type named %s.", name);
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
+ error ("This context has class, union or enum %s, not a struct.", name);
+ return SYMBOL_TYPE (sym);
+}
+
+/* Lookup a union type named "union NAME",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_union (name, block)
+ char *name;
+ struct block *block;
+{
+ register struct symbol *sym
+ = lookup_symbol (name, block, STRUCT_NAMESPACE, 0);
+
+ if (sym == 0)
+ error ("No union type named %s.", name);
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
+ error ("This context has class, struct or enum %s, not a union.", name);
+ return SYMBOL_TYPE (sym);
+}
+
+/* Lookup an enum type named "enum NAME",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_enum (name, block)
+ char *name;
+ struct block *block;
+{
+ register struct symbol *sym
+ = lookup_symbol (name, block, STRUCT_NAMESPACE, 0);
+ if (sym == 0)
+ error ("No enum type named %s.", name);
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
+ error ("This context has class, struct or union %s, not an enum.", name);
+ return SYMBOL_TYPE (sym);
+}
+
+/* Given a type TYPE, lookup the type of the component of type named
+ NAME. */
+
+struct type *
+lookup_struct_elt_type (type, name)
+ struct type *type;
+ char *name;
+{
+ struct type *t;
+ int i;
+ char *errmsg;
+
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ {
+ terminal_ours ();
+ fflush (stdout);
+ fprintf (stderr, "Type ");
+ type_print (type, "", stderr, -1);
+ fprintf (stderr, " is not a structure or union type.\n");
+ return_to_top_level ();
+ }
+
+ for (i = TYPE_NFIELDS (type) - 1; i >= 0; i--)
+ if (!strcmp (TYPE_FIELD_NAME (type, i), name))
+ return TYPE_FIELD_TYPE (type, i);
+
+ terminal_ours ();
+ fflush (stdout);
+ fprintf (stderr, "Type ");
+ type_print (type, "", stderr, -1);
+ fprintf (stderr, " has no component named %s\n", name);
+ return_to_top_level ();
+}
+
+/* Given a type TYPE, return a type of pointers to that type.
+ May need to construct such a type if this is the first use.
+
+ C++: use TYPE_MAIN_VARIANT and TYPE_CHAIN to keep pointer
+ to member types under control. */
+
+struct type *
+lookup_pointer_type (type)
+ struct type *type;
+{
+ register struct type *ptype = TYPE_POINTER_TYPE (type);
+ if (ptype) return TYPE_MAIN_VARIANT (ptype);
+
+ /* This is the first time anyone wanted a pointer to a TYPE. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ ptype = (struct type *) xmalloc (sizeof (struct type));
+ else
+ ptype = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+
+ bzero (ptype, sizeof (struct type));
+ TYPE_MAIN_VARIANT (ptype) = ptype;
+ TYPE_TARGET_TYPE (ptype) = type;
+ TYPE_POINTER_TYPE (type) = ptype;
+ /* New type is permanent if type pointed to is permanent. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+ /* We assume the machine has only one representation for pointers! */
+ TYPE_LENGTH (ptype) = sizeof (char *);
+ TYPE_CODE (ptype) = TYPE_CODE_PTR;
+ return ptype;
+}
+
+struct type *
+lookup_reference_type (type)
+ struct type *type;
+{
+ register struct type *rtype = TYPE_REFERENCE_TYPE (type);
+ if (rtype) return TYPE_MAIN_VARIANT (rtype);
+
+ /* This is the first time anyone wanted a pointer to a TYPE. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ rtype = (struct type *) xmalloc (sizeof (struct type));
+ else
+ rtype = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+
+ bzero (rtype, sizeof (struct type));
+ TYPE_MAIN_VARIANT (rtype) = rtype;
+ TYPE_TARGET_TYPE (rtype) = type;
+ TYPE_REFERENCE_TYPE (type) = rtype;
+ /* New type is permanent if type pointed to is permanent. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ TYPE_FLAGS (rtype) |= TYPE_FLAG_PERM;
+ /* We assume the machine has only one representation for pointers! */
+ TYPE_LENGTH (rtype) = sizeof (char *);
+ TYPE_CODE (rtype) = TYPE_CODE_REF;
+ return rtype;
+}
+
+
+/* Implement direct support for MEMBER_TYPE in GNU C++.
+ May need to construct such a type if this is the first use.
+ The TYPE is the type of the member. The DOMAIN is the type
+ of the aggregate that the member belongs to. */
+
+struct type *
+lookup_member_type (type, domain)
+ struct type *type, *domain;
+{
+ register struct type *mtype = TYPE_MAIN_VARIANT (type);
+ struct type *main_type;
+
+ main_type = mtype;
+ while (mtype)
+ {
+ if (TYPE_DOMAIN_TYPE (mtype) == domain)
+ return mtype;
+ mtype = TYPE_NEXT_VARIANT (mtype);
+ }
+
+ /* This is the first time anyone wanted this member type. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ mtype = (struct type *) xmalloc (sizeof (struct type));
+ else
+ mtype = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+
+ bzero (mtype, sizeof (struct type));
+ if (main_type == 0)
+ main_type = mtype;
+ else
+ {
+ TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
+ TYPE_NEXT_VARIANT (main_type) = mtype;
+ }
+ TYPE_MAIN_VARIANT (mtype) = main_type;
+ TYPE_TARGET_TYPE (mtype) = type;
+ TYPE_DOMAIN_TYPE (mtype) = domain;
+ /* New type is permanent if type pointed to is permanent. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
+
+ /* In practice, this is never used. */
+ TYPE_LENGTH (mtype) = 1;
+ TYPE_CODE (mtype) = TYPE_CODE_MEMBER;
+
+#if 0
+ /* Now splice in the new member pointer type. */
+ if (main_type)
+ {
+ /* This type was not "smashed". */
+ TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
+ TYPE_CHAIN (main_type) = mtype;
+ }
+#endif
+
+ return mtype;
+}
+
+struct type *
+lookup_method_type (type, domain, args)
+ struct type *type, *domain, **args;
+{
+ register struct type *mtype = TYPE_MAIN_VARIANT (type);
+ struct type *main_type;
+
+ main_type = mtype;
+ while (mtype)
+ {
+ if (TYPE_DOMAIN_TYPE (mtype) == domain)
+ {
+ struct type **t1 = args;
+ struct type **t2 = TYPE_ARG_TYPES (mtype);
+ if (t2)
+ {
+ int i;
+ for (i = 0; t1[i] != 0 && t1[i]->code != TYPE_CODE_VOID; i++)
+ if (t1[i] != t2[i])
+ break;
+ if (t1[i] == t2[i])
+ return mtype;
+ }
+ }
+ mtype = TYPE_NEXT_VARIANT (mtype);
+ }
+
+ /* This is the first time anyone wanted this member type. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ mtype = (struct type *) xmalloc (sizeof (struct type));
+ else
+ mtype = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+
+ bzero (mtype, sizeof (struct type));
+ if (main_type == 0)
+ main_type = mtype;
+ else
+ {
+ TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
+ TYPE_NEXT_VARIANT (main_type) = mtype;
+ }
+ TYPE_MAIN_VARIANT (mtype) = main_type;
+ TYPE_TARGET_TYPE (mtype) = type;
+ TYPE_DOMAIN_TYPE (mtype) = domain;
+ TYPE_ARG_TYPES (mtype) = args;
+ /* New type is permanent if type pointed to is permanent. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
+
+ /* In practice, this is never used. */
+ TYPE_LENGTH (mtype) = 1;
+ TYPE_CODE (mtype) = TYPE_CODE_METHOD;
+
+#if 0
+ /* Now splice in the new member pointer type. */
+ if (main_type)
+ {
+ /* This type was not "smashed". */
+ TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
+ TYPE_CHAIN (main_type) = mtype;
+ }
+#endif
+
+ return mtype;
+}
+
+/* Given a type TYPE, return a type which has offset OFFSET,
+ via_virtual VIA_VIRTUAL, and via_public VIA_PUBLIC.
+ May need to construct such a type if none exists. */
+struct type *
+lookup_basetype_type (type, offset, via_virtual, via_public)
+ struct type *type;
+ int offset;
+ int via_virtual, via_public;
+{
+ register struct type *btype = TYPE_MAIN_VARIANT (type);
+ struct type *main_type;
+
+ if (offset != 0)
+ {
+ printf ("Internal error: type offset non-zero in lookup_basetype_type");
+ offset = 0;
+ }
+
+ main_type = btype;
+ while (btype)
+ {
+ if (/* TYPE_OFFSET (btype) == offset
+ && */ TYPE_VIA_PUBLIC (btype) == via_public
+ && TYPE_VIA_VIRTUAL (btype) == via_virtual)
+ return btype;
+ btype = TYPE_NEXT_VARIANT (btype);
+ }
+
+ /* This is the first time anyone wanted this member type. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ btype = (struct type *) xmalloc (sizeof (struct type));
+ else
+ btype = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+
+ if (main_type == 0)
+ {
+ main_type = btype;
+ bzero (btype, sizeof (struct type));
+ TYPE_MAIN_VARIANT (btype) = main_type;
+ }
+ else
+ {
+ bcopy (main_type, btype, sizeof (struct type));
+ TYPE_NEXT_VARIANT (main_type) = btype;
+ }
+/* TYPE_OFFSET (btype) = offset; */
+ if (via_public)
+ TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_PUBLIC;
+ if (via_virtual)
+ TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_VIRTUAL;
+ /* New type is permanent if type pointed to is permanent. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ TYPE_FLAGS (btype) |= TYPE_FLAG_PERM;
+
+ /* In practice, this is never used. */
+ TYPE_LENGTH (btype) = 1;
+ TYPE_CODE (btype) = TYPE_CODE_STRUCT;
+
+ return btype;
+}
+
+/* Given a type TYPE, return a type of functions that return that type.
+ May need to construct such a type if this is the first use. */
+
+struct type *
+lookup_function_type (type)
+ struct type *type;
+{
+ register struct type *ptype = TYPE_FUNCTION_TYPE (type);
+ if (ptype) return ptype;
+
+ /* This is the first time anyone wanted a function returning a TYPE. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ ptype = (struct type *) xmalloc (sizeof (struct type));
+ else
+ ptype = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+
+ bzero (ptype, sizeof (struct type));
+ TYPE_TARGET_TYPE (ptype) = type;
+ TYPE_FUNCTION_TYPE (type) = ptype;
+ /* New type is permanent if type returned is permanent. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
+ TYPE_LENGTH (ptype) = 1;
+ TYPE_CODE (ptype) = TYPE_CODE_FUNC;
+ TYPE_NFIELDS (ptype) = 0;
+ return ptype;
+}
+
+/* Create an array type. Elements will be of type TYPE, and there will
+ be NUM of them.
+
+ Eventually this should be extended to take two more arguments which
+ specify the bounds of the array and the type of the index.
+ It should also be changed to be a "lookup" function, with the
+ appropriate data structures added to the type field.
+ Then read array type should call here. */
+
+struct type *
+create_array_type (element_type, number)
+ struct type *element_type;
+ int number;
+{
+ struct type *result_type = (struct type *)
+ obstack_alloc (symbol_obstack, sizeof (struct type));
+
+ bzero (result_type, sizeof (struct type));
+
+ TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
+ TYPE_TARGET_TYPE (result_type) = element_type;
+ TYPE_LENGTH (result_type) = number * TYPE_LENGTH (element_type);
+ TYPE_NFIELDS (result_type) = 1;
+ TYPE_FIELDS (result_type) =
+ (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field));
+ TYPE_FIELD_TYPE (result_type, 0) = builtin_type_int;
+ TYPE_VPTR_FIELDNO (result_type) = -1;
+
+ return result_type;
+}
+
+
+/* Smash TYPE to be a type of pointers to TO_TYPE.
+ If TO_TYPE is not permanent and has no pointer-type yet,
+ record TYPE as its pointer-type. */
+
+void
+smash_to_pointer_type (type, to_type)
+ struct type *type, *to_type;
+{
+ int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM);
+
+ bzero (type, sizeof (struct type));
+ TYPE_TARGET_TYPE (type) = to_type;
+ /* We assume the machine has only one representation for pointers! */
+ TYPE_LENGTH (type) = sizeof (char *);
+ TYPE_CODE (type) = TYPE_CODE_PTR;
+
+ TYPE_MAIN_VARIANT (type) = type;
+
+ if (type_permanent)
+ TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
+
+ if (TYPE_POINTER_TYPE (to_type) == 0
+ && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM)
+ || type_permanent))
+ {
+ TYPE_POINTER_TYPE (to_type) = type;
+ }
+}
+
+/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. */
+
+void
+smash_to_member_type (type, domain, to_type)
+ struct type *type, *domain, *to_type;
+{
+ bzero (type, sizeof (struct type));
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_DOMAIN_TYPE (type) = domain;
+
+ /* In practice, this is never needed. */
+ TYPE_LENGTH (type) = 1;
+ TYPE_CODE (type) = TYPE_CODE_MEMBER;
+
+ TYPE_MAIN_VARIANT (type) = lookup_member_type (domain, to_type);
+}
+
+/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE. */
+
+void
+smash_to_method_type (type, domain, to_type, args)
+ struct type *type, *domain, *to_type, **args;
+{
+ bzero (type, sizeof (struct type));
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_DOMAIN_TYPE (type) = domain;
+ TYPE_ARG_TYPES (type) = args;
+
+ /* In practice, this is never needed. */
+ TYPE_LENGTH (type) = 1;
+ TYPE_CODE (type) = TYPE_CODE_METHOD;
+
+ TYPE_MAIN_VARIANT (type) = lookup_method_type (domain, to_type, args);
+}
+
+/* Smash TYPE to be a type of reference to TO_TYPE.
+ If TO_TYPE is not permanent and has no pointer-type yet,
+ record TYPE as its pointer-type. */
+
+void
+smash_to_reference_type (type, to_type)
+ struct type *type, *to_type;
+{
+ int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM);
+
+ bzero (type, sizeof (struct type));
+ TYPE_TARGET_TYPE (type) = to_type;
+ /* We assume the machine has only one representation for pointers! */
+ TYPE_LENGTH (type) = sizeof (char *);
+ TYPE_CODE (type) = TYPE_CODE_REF;
+
+ TYPE_MAIN_VARIANT (type) = type;
+
+ if (type_permanent)
+ TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
+
+ if (TYPE_REFERENCE_TYPE (to_type) == 0
+ && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM)
+ || type_permanent))
+ {
+ TYPE_REFERENCE_TYPE (to_type) = type;
+ }
+}
+
+/* Smash TYPE to be a type of functions returning TO_TYPE.
+ If TO_TYPE is not permanent and has no function-type yet,
+ record TYPE as its function-type. */
+
+void
+smash_to_function_type (type, to_type)
+ struct type *type, *to_type;
+{
+ int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM);
+
+ bzero (type, sizeof (struct type));
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_LENGTH (type) = 1;
+ TYPE_CODE (type) = TYPE_CODE_FUNC;
+ TYPE_NFIELDS (type) = 0;
+
+ if (type_permanent)
+ TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
+
+ if (TYPE_FUNCTION_TYPE (to_type) == 0
+ && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM)
+ || type_permanent))
+ {
+ TYPE_FUNCTION_TYPE (to_type) = type;
+ }
+}
+
+/* Find which partial symtab on the partial_symtab_list contains
+ PC. Return 0 if none. */
+
+struct partial_symtab *
+find_pc_psymtab (pc)
+ register CORE_ADDR pc;
+{
+ register struct partial_symtab *ps;
+
+ for (ps = partial_symtab_list; ps; ps = ps->next)
+ if (pc >= ps->textlow && pc < ps->texthigh)
+ return ps;
+
+ return 0;
+}
+
+/* Find which partial symbol within a psymtab contains PC. Return 0
+ if none. Check all psymtabs if PSYMTAB is 0. */
+struct partial_symbol *
+find_pc_psymbol (psymtab, pc)
+ struct partial_symtab *psymtab;
+ CORE_ADDR pc;
+{
+ struct partial_symbol *best, *p;
+ int best_pc;
+
+ if (!psymtab)
+ psymtab = find_pc_psymtab (pc);
+ if (!psymtab)
+ return 0;
+
+ best_pc = psymtab->textlow - 1;
+
+ for (p = static_psymbols.list + psymtab->statics_offset;
+ (p - (static_psymbols.list + psymtab->statics_offset)
+ < psymtab->n_static_syms);
+ p++)
+ if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
+ && SYMBOL_CLASS (p) == LOC_BLOCK
+ && pc >= SYMBOL_VALUE (p)
+ && SYMBOL_VALUE (p) > best_pc)
+ {
+ best_pc = SYMBOL_VALUE (p);
+ best = p;
+ }
+ if (best_pc == psymtab->textlow - 1)
+ return 0;
+ return best;
+}
+
+
+static struct symbol *lookup_block_symbol ();
+
+/* Find the definition for a specified symbol name NAME
+ in namespace NAMESPACE, visible from lexical block BLOCK.
+ Returns the struct symbol pointer, or zero if no symbol is found.
+ C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
+ NAME is a field of the current implied argument `this'. If so set
+ *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero.
+ BLOCK_FOUND is set to the block in which NAME is found (in the case of
+ a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
+
+struct symbol *
+lookup_symbol (name, block, namespace, is_a_field_of_this)
+ char *name;
+ register struct block *block;
+ enum namespace namespace;
+ int *is_a_field_of_this;
+{
+ register int i, n;
+ register struct symbol *sym;
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct partial_symbol *psym;
+ struct blockvector *bv;
+
+ /* Search specified block and its superiors. */
+
+ while (block != 0)
+ {
+ sym = lookup_block_symbol (block, name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ return sym;
+ }
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ /* C++: If requested to do so by the caller,
+ check to see if NAME is a field of `this'. */
+ if (is_a_field_of_this)
+ {
+ struct value *v = value_of_this (0);
+
+ *is_a_field_of_this = 0;
+ if (v && check_field (v, name))
+ {
+ *is_a_field_of_this = 1;
+ return 0;
+ }
+ }
+
+ /* Now search all global blocks. Do the symtab's first, then
+ check the psymtab's */
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, 0);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ return sym;
+ }
+ }
+
+ /* Check for the possibility of the symbol being a global function
+ that is stored on the misc function vector. Eventually, all
+ global symbols might be resolved in this way. */
+
+ if (namespace == VAR_NAMESPACE)
+ {
+ int index = lookup_misc_func (name);
+
+ if (index == -1)
+ { /* Look for a mangled C++ name for NAME. */
+ int name_len = strlen (name);
+ for (index = misc_function_count; --index >= 0; )
+ /* Assume orginal name is prefix of mangled name. */
+ if (!strncmp (misc_function_vector[index].name, name, name_len))
+ {
+ char *demangled =
+ cplus_demangle(misc_function_vector[index].name, -1);
+ if (demangled != NULL)
+ {
+ int cond = strcmp (demangled, name);
+ free (demangled);
+ if (!cond)
+ break;
+ }
+ }
+ /* Loop terminates on no match with index == -1. */
+ }
+
+ if (index != -1)
+ {
+ ps = find_pc_psymtab (misc_function_vector[index].address);
+ if (ps && !ps->readin)
+ {
+ s = psymtab_to_symtab (ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, 0);
+ sym = lookup_block_symbol (block, name, namespace);
+ /* sym == 0 if symbol was found in the psymtab but not
+ in the symtab.
+ Return 0 to use the misc_function definition of "foo_".
+
+ This happens for Fortran "foo_" symbols,
+ which are "foo" in the symtab.
+
+ This can also happen if "asm" is used to make a
+ regular symbol but not a debugging symbol, e.g.
+ asm(".globl _main");
+ asm("_main:");
+ */
+
+ return sym;
+ }
+ }
+ }
+
+ if (psym = lookup_partial_symbol (name, 1, namespace))
+ {
+ ps = psym->pst;
+ s = psymtab_to_symtab(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, 0);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ fatal ("Internal: global symbol found in psymtab but not in symtab");
+ return sym;
+ }
+
+ /* Now search all per-file blocks.
+ Not strictly correct, but more useful than an error.
+ Do the symtabs first, then check the psymtabs */
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, 1);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ return sym;
+ }
+ }
+
+ if (psym = lookup_partial_symbol(name, 0, namespace))
+ {
+ ps = psym->pst;
+ s = psymtab_to_symtab(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, 1);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ fatal ("Internal: static symbol found in psymtab but not in symtab");
+ return sym;
+ }
+
+ return 0;
+}
+
+/* Look, in partial_symtab PST, for symbol NAME. Check the global
+ symbols if GLOBAL, the static symbols if not */
+
+static struct partial_symbol *
+lookup_partial_symbol (name, global, namespace)
+ register char *name;
+ register int global;
+ register enum namespace namespace;
+{
+ register struct partial_symbol *start, *psym;
+ register struct partial_symbol *top, *bottom, *center;
+ register struct partial_symtab *pst;
+ register int length;
+
+ if (global)
+ {
+ start = global_psymbols.list;
+ length = global_psymbols.next - start;
+ }
+ else
+ {
+ start = static_psymbols.list;
+ length = static_psymbols.next - start;
+ }
+
+ if (!length)
+ return (struct partial_symbol *) 0;
+
+ /* Binary search. This search is guarranteed to end with center
+ pointing at the earliest partial symbol with the correct
+ name. At that point *all* partial symbols with that name
+ will be checked against the correct namespace. */
+ bottom = start;
+ top = start + length - 1;
+ while (top > bottom)
+ {
+ center = bottom + (top - bottom) / 2;
+
+ assert (center < top);
+
+ if (strcmp (SYMBOL_NAME (center), name) >= 0)
+ top = center;
+ else
+ bottom = center + 1;
+ }
+ assert (top == bottom);
+
+ while (strcmp (SYMBOL_NAME (top), name) == 0)
+ {
+ if (!top->pst->readin && SYMBOL_NAMESPACE (top) == namespace)
+ return top;
+ top ++;
+ }
+
+ return (struct partial_symbol *) 0;
+}
+
+/* Look for a symbol in block BLOCK. */
+
+static struct symbol *
+lookup_block_symbol (block, name, namespace)
+ register struct block *block;
+ char *name;
+ enum namespace namespace;
+{
+ register int bot, top, inc;
+ register struct symbol *sym, *parameter_sym;
+
+ top = BLOCK_NSYMS (block);
+ bot = 0;
+
+ /* If the blocks's symbols were sorted, start with a binary search. */
+
+ if (BLOCK_SHOULD_SORT (block))
+ {
+ /* First, advance BOT to not far before
+ the first symbol whose name is NAME. */
+
+ while (1)
+ {
+ inc = (top - bot + 1);
+ /* No need to keep binary searching for the last few bits worth. */
+ if (inc < 4)
+ break;
+ inc = (inc >> 1) + bot;
+ sym = BLOCK_SYM (block, inc);
+ if (SYMBOL_NAME (sym)[0] < name[0])
+ bot = inc;
+ else if (SYMBOL_NAME (sym)[0] > name[0])
+ top = inc;
+ else if (strcmp (SYMBOL_NAME (sym), name) < 0)
+ bot = inc;
+ else
+ top = inc;
+ }
+
+ /* Now scan forward until we run out of symbols,
+ find one whose name is greater than NAME,
+ or find one we want.
+ If there is more than one symbol with the right name and namespace,
+ we return the first one. dbxread.c is careful to make sure
+ that if one is a register then it comes first. */
+
+ top = BLOCK_NSYMS (block);
+ while (bot < top)
+ {
+ sym = BLOCK_SYM (block, bot);
+ inc = SYMBOL_NAME (sym)[0] - name[0];
+ if (inc == 0)
+ inc = strcmp (SYMBOL_NAME (sym), name);
+ if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
+ return sym;
+ if (inc > 0)
+ return 0;
+ bot++;
+ }
+ return 0;
+ }
+
+ /* Here if block isn't sorted.
+ This loop is equivalent to the loop above,
+ but hacked greatly for speed.
+
+ Note that parameter symbols do not always show up last in the
+ list; this loop makes sure to take anything else other than
+ parameter symbols first; it only uses parameter symbols as a
+ last resort. Note that this only takes up extra computation
+ time on a match. */
+
+ parameter_sym = (struct symbol *) 0;
+ top = BLOCK_NSYMS (block);
+ inc = name[0];
+ while (bot < top)
+ {
+ sym = BLOCK_SYM (block, bot);
+ if (SYMBOL_NAME (sym)[0] == inc
+ && !strcmp (SYMBOL_NAME (sym), name)
+ && SYMBOL_NAMESPACE (sym) == namespace)
+ {
+ if (SYMBOL_CLASS (sym) == LOC_ARG
+ || SYMBOL_CLASS (sym) == LOC_REF_ARG
+ || SYMBOL_CLASS (sym) == LOC_REGPARM)
+ parameter_sym = sym;
+ else
+ return sym;
+ }
+ bot++;
+ }
+ return parameter_sym; /* Will be 0 if not found. */
+}
+
+/* Return the symbol for the function which contains a specified
+ lexical block, described by a struct block BL. */
+
+struct symbol *
+block_function (bl)
+ struct block *bl;
+{
+ while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
+ bl = BLOCK_SUPERBLOCK (bl);
+
+ return BLOCK_FUNCTION (bl);
+}
+
+/* Subroutine of find_pc_line */
+
+struct symtab *
+find_pc_symtab (pc)
+ register CORE_ADDR pc;
+{
+ register struct block *b;
+ struct blockvector *bv;
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+
+ /* Search all symtabs for one whose file contains our pc */
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, 0);
+ if (BLOCK_START (b) <= pc
+ && BLOCK_END (b) > pc)
+ break;
+ }
+
+ if (!s)
+ {
+ ps = find_pc_psymtab (pc);
+ if (ps && ps->readin)
+ fatal ("Internal error: pc in read in psymtab, but not in symtab.");
+
+ if (ps)
+ s = psymtab_to_symtab (ps);
+ }
+
+ return s;
+}
+
+/* Find the source file and line number for a given PC value.
+ Return a structure containing a symtab pointer, a line number,
+ and a pc range for the entire source line.
+ The value's .pc field is NOT the specified pc.
+ NOTCURRENT nonzero means, if specified pc is on a line boundary,
+ use the line that ends there. Otherwise, in that case, the line
+ that begins there is used. */
+
+struct symtab_and_line
+find_pc_line (pc, notcurrent)
+ CORE_ADDR pc;
+ int notcurrent;
+{
+ struct symtab *s;
+ register struct linetable *l;
+ register int len;
+ register int i;
+ register struct linetable_entry *item;
+ struct symtab_and_line value;
+ struct blockvector *bv;
+
+ /* Info on best line seen so far, and where it starts, and its file. */
+
+ int best_line = 0;
+ CORE_ADDR best_pc = 0;
+ CORE_ADDR best_end = 0;
+ struct symtab *best_symtab = 0;
+
+ /* Store here the first line number
+ of a file which contains the line at the smallest pc after PC.
+ If we don't find a line whose range contains PC,
+ we will use a line one less than this,
+ with a range from the start of that file to the first line's pc. */
+ int alt_line = 0;
+ CORE_ADDR alt_pc = 0;
+ struct symtab *alt_symtab = 0;
+
+ /* Info on best line seen in this file. */
+
+ int prev_line;
+ CORE_ADDR prev_pc;
+
+ /* Info on first line of this file. */
+
+ int first_line;
+ CORE_ADDR first_pc;
+
+ /* If this pc is not from the current frame,
+ it is the address of the end of a call instruction.
+ Quite likely that is the start of the following statement.
+ But what we want is the statement containing the instruction.
+ Fudge the pc to make sure we get that. */
+
+ if (notcurrent) pc -= 1;
+
+ s = find_pc_symtab (pc);
+ if (s == 0)
+ {
+ value.symtab = 0;
+ value.line = 0;
+ value.pc = pc;
+ value.end = 0;
+ return value;
+ }
+
+ bv = BLOCKVECTOR (s);
+
+ /* Look at all the symtabs that share this blockvector.
+ They all have the same apriori range, that we found was right;
+ but they have different line tables. */
+
+ for (; s && BLOCKVECTOR (s) == bv; s = s->next)
+ {
+ /* Find the best line in this symtab. */
+ l = LINETABLE (s);
+ len = l->nitems;
+ prev_line = -1;
+ first_line = -1;
+ for (i = 0; i < len; i++)
+ {
+ item = &(l->item[i]);
+
+ if (first_line < 0)
+ {
+ first_line = item->line;
+ first_pc = item->pc;
+ }
+ /* Return the last line that did not start after PC. */
+ if (pc >= item->pc)
+ {
+ prev_line = item->line;
+ prev_pc = item->pc;
+ }
+ else
+ break;
+ }
+
+ /* Is this file's best line closer than the best in the other files?
+ If so, record this file, and its best line, as best so far. */
+ if (prev_line >= 0 && prev_pc > best_pc)
+ {
+ best_pc = prev_pc;
+ best_line = prev_line;
+ best_symtab = s;
+ if (i < len)
+ best_end = item->pc;
+ else
+ best_end = 0;
+ }
+ /* Is this file's first line closer than the first lines of other files?
+ If so, record this file, and its first line, as best alternate. */
+ if (first_line >= 0 && first_pc > pc
+ && (alt_pc == 0 || first_pc < alt_pc))
+ {
+ alt_pc = first_pc;
+ alt_line = first_line;
+ alt_symtab = s;
+ }
+ }
+ if (best_symtab == 0)
+ {
+ value.symtab = alt_symtab;
+ value.line = alt_line - 1;
+ value.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0));
+ value.end = alt_pc;
+ }
+ else
+ {
+ value.symtab = best_symtab;
+ value.line = best_line;
+ value.pc = best_pc;
+ value.end = (best_end ? best_end
+ : (alt_pc ? alt_pc
+ : BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0))));
+ }
+ return value;
+}
+
+/* Find the PC value for a given source file and line number.
+ Returns zero for invalid line number.
+ The source file is specified with a struct symtab. */
+
+CORE_ADDR
+find_line_pc (symtab, line)
+ struct symtab *symtab;
+ int line;
+{
+ register struct linetable *l;
+ register int index;
+ int dummy;
+
+ if (symtab == 0)
+ return 0;
+ l = LINETABLE (symtab);
+ index = find_line_common(l, line, &dummy);
+ return index ? l->item[index].pc : 0;
+}
+
+/* Find the range of pc values in a line.
+ Store the starting pc of the line into *STARTPTR
+ and the ending pc (start of next line) into *ENDPTR.
+ Returns 1 to indicate success.
+ Returns 0 if could not find the specified line. */
+
+int
+find_line_pc_range (symtab, thisline, startptr, endptr)
+ struct symtab *symtab;
+ int thisline;
+ CORE_ADDR *startptr, *endptr;
+{
+ register struct linetable *l;
+ register int index;
+ int exact_match; /* did we get an exact linenumber match */
+ register CORE_ADDR prev_pc;
+ CORE_ADDR last_pc;
+
+ if (symtab == 0)
+ return 0;
+
+ l = LINETABLE (symtab);
+ index = find_line_common (l, thisline, &exact_match);
+ if (index)
+ {
+ *startptr = l->item[index].pc;
+ /* If we have not seen an entry for the specified line,
+ assume that means the specified line has zero bytes. */
+ if (!exact_match || index == l->nitems-1)
+ *endptr = *startptr;
+ else
+ /* Perhaps the following entry is for the following line.
+ It's worth a try. */
+ if (l->item[index+1].line == thisline + 1)
+ *endptr = l->item[index+1].pc;
+ else
+ *endptr = find_line_pc (symtab, thisline+1);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Given a line table and a line number, return the index into the line
+ table for the pc of the nearest line whose number is >= the specified one.
+ Return 0 if none is found. The value is never zero is it is an index.
+
+ Set *EXACT_MATCH nonzero if the value returned is an exact match. */
+
+static int
+find_line_common (l, lineno, exact_match)
+ register struct linetable *l;
+ register int lineno;
+ int *exact_match;
+{
+ register int i;
+ register int len;
+
+ /* BEST is the smallest linenumber > LINENO so far seen,
+ or 0 if none has been seen so far.
+ BEST_INDEX identifies the item for it. */
+
+ int best_index = 0;
+ int best = 0;
+
+ int nextline = -1;
+
+ if (lineno <= 0)
+ return 0;
+
+ len = l->nitems;
+ for (i = 0; i < len; i++)
+ {
+ register struct linetable_entry *item = &(l->item[i]);
+
+ if (item->line == lineno)
+ {
+ *exact_match = 1;
+ return i;
+ }
+
+ if (item->line > lineno && (best == 0 || item->line < best))
+ {
+ best = item->line;
+ best_index = i;
+ }
+ }
+
+ /* If we got here, we didn't get an exact match. */
+
+ *exact_match = 0;
+ return best_index;
+}
+
+int
+find_pc_line_pc_range (pc, startptr, endptr)
+ CORE_ADDR pc;
+ CORE_ADDR *startptr, *endptr;
+{
+ struct symtab_and_line sal;
+ sal = find_pc_line (pc, 0);
+ *startptr = sal.pc;
+ *endptr = sal.end;
+ return sal.symtab != 0;
+}
+
+/* Parse a string that specifies a line number.
+ Pass the address of a char * variable; that variable will be
+ advanced over the characters actually parsed.
+
+ The string can be:
+
+ LINENUM -- that line number in current file. PC returned is 0.
+ FILE:LINENUM -- that line in that file. PC returned is 0.
+ FUNCTION -- line number of openbrace of that function.
+ PC returned is the start of the function.
+ FILE:FUNCTION -- likewise, but prefer functions in that file.
+ *EXPR -- line in which address EXPR appears.
+
+ FUNCTION may be an undebuggable function found in misc_function_vector.
+
+ If the argument FUNFIRSTLINE is nonzero, we want the first line
+ of real code inside a function when a function is specified.
+
+ DEFAULT_SYMTAB specifies the file to use if none is specified.
+ It defaults to current_source_symtab.
+ DEFAULT_LINE specifies the line number to use for relative
+ line numbers (that start with signs). Defaults to current_source_line.
+
+ Note that it is possible to return zero for the symtab
+ if no file is validly specified. Callers must check that.
+ Also, the line number returned may be invalid. */
+
+struct symtabs_and_lines
+decode_line_1 (argptr, funfirstline, default_symtab, default_line)
+ char **argptr;
+ int funfirstline;
+ struct symtab *default_symtab;
+ int default_line;
+{
+ struct symtabs_and_lines decode_line_2 ();
+ struct symtabs_and_lines values;
+ struct symtab_and_line value;
+ register char *p, *p1;
+ register struct symtab *s;
+ register struct symbol *sym;
+ register CORE_ADDR pc;
+ register int i;
+ char *copy;
+ struct symbol *sym_class;
+ char *class_name, *method_name, *phys_name;
+ int method_counter;
+ int i1;
+ struct symbol **sym_arr;
+ struct type *t, *field;
+ char **physnames;
+
+ /* Defaults have defaults. */
+
+ if (default_symtab == 0)
+ {
+ default_symtab = current_source_symtab;
+ default_line = current_source_line;
+ }
+
+ /* See if arg is *PC */
+
+ if (**argptr == '*')
+ {
+ (*argptr)++;
+ pc = parse_and_eval_address_1 (argptr);
+ values.sals = (struct symtab_and_line *)
+ malloc (sizeof (struct symtab_and_line));
+ values.nelts = 1;
+ values.sals[0] = find_pc_line (pc, 0);
+ values.sals[0].pc = pc;
+ return values;
+ }
+
+ /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+
+ s = 0;
+
+ for (p = *argptr; *p; p++)
+ {
+ if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
+ break;
+ }
+ while (p[0] == ' ' || p[0] == '\t') p++;
+
+ if (p[0] == ':')
+ {
+
+ /* C++ */
+ if (p[1] ==':')
+ {
+ /* Extract the class name. */
+ p1 = p;
+ while (p != *argptr && p[-1] == ' ') --p;
+ copy = (char *) alloca (p - *argptr + 1);
+ bcopy (*argptr, copy, p - *argptr);
+ copy[p - *argptr] = 0;
+
+ /* Discard the class name from the arg. */
+ p = p1 + 2;
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0);
+
+ if (sym_class &&
+ (TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION))
+ {
+ /* Arg token is not digits => try it as a function name
+ Find the next token (everything up to end or next whitespace). */
+ p = *argptr;
+ while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++;
+ copy = (char *) alloca (p - *argptr + 1);
+ bcopy (*argptr, copy, p - *argptr);
+ copy[p - *argptr] = '\0';
+
+ /* no line number may be specified */
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ sym = 0;
+ i1 = 0; /* counter for the symbol array */
+ t = SYMBOL_TYPE (sym_class);
+ sym_arr = (struct symbol **) alloca(TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*));
+ physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*));
+
+ if (destructor_name_p (copy, t))
+ {
+ /* destructors are a special case. */
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, 0);
+ int len = TYPE_FN_FIELDLIST_LENGTH (t, 0) - 1;
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, len);
+ physnames[i1] = (char *)alloca (strlen (phys_name) + 1);
+ strcpy (physnames[i1], phys_name);
+ sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE, 0);
+ if (sym_arr[i1]) i1++;
+ }
+ else while (t)
+ {
+ class_name = TYPE_NAME (t);
+ /* Ignore this class if it doesn't have a name.
+ This prevents core dumps, but is just a workaround
+ because we might not find the function in
+ certain cases, such as
+ struct D {virtual int f();}
+ struct C : D {virtual int g();}
+ (in this case g++ 1.35.1- does not put out a name
+ for D as such, it defines type 19 (for example) in
+ the same stab as C, and then does a
+ .stabs "D:T19" and a .stabs "D:t19".
+ Thus
+ "break C::f" should not be looking for field f in
+ the class named D,
+ but just for the field f in the baseclasses of C
+ (no matter what their names).
+
+ However, I don't know how to replace the code below
+ that depends on knowing the name of D. */
+ if (class_name)
+ {
+ /* We just want the class name. In the context
+ of C++, stripping off "struct " is always
+ sensible. */
+ if (strncmp("struct ", class_name, 7) == 0)
+ class_name += 7;
+ if (strncmp("union ", class_name, 6) == 0)
+ class_name += 6;
+
+ sym_class = lookup_symbol (class_name, 0, STRUCT_NAMESPACE, 0);
+ for (method_counter = TYPE_NFN_FIELDS (SYMBOL_TYPE (sym_class)) - 1;
+ method_counter >= 0;
+ --method_counter)
+ {
+ int field_counter;
+ struct fn_field *f =
+ TYPE_FN_FIELDLIST1 (SYMBOL_TYPE (sym_class), method_counter);
+
+ method_name = TYPE_FN_FIELDLIST_NAME (SYMBOL_TYPE (sym_class), method_counter);
+ if (!strcmp (copy, method_name))
+ /* Find all the fields with that name. */
+ for (field_counter = TYPE_FN_FIELDLIST_LENGTH (SYMBOL_TYPE (sym_class), method_counter) - 1;
+ field_counter >= 0;
+ --field_counter)
+ {
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+ physnames[i1] = (char*) alloca (strlen (phys_name) + 1);
+ strcpy (physnames[i1], phys_name);
+ sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE, 0);
+ if (sym_arr[i1]) i1++;
+ }
+ }
+ }
+ if (TYPE_N_BASECLASSES (t))
+ t = TYPE_BASECLASS(t, 1);
+ else
+ break;
+ }
+
+ if (i1 == 1)
+ {
+ /* There is exactly one field with that name. */
+ sym = sym_arr[0];
+
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* Arg is the name of a function */
+ pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+ if (funfirstline)
+ SKIP_PROLOGUE (pc);
+ values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
+ values.nelts = 1;
+ values.sals[0] = find_pc_line (pc, 0);
+ values.sals[0].pc = (values.sals[0].end && values.sals[0].pc != pc) ? values.sals[0].end : pc;
+ }
+ else
+ {
+ values.nelts = 0;
+ }
+ return values;
+ }
+ if (i1 > 0)
+ {
+ /* There is more than one field with that name
+ (overloaded). Ask the user which one to use. */
+ return decode_line_2 (argptr, sym_arr, physnames,
+ i1, funfirstline);
+ }
+ else
+ error ("that class does not have any method named %s",copy);
+ }
+ else
+ error("no class, struct, or union named %s", copy );
+ }
+ /* end of C++ */
+
+
+ /* Extract the file name. */
+ p1 = p;
+ while (p != *argptr && p[-1] == ' ') --p;
+ copy = (char *) alloca (p - *argptr + 1);
+ bcopy (*argptr, copy, p - *argptr);
+ copy[p - *argptr] = 0;
+
+ /* Find that file's data. */
+ s = lookup_symtab (copy);
+ if (s == 0)
+ {
+ if (symtab_list == 0 && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ error ("No source file named %s.", copy);
+ }
+
+ /* Discard the file name from the arg. */
+ p = p1 + 1;
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+ }
+
+ /* S is specified file's symtab, or 0 if no file specified.
+ arg no longer contains the file name. */
+
+ /* Check whether arg is all digits (and sign) */
+
+ p = *argptr;
+ if (*p == '-' || *p == '+') p++;
+ while (*p >= '0' && *p <= '9')
+ p++;
+
+ if (p != *argptr && (*p == 0 || *p == ' ' || *p == '\t' || *p == ','))
+ {
+ /* We found a token consisting of all digits -- at least one digit. */
+ enum sign {none, plus, minus} sign = none;
+
+ /* This is where we need to make sure that we have good defaults.
+ We must guarrantee that this section of code is never executed
+ when we are called with just a function name, since
+ select_source_symtab calls us with such an argument */
+
+ if (s == 0 && default_symtab == 0)
+ {
+ if (symtab_list == 0 && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ select_source_symtab (0);
+ default_symtab = current_source_symtab;
+ default_line = current_source_line;
+ }
+
+ if (**argptr == '+')
+ sign = plus, (*argptr)++;
+ else if (**argptr == '-')
+ sign = minus, (*argptr)++;
+ value.line = atoi (*argptr);
+ switch (sign)
+ {
+ case plus:
+ if (p == *argptr)
+ value.line = 5;
+ if (s == 0)
+ value.line = default_line + value.line;
+ break;
+ case minus:
+ if (p == *argptr)
+ value.line = 15;
+ if (s == 0)
+ value.line = default_line - value.line;
+ else
+ value.line = 1;
+ break;
+ }
+
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+ if (s == 0)
+ s = default_symtab;
+ value.symtab = s;
+ value.pc = 0;
+ values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
+ values.sals[0] = value;
+ values.nelts = 1;
+ return values;
+ }
+
+ /* Arg token is not digits => try it as a function name
+ Find the next token (everything up to end or next whitespace). */
+ p = *argptr;
+ while (*p && *p != ' ' && *p != '\t' && *p != ',') p++;
+ copy = (char *) alloca (p - *argptr + 1);
+ bcopy (*argptr, copy, p - *argptr);
+ copy[p - *argptr] = 0;
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ /* Look up that token as a function.
+ If file specified, use that file's per-file block to start with. */
+
+ if (s == 0)
+ /* use current file as default if none is specified. */
+ s = default_symtab;
+
+ sym = lookup_symbol (copy, s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1) : 0,
+ VAR_NAMESPACE, 0);
+
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* Arg is the name of a function */
+ pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
+ if (funfirstline)
+ SKIP_PROLOGUE (pc);
+ value = find_pc_line (pc, 0);
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+ /* Convex: no need to suppress code on first line, if any */
+ value.pc = pc;
+#else
+ value.pc = (value.end && value.pc != pc) ? value.end : pc;
+#endif
+ values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
+ values.sals[0] = value;
+ values.nelts = 1;
+ return values;
+ }
+
+ if (sym)
+ error ("%s is not a function.", copy);
+
+ if (symtab_list == 0 && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+
+ if ((i = lookup_misc_func (copy)) >= 0)
+ {
+ value.symtab = 0;
+ value.line = 0;
+ value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
+ if (funfirstline)
+ SKIP_PROLOGUE (value.pc);
+ values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
+ values.sals[0] = value;
+ values.nelts = 1;
+ return values;
+ }
+
+ error ("Function %s not defined.", copy);
+}
+
+struct symtabs_and_lines
+decode_line_spec (string, funfirstline)
+ char *string;
+ int funfirstline;
+{
+ struct symtabs_and_lines sals;
+ if (string == 0)
+ error ("Empty line specification.");
+ sals = decode_line_1 (&string, funfirstline,
+ current_source_symtab, current_source_line);
+ if (*string)
+ error ("Junk at end of line specification: %s", string);
+ return sals;
+}
+
+/* Given a list of NELTS symbols in sym_arr (with corresponding
+ mangled names in physnames), return a list of lines to operate on
+ (ask user if necessary). */
+struct symtabs_and_lines
+decode_line_2 (argptr, sym_arr, physnames, nelts, funfirstline)
+ char **argptr;
+ struct symbol *sym_arr[];
+ char *physnames[];
+ int nelts;
+ int funfirstline;
+{
+ char *getenv();
+ struct symtabs_and_lines values, return_values;
+ register CORE_ADDR pc;
+ char *args, *arg1, *command_line_input ();
+ int i;
+ char *prompt;
+
+ values.sals = (struct symtab_and_line *) alloca (nelts * sizeof(struct symtab_and_line));
+ return_values.sals = (struct symtab_and_line *) malloc (nelts * sizeof(struct symtab_and_line));
+
+ i = 0;
+ printf("[0] cancel\n[1] all\n");
+ while (i < nelts)
+ {
+ if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
+ {
+ /* Arg is the name of a function */
+ pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i]))
+ + FUNCTION_START_OFFSET;
+ if (funfirstline)
+ SKIP_PROLOGUE (pc);
+ values.sals[i] = find_pc_line (pc, 0);
+ values.sals[i].pc = (values.sals[i].end && values.sals[i].pc != pc) ? values.sals[i].end : pc;
+ printf("[%d] file:%s; line number:%d\n",
+ (i+2), values.sals[i].symtab->filename, values.sals[i].line);
+ }
+ else printf ("?HERE\n");
+ i++;
+ }
+
+ if ((prompt = getenv ("PS2")) == NULL)
+ {
+ prompt = ">";
+ }
+ printf("%s ",prompt);
+ fflush(stdout);
+
+ args = command_line_input (0, 0);
+
+ if (args == 0)
+ error_no_arg ("one or more choice numbers");
+
+ i = 0;
+ while (*args)
+ {
+ int num;
+
+ arg1 = args;
+ while (*arg1 >= '0' && *arg1 <= '9') arg1++;
+ if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
+ error ("Arguments must be choice numbers.");
+
+ num = atoi (args);
+
+ if (num == 0)
+ error ("cancelled");
+ else if (num == 1)
+ {
+ bcopy (values.sals, return_values.sals, (nelts * sizeof(struct symtab_and_line)));
+ return_values.nelts = nelts;
+ return return_values;
+ }
+
+ if (num > nelts + 2)
+ {
+ printf ("No choice number %d.\n", num);
+ }
+ else
+ {
+ num -= 2;
+ if (values.sals[num].pc)
+ {
+ return_values.sals[i++] = values.sals[num];
+ values.sals[num].pc = 0;
+ }
+ else
+ {
+ printf ("duplicate request for %d ignored.\n", num);
+ }
+ }
+
+ args = arg1;
+ while (*args == ' ' || *args == '\t') args++;
+ }
+ return_values.nelts = i;
+ return return_values;
+}
+
+/* hash a symbol ("hashpjw" from Aho, Sethi & Ullman, p.436) */
+
+int
+hash_symbol(str)
+ register char *str;
+{
+ register unsigned int h = 0, g;
+ register unsigned char c;
+
+ while (c = *(unsigned char *)str++) {
+ h = (h << 4) + c;
+ if (g = h & 0xf0000000) {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+ return ((int)h);
+}
+
+/* Return the index of misc function named NAME. */
+
+int
+lookup_misc_func (name)
+ register char *name;
+{
+ register int i = hash_symbol(name) & (MISC_FUNC_HASH_SIZE - 1);
+
+ if (misc_function_vector == 0)
+ error("No symbol file");
+
+ i = misc_function_hash_tab[i];
+ while (i >= 0)
+ {
+ if (strcmp(misc_function_vector[i].name, name) == 0)
+ break;
+ i = misc_function_vector[i].next;
+ }
+ return (i);
+}
+
+/*
+ * Slave routine for sources_info. Force line breaks at ,'s.
+ */
+static void
+output_source_filename (name, next)
+char *name;
+int next;
+{
+ static int column = 0;
+
+ if (column != 0 && column + strlen (name) >= 70)
+ {
+ printf_filtered ("\n");
+ column = 0;
+ }
+ else if (column != 0)
+ {
+ printf_filtered (" ");
+ column++;
+ }
+ printf_filtered ("%s", name);
+ column += strlen (name);
+ if (next)
+ {
+ printf_filtered (",");
+ column++;
+ }
+
+ if (!next) column = 0;
+}
+
+static void
+sources_info ()
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register int column = 0;
+
+ if (symtab_list == 0 && partial_symtab_list == 0)
+ {
+ printf ("No symbol table is loaded.\n");
+ return;
+ }
+
+ printf_filtered ("Source files for which symbols have been read in:\n\n");
+
+ for (s = symtab_list; s; s = s->next)
+ output_source_filename (s->filename, s->next);
+ printf_filtered ("\n\n");
+
+ printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
+
+ for (ps = partial_symtab_list; ps; ps = ps->next)
+ if (!ps->readin)
+ output_source_filename (ps->filename, ps->next);
+ printf_filtered ("\n");
+}
+
+/* List all symbols (if REGEXP is 0) or all symbols matching REGEXP.
+ If CLASS is zero, list all symbols except functions and type names.
+ If CLASS is 1, list only functions.
+ If CLASS is 2, list only type names. */
+
+static void sort_block_syms ();
+
+static void
+list_symbols (regexp, class)
+ char *regexp;
+ int class;
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct blockvector *bv;
+ struct blockvector *prev_bv = 0;
+ register struct block *b;
+ register int i, j;
+ register struct symbol *sym;
+ struct partial_symbol *psym, *bound;
+ char *val;
+ static char *classnames[]
+ = {"variable", "function", "type", "method"};
+ int print_count = 0;
+ int found_in_file = 0;
+
+ if (regexp)
+ if (val = (char *) re_comp (regexp))
+ error ("Invalid regexp: %s", val);
+
+ /* Search through the partial_symtab_list *first* for all symbols
+ matching the regexp. That way we don't have to reproduce all of
+ the machinery below. */
+ for (psym = global_psymbols.list, bound = global_psymbols.next; ;
+ psym = static_psymbols.list, bound = static_psymbols.next)
+ {
+ for (; psym < bound; ++psym)
+ {
+ if (psym->pst->readin)
+ continue;
+
+ QUIT;
+ /* If it would match (logic taken from loop below)
+ load the file and go on to the next one */
+ if ((regexp == 0 || re_exec (SYMBOL_NAME (psym)))
+ && ((class == 0 && SYMBOL_CLASS (psym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (psym) != LOC_BLOCK)
+ || (class == 1 && SYMBOL_CLASS (psym) == LOC_BLOCK)
+ || (class == 2 && SYMBOL_CLASS (psym) == LOC_TYPEDEF)
+ || (class == 3 && SYMBOL_CLASS (psym) == LOC_BLOCK)))
+ psymtab_to_symtab(psym->pst);
+ }
+ if (psym == static_psymbols.next)
+ break;
+ }
+
+ /* Printout here so as to get after the "Reading in symbols"
+ messages which will be generated above. */
+ printf_filtered (regexp
+ ? "All %ss matching regular expression \"%s\":\n"
+ : "All defined %ss:\n",
+ classnames[class],
+ regexp);
+
+ /* Here, *if* the class is correct (function only, right now), we
+ should search through the misc function vector for symbols that
+ match and call find_pc_psymtab on them. If find_pc_psymtab returns
+ 0, don't worry about it (already read in or no debugging info). */
+
+ if (class == 1)
+ {
+ for (i = 0; i < misc_function_count; i++)
+ if (regexp == 0 || re_exec (misc_function_vector[i].name))
+ {
+ ps = find_pc_psymtab (misc_function_vector[i].address);
+ if (ps && !ps->readin)
+ psymtab_to_symtab (ps);
+ }
+ }
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ found_in_file = 0;
+ bv = BLOCKVECTOR (s);
+ /* Often many files share a blockvector.
+ Scan each blockvector only once so that
+ we don't get every symbol many times.
+ It happens that the first symtab in the list
+ for any given blockvector is the main file. */
+ if (bv != prev_bv)
+ for (i = 0; i < 2; i++)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ /* Skip the sort if this block is always sorted. */
+ if (!BLOCK_SHOULD_SORT (b))
+ sort_block_syms (b);
+ for (j = 0; j < BLOCK_NSYMS (b); j++)
+ {
+ QUIT;
+ sym = BLOCK_SYM (b, j);
+ if ((regexp == 0 || re_exec (SYMBOL_NAME (sym)))
+ && ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (sym) != LOC_BLOCK)
+ || (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ || (class == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
+ {
+ if (!found_in_file)
+ {
+ printf_filtered ("\nFile %s:\n", s->filename);
+ print_count += 2;
+ }
+ found_in_file = 1;
+ if (class != 2 && i == 1)
+ printf_filtered ("static ");
+ if (class == 2
+ && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+ printf_filtered ("typedef ");
+
+ if (class < 3)
+ {
+ type_print (SYMBOL_TYPE (sym),
+ (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ ? "" : SYMBOL_NAME (sym)),
+ stdout, 0);
+
+ if (class == 2
+ && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE
+ && (TYPE_NAME ((SYMBOL_TYPE (sym))) == 0
+ || 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (sym))),
+ SYMBOL_NAME (sym))))
+ printf_filtered (" %s", SYMBOL_NAME (sym));
+
+ printf_filtered (";\n");
+ }
+ else
+ {
+# if 0
+ char buf[1024];
+ type_print_base (TYPE_FN_FIELD_TYPE(t, i), stdout, 0, 0);
+ type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), stdout, 0);
+ sprintf (buf, " %s::", TYPE_NAME (t));
+ type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), buf, name, stdout);
+# endif
+ }
+ }
+ }
+ }
+ prev_bv = bv;
+ }
+}
+
+static void
+variables_info (regexp)
+ char *regexp;
+{
+ list_symbols (regexp, 0);
+}
+
+static void
+functions_info (regexp)
+ char *regexp;
+{
+ list_symbols (regexp, 1);
+}
+
+static void
+types_info (regexp)
+ char *regexp;
+{
+ list_symbols (regexp, 2);
+}
+
+#if 0
+/* Tiemann says: "info methods was never implemented." */
+static void
+methods_info (regexp)
+ char *regexp;
+{
+ list_symbols (regexp, 3);
+}
+#endif /* 0 */
+
+/* Call sort_block_syms to sort alphabetically the symbols of one block. */
+
+static int
+compare_symbols (s1, s2)
+ struct symbol **s1, **s2;
+{
+ /* Names that are less should come first. */
+ register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2));
+ if (namediff != 0) return namediff;
+ /* For symbols of the same name, registers should come first. */
+ return ((SYMBOL_CLASS (*s2) == LOC_REGISTER)
+ - (SYMBOL_CLASS (*s1) == LOC_REGISTER));
+}
+
+static void
+sort_block_syms (b)
+ register struct block *b;
+{
+ qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+ sizeof (struct symbol *), compare_symbols);
+}
+
+/* Initialize the standard C scalar types. */
+
+static
+struct type *
+init_type (code, length, uns, name)
+ enum type_code code;
+ int length, uns;
+ char *name;
+{
+ register struct type *type;
+
+ type = (struct type *) xmalloc (sizeof (struct type));
+ bzero (type, sizeof *type);
+ TYPE_MAIN_VARIANT (type) = type;
+ TYPE_CODE (type) = code;
+ TYPE_LENGTH (type) = length;
+ TYPE_FLAGS (type) = uns ? TYPE_FLAG_UNSIGNED : 0;
+ TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
+ TYPE_NFIELDS (type) = 0;
+ TYPE_NAME (type) = name;
+
+ /* C++ fancies. */
+ TYPE_NFN_FIELDS (type) = 0;
+ TYPE_N_BASECLASSES (type) = 0;
+ TYPE_BASECLASSES (type) = 0;
+ return type;
+}
+
+/* Return Nonzero if block a is lexically nested within block b,
+ or if a and b have the same pc range.
+ Return zero otherwise. */
+int
+contained_in (a, b)
+ struct block *a, *b;
+{
+ if (!a || !b)
+ return 0;
+ return a->startaddr >= b->startaddr && a->endaddr <= b->endaddr;
+}
+
+
+/* Helper routine for make_symbol_completion_list. */
+
+int return_val_size, return_val_index;
+char **return_val;
+
+void
+completion_list_add_symbol (symname)
+ char *symname;
+{
+ if (return_val_index + 3 > return_val_size)
+ return_val =
+ (char **)xrealloc (return_val,
+ (return_val_size *= 2) * sizeof (char *));
+
+ return_val[return_val_index] =
+ (char *)xmalloc (1 + strlen (symname));
+
+ strcpy (return_val[return_val_index], symname);
+
+ return_val[++return_val_index] = (char *)NULL;
+}
+
+/* Return a NULL terminated array of all symbols (regardless of class) which
+ begin by matching TEXT. If the answer is no symbols, then the return value
+ is an array which contains only a NULL pointer.
+
+ Problem: All of the symbols have to be copied because readline
+ frees them. I'm not going to worry about this; hopefully there
+ won't be that many. */
+
+char **
+make_symbol_completion_list (text)
+ char *text;
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct blockvector *bv;
+ struct blockvector *prev_bv = 0;
+ register struct block *b, *surrounding_static_block;
+ extern struct block *get_selected_block ();
+ register int i, j;
+ register struct symbol *sym;
+ struct partial_symbol *psym;
+
+ int text_len = strlen (text);
+ return_val_size = 100;
+ return_val_index = 0;
+ return_val =
+ (char **)xmalloc ((1 + return_val_size) *sizeof (char *));
+ return_val[0] = (char *)NULL;
+
+ /* Look through the partial symtabs for all symbols which begin
+ by matching TEXT. Add each one that you find to the list. */
+
+ for (ps = partial_symtab_list; ps; ps = ps->next)
+ {
+ /* If the psymtab's been read in we'll get it when we search
+ through the blockvector. */
+ if (ps->readin) continue;
+
+ for (psym = global_psymbols.list + ps->globals_offset;
+ psym < (global_psymbols.list + ps->globals_offset
+ + ps->n_global_syms);
+ psym++)
+ {
+ QUIT; /* If interrupted, then quit. */
+ if ((strncmp (SYMBOL_NAME (psym), text, text_len) == 0))
+ completion_list_add_symbol (SYMBOL_NAME (psym));
+ }
+
+ for (psym = static_psymbols.list + ps->statics_offset;
+ psym < (static_psymbols.list + ps->statics_offset
+ + ps->n_static_syms);
+ psym++)
+ {
+ QUIT;
+ if ((strncmp (SYMBOL_NAME (psym), text, text_len) == 0))
+ completion_list_add_symbol (SYMBOL_NAME (psym));
+ }
+ }
+
+ /* At this point scan through the misc function vector and add each
+ symbol you find to the list. Eventually we want to ignore
+ anything that isn't a text symbol (everything else will be
+ handled by the psymtab code above). */
+
+ for (i = 0; i < misc_function_count; i++)
+ if (!strncmp (text, misc_function_vector[i].name, text_len))
+ completion_list_add_symbol (misc_function_vector[i].name);
+
+ /* Search upwards from currently selected frame (so that we can
+ complete on local vars. */
+ for (b = get_selected_block (); b; b = BLOCK_SUPERBLOCK (b))
+ {
+ if (!BLOCK_SUPERBLOCK (b))
+ surrounding_static_block = b; /* For elmin of dups */
+
+ /* Also catch fields of types defined in this places which
+ match our text string. Only complete on types visible
+ from current context. */
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ register struct symbol *sym = BLOCK_SYM (b, i);
+
+ if (!strncmp (SYMBOL_NAME (sym), text, text_len))
+ completion_list_add_symbol (SYMBOL_NAME (sym));
+
+ if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ struct type *t = SYMBOL_TYPE (sym);
+ enum type_code c = TYPE_CODE (t);
+
+ if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
+ for (j = 0; j < TYPE_NFIELDS (t); j++)
+ if (TYPE_FIELD_NAME (t, j) &&
+ !strncmp (TYPE_FIELD_NAME (t, j), text, text_len))
+ completion_list_add_symbol (TYPE_FIELD_NAME (t, j));
+ }
+ }
+ }
+
+ /* Go through the symtabs and check the externs and statics for
+ symbols which match. */
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 0);
+
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ if (!strncmp (SYMBOL_NAME (BLOCK_SYM (b, i)), text, text_len))
+ completion_list_add_symbol (SYMBOL_NAME (BLOCK_SYM (b, i)));
+ }
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1);
+
+ /* Don't do this block twice. */
+ if (b == surrounding_static_block) continue;
+
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ if (!strncmp (SYMBOL_NAME (BLOCK_SYM (b, i)), text, text_len))
+ completion_list_add_symbol (SYMBOL_NAME (BLOCK_SYM (b, i)));
+ }
+
+ return (return_val);
+}
+
+void
+_initialize_symtab ()
+{
+ add_info ("variables", variables_info,
+ "All global and static variable names, or those matching REGEXP.");
+ add_info ("functions", functions_info,
+ "All function names, or those matching REGEXP.");
+ add_info ("types", types_info,
+ "All types names, or those matching REGEXP.");
+#if 0
+ add_info ("methods", methods_info,
+ "All method names, or those matching REGEXP::REGEXP.\n\
+If the class qualifier is ommited, it is assumed to be the current scope.\n\
+If the first REGEXP is ommited, then all methods matching the second REGEXP\n\
+are listed.");
+#endif
+ add_info ("sources", sources_info,
+ "Source files in the program.");
+
+ obstack_init (symbol_obstack);
+ obstack_init (psymbol_obstack);
+
+ builtin_type_void = init_type (TYPE_CODE_VOID, 1, 0, "void");
+
+ builtin_type_float = init_type (TYPE_CODE_FLT, sizeof (float), 0, "float");
+ builtin_type_double = init_type (TYPE_CODE_FLT, sizeof (double), 0, "double");
+
+ builtin_type_char = init_type (TYPE_CODE_INT, sizeof (char), 0, "char");
+ builtin_type_short = init_type (TYPE_CODE_INT, sizeof (short), 0, "short");
+ builtin_type_long = init_type (TYPE_CODE_INT, sizeof (long), 0, "long");
+ builtin_type_int = init_type (TYPE_CODE_INT, sizeof (int), 0, "int");
+
+ builtin_type_unsigned_char = init_type (TYPE_CODE_INT, sizeof (char), 1, "unsigned char");
+ builtin_type_unsigned_short = init_type (TYPE_CODE_INT, sizeof (short), 1, "unsigned short");
+ builtin_type_unsigned_long = init_type (TYPE_CODE_INT, sizeof (long), 1, "unsigned long");
+ builtin_type_unsigned_int = init_type (TYPE_CODE_INT, sizeof (int), 1, "unsigned int");
+#ifdef LONG_LONG
+ builtin_type_long_long =
+ init_type (TYPE_CODE_INT, sizeof (long long), 0, "long long");
+ builtin_type_unsigned_long_long =
+ init_type (TYPE_CODE_INT, sizeof (long long), 1, "unsigned long long");
+#endif
+}
+
diff --git a/gnu/usr.bin/kgdb/symtab.h b/gnu/usr.bin/kgdb/symtab.h
new file mode 100644
index 000000000000..fefed6001e5f
--- /dev/null
+++ b/gnu/usr.bin/kgdb/symtab.h
@@ -0,0 +1,384 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ *
+ * @(#)symtab.h 6.3 (Berkeley) 5/8/91
+ */
+
+/* Symbol table definitions for GDB.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <obstack.h>
+
+/* An obstack to hold objects that should be freed
+ when we load a new symbol table.
+ This includes the symbols made by dbxread
+ and the types that are not permanent. */
+
+extern struct obstack *symbol_obstack;
+extern struct obstack *psymbol_obstack;
+
+/* Some definitions and declarations to go with use of obstacks. */
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+extern char *xmalloc ();
+extern void free ();
+
+/* gdb can know one or several symbol tables at the same time;
+ the ultimate intent is to have one for each separately-compiled module.
+ Each such symbol table is recorded by a struct symtab, and they
+ are all chained together. */
+
+/* In addition, gdb can record any number of miscellaneous undebuggable
+ functions' addresses. In a system that appends _ to function names,
+ the _'s are removed from the names stored in this table. */
+
+/* Actually, the misc function list is used to store *all* of the
+ global symbols (text, data, bss, and abs). It is sometimes used
+ to figure out what symtabs to read in. The "type" field appears
+ never to be used. */
+
+enum misc_function_type {mf_unknown = 0, mf_text, mf_data, mf_bss, mf_abs};
+
+struct misc_function
+{
+ char *name;
+ CORE_ADDR address;
+ int next; /* index of next in this hash bucket */
+ unsigned char type; /* Really enum misc_function_type. */
+};
+
+/* Address and length of the vector recording all misc function names/addresses. */
+
+struct misc_function *misc_function_vector;
+int misc_function_count;
+#define MISC_FUNC_HASH_SIZE (2048)
+int misc_function_hash_tab[MISC_FUNC_HASH_SIZE];
+
+#include "symseg.h"
+
+/* Each source file is represented by a struct symtab. */
+/* These objects are chained through the `next' field. */
+
+struct symtab
+ {
+ /* Chain of all existing symtabs. */
+ struct symtab *next;
+ /* List of all symbol scope blocks for this symtab. */
+ struct blockvector *blockvector;
+ /* Table mapping core addresses to line numbers for this file. */
+ struct linetable *linetable;
+ /* Vector containing all types defined for this symtab. */
+ struct typevector *typevector;
+ /* Name of this source file. */
+ char *filename;
+ /* This component says how to free the data we point to:
+ free_contents => do a tree walk and free each object.
+ free_nothing => do nothing; some other symtab will free
+ the data this one uses.
+ free_linetable => free just the linetable. */
+ enum free_code {free_nothing, free_contents, free_linetable}
+ free_code;
+ /* Pointer to one block of storage to be freed, if nonzero. */
+ char *free_ptr;
+ /* Total number of lines found in source file. */
+ int nlines;
+ /* Array mapping line number to character position. */
+ int *line_charpos;
+ /* Language of this source file. */
+ enum language language;
+ /* String of version information. May be zero. */
+ char *version;
+ /* String of compilation information. May be zero. */
+ char *compilation;
+ /* Offset within loader symbol table
+ of first local symbol for this file. */
+ int ldsymoff;
+ /* Full name of file as found by searching the source path.
+ 0 if not yet known. */
+ char *fullname;
+ };
+
+/*
+ * Each source file that has not been fully read in is represented by
+ * a partial_symtab. This contains the information on where in the
+ * executable the debugging symbols for a specific file are, and a
+ * list of names of global symbols which are located in this file.
+ */
+struct partial_symtab
+{
+ /* Chain of all existing partial symtabs. */
+ struct partial_symtab *next;
+ /* Name of the source file which this partial_symtab defines */
+ char *filename;
+ /* Offset within loader symbol table of first local symbol for this
+ file and length (in bytes) of the section of the symbol table
+ devoted to this file's symbols (actually, the section bracketed
+ may contain more than just this files symbols
+ If ldsymlen is 0, the only reason for this things existence is
+ the dependency list below. Nothing else will happen when it is
+ read in. */
+ int ldsymoff, ldsymlen;
+ /* Range of text addresses covered by this file; texthigh is the
+ beginning of the next section. */
+ int textlow, texthigh;
+ /* Non-zero if the symtab corresponding to this psymtab has been
+ readin */
+ unsigned char readin;
+ /* Array of pointers to all of the partial_symtab s which this one
+ depends one. Since this array can only be set to previous or
+ the current (?) psymtab, this dependency tree is guarranteed not
+ to have any loops. */
+ struct partial_symtab **dependencies;
+ int number_of_dependencies;
+ /* Global symbol list. This list will be sorted after readin to
+ improve access. Binary search will be the usual method of
+ finding a symbol within it. globals_offset is an integer offset
+ within ps_globals */
+ int globals_offset, n_global_syms;
+ /* Static symbol list. This list will *not* be sorted after readin;
+ to find a symbol in it, exhaustive search must be used. This is
+ reasonable because searches through this list will eventually
+ lead to either the read in of a files symbols for real (assumed
+ to take a *lot* of time; check) or an error (and we don't care
+ how long errors take). */
+ int statics_offset, n_static_syms;
+};
+
+/* This is the list of struct symtab's that gdb considers current. */
+
+struct symtab *symtab_list;
+
+/* This is the list of struct partial_symtab's that gdb may need to access */
+
+struct partial_symtab *partial_symtab_list;
+
+/* This symtab variable specifies the current file for printing source lines */
+
+struct symtab *current_source_symtab;
+
+/* This is the next line to print for listing source lines. */
+
+int current_source_line;
+
+#define BLOCKLIST(symtab) (symtab)->blockvector
+#define BLOCKVECTOR(symtab) (symtab)->blockvector
+
+#define TYPEVECTOR(symtab) (symtab)->typevector
+
+#define LINELIST(symtab) (symtab)->linetable
+#define LINETABLE(symtab) (symtab)->linetable
+
+/* Macros normally used to access components of symbol table structures. */
+
+#define BLOCKLIST_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKLIST_BLOCK(blocklist,n) (blocklist)->block[n]
+#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
+
+#define TYPEVECTOR_NTYPES(typelist) (typelist)->length
+#define TYPEVECTOR_TYPE(typelist,n) (typelist)->type[n]
+
+#define BLOCK_START(bl) (bl)->startaddr
+#define BLOCK_END(bl) (bl)->endaddr
+#define BLOCK_NSYMS(bl) (bl)->nsyms
+#define BLOCK_SYM(bl, n) (bl)->sym[n]
+#define BLOCK_FUNCTION(bl) (bl)->function
+#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
+#define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag
+
+/* Nonzero if symbols of block BL should be sorted alphabetically. */
+#define BLOCK_SHOULD_SORT(bl) ((bl)->nsyms >= 40)
+
+#define SYMBOL_NAME(symbol) (symbol)->name
+#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
+#define SYMBOL_CLASS(symbol) (symbol)->class
+#define SYMBOL_VALUE(symbol) (symbol)->value.value
+#define SYMBOL_VALUE_BYTES(symbol) (symbol)->value.bytes
+#define SYMBOL_BLOCK_VALUE(symbol) (symbol)->value.block
+#define SYMBOL_TYPE(symbol) (symbol)->type
+
+/* Some macros for bitfields. */
+#define B_SET(a,x) (a[x>>5] |= (1 << (x&31)))
+#define B_CLR(a,x) (a[x>>5] &= ~(1 << (x&31)))
+#define B_TST(a,x) (a[x>>5] & (1 << (x&31)))
+
+#define TYPE_NAME(thistype) (thistype)->name
+#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
+#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
+#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
+#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
+#define TYPE_MAIN_VARIANT(thistype) (thistype)->main_variant
+#define TYPE_NEXT_VARIANT(thistype) (thistype)->next_variant
+#define TYPE_LENGTH(thistype) (thistype)->length
+#define TYPE_FLAGS(thistype) (thistype)->flags
+#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
+#define TYPE_CODE(thistype) (thistype)->code
+#define TYPE_NFIELDS(thistype) (thistype)->nfields
+#define TYPE_FIELDS(thistype) (thistype)->fields
+/* C++ */
+#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
+#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
+#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
+#define TYPE_FN_FIELDS(thistype) (thistype)->fn_fields
+#define TYPE_NFN_FIELDS(thistype) (thistype)->nfn_fields
+#define TYPE_NFN_FIELDS_TOTAL(thistype) (thistype)->nfn_fields_total
+#define TYPE_BASECLASSES(thistype) (thistype)->baseclasses
+#define TYPE_ARG_TYPES(thistype) (thistype)->arg_types
+#define TYPE_BASECLASS(thistype,index) (thistype)->baseclasses[index]
+#define TYPE_N_BASECLASSES(thistype) (thistype)->n_baseclasses
+#define TYPE_VIA_PUBLIC(thistype) ((thistype)->flags & TYPE_FLAG_VIA_PUBLIC)
+#define TYPE_VIA_VIRTUAL(thistype) ((thistype)->flags & TYPE_FLAG_VIA_VIRTUAL)
+
+#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
+#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
+#define TYPE_FIELD_NAME(thistype, n) (thistype)->fields[n].name
+#define TYPE_FIELD_VALUE(thistype, n) (* (int*) &(thistype)->fields[n].type)
+#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
+#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
+#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
+
+#define TYPE_FIELD_PRIVATE_BITS(thistype) (thistype)->private_field_bits
+#define TYPE_FIELD_PROTECTED_BITS(thistype) (thistype)->protected_field_bits
+#define SET_TYPE_FIELD_PRIVATE(thistype, n) B_SET ((thistype)->private_field_bits, (n))
+#define SET_TYPE_FIELD_PROTECTED(thistype, n) B_SET ((thistype)->protected_field_bits, (n))
+#define TYPE_FIELD_PRIVATE(thistype, n) B_TST((thistype)->private_field_bits, (n))
+#define TYPE_FIELD_PROTECTED(thistype, n) B_TST((thistype)->protected_field_bits, (n))
+
+#define TYPE_HAS_DESTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_DESTRUCTOR)
+#define TYPE_HAS_CONSTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_CONSTRUCTOR)
+
+#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1)
+#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize)
+
+#define TYPE_FN_FIELDLISTS(thistype) (thistype)->fn_fieldlists
+#define TYPE_FN_FIELDLIST(thistype, n) (thistype)->fn_fieldlists[n]
+#define TYPE_FN_FIELDLIST1(thistype, n) (thistype)->fn_fieldlists[n].fn_fields
+#define TYPE_FN_FIELDLIST_NAME(thistype, n) (thistype)->fn_fieldlists[n].name
+#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) (thistype)->fn_fieldlists[n].length
+
+#define TYPE_FN_FIELD(thistype, n) (thistype)[n]
+#define TYPE_FN_FIELD_NAME(thistype, n) (thistype)[n].name
+#define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type
+#define TYPE_FN_FIELD_ARGS(thistype, n) (thistype)[n].args
+#define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname
+#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) ((thistype)[n].voffset < 0)
+#define TYPE_FN_FIELD_STATIC_P(thistype, n) ((thistype)[n].voffset > 0)
+#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1)
+
+#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits
+#define TYPE_FN_PROTECTED_BITS(thistype) (thistype).protected_fn_field_bits
+#define SET_TYPE_FN_PRIVATE(thistype, n) B_SET ((thistype).private_fn_field_bits, n)
+#define SET_TYPE_FN_PROTECTED(thistype, n) B_SET ((thistype).protected_fn_field_bits, n)
+#define TYPE_FN_PRIVATE(thistype, n) B_TST ((thistype).private_fn_field_bits, n)
+#define TYPE_FN_PROTECTED(thistype, n) B_TST ((thistype).protected_fn_field_bits, n)
+
+/* Functions that work on the objects described above */
+
+extern struct symtab *lookup_symtab ();
+extern struct symbol *lookup_symbol ();
+extern struct type *lookup_typename ();
+extern struct type *lookup_unsigned_typename ();
+extern struct type *lookup_struct ();
+extern struct type *lookup_union ();
+extern struct type *lookup_enum ();
+extern struct type *lookup_struct_elt_type ();
+extern struct type *lookup_pointer_type ();
+extern struct type *lookup_function_type ();
+extern struct type *lookup_basetype_type ();
+extern struct type *create_array_type ();
+extern struct symbol *block_function ();
+extern struct symbol *find_pc_function ();
+extern int find_pc_partial_function ();
+extern struct partial_symtab *find_pc_psymtab ();
+extern struct symtab *find_pc_symtab ();
+extern struct partial_symbol *find_pc_psymbol ();
+extern int find_pc_misc_function ();
+
+/* C++ stuff. */
+extern struct type *lookup_reference_type ();
+extern struct type *lookup_member_type ();
+extern struct type *lookup_class ();
+/* end of C++ stuff. */
+
+extern struct type *builtin_type_void;
+extern struct type *builtin_type_char;
+extern struct type *builtin_type_short;
+extern struct type *builtin_type_int;
+extern struct type *builtin_type_long;
+extern struct type *builtin_type_unsigned_char;
+extern struct type *builtin_type_unsigned_short;
+extern struct type *builtin_type_unsigned_int;
+extern struct type *builtin_type_unsigned_long;
+extern struct type *builtin_type_float;
+extern struct type *builtin_type_double;
+
+#ifdef LONG_LONG
+extern struct type *builtin_type_long_long;
+extern struct type *builtin_type_unsigned_long_long;
+
+#ifndef BUILTIN_TYPE_LONGEST
+#define BUILTIN_TYPE_LONGEST builtin_type_long_long
+#endif
+
+#ifndef BUILTIN_TYPE_UNSIGNED_LONGEST
+#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long_long
+#endif
+
+#else /* LONG_LONG */
+
+#ifndef BUILTIN_TYPE_LONGEST
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+#endif
+
+#ifndef BUILTIN_TYPE_UNSIGNED_LONGEST
+#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long
+#endif
+
+#endif
+
+struct symtab_and_line
+{
+ struct symtab *symtab;
+ int line;
+ CORE_ADDR pc;
+ CORE_ADDR end;
+};
+
+struct symtabs_and_lines
+{
+ struct symtab_and_line *sals;
+ int nelts;
+};
+
+/* Given a pc value, return line number it is in.
+ Second arg nonzero means if pc is on the boundary
+ use the previous statement's line number. */
+
+struct symtab_and_line find_pc_line ();
+
+/* Given a string, return the line specified by it.
+ For commands like "list" and "breakpoint". */
+
+struct symtabs_and_lines decode_line_spec ();
+struct symtabs_and_lines decode_line_spec_1 ();
+struct symtabs_and_lines decode_line_1 ();
diff --git a/gnu/usr.bin/kgdb/utils.c b/gnu/usr.bin/kgdb/utils.c
new file mode 100644
index 000000000000..6f462fc40c66
--- /dev/null
+++ b/gnu/usr.bin/kgdb/utils.c
@@ -0,0 +1,1094 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ *
+ * /home/ncvs/src/gnu/usr.bin/kgdb/utils.c,v 1.2 1994/11/07 08:19:13 davidg Exp;
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)utils.c 6.4 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* General utility routines for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "param.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include "defs.h"
+#ifdef HAVE_TERMIO
+#include <termio.h>
+#endif
+
+/* If this definition isn't overridden by the header files, assume
+ that isatty and fileno exist on this system. */
+#ifndef ISATTY
+#define ISATTY(FP) (isatty (fileno (FP)))
+#endif
+
+extern FILE *instream;
+
+void error ();
+void fatal ();
+
+/* Chain of cleanup actions established with make_cleanup,
+ to be executed if an error happens. */
+
+static struct cleanup *cleanup_chain;
+
+/* Nonzero means a quit has been requested. */
+
+int quit_flag;
+
+/* Nonzero means quit immediately if Control-C is typed now,
+ rather than waiting until QUIT is executed. */
+
+int immediate_quit;
+
+/* Add a new cleanup to the cleanup_chain,
+ and return the previous chain pointer
+ to be passed later to do_cleanups or discard_cleanups.
+ Args are FUNCTION to clean up with, and ARG to pass to it. */
+
+struct cleanup *
+make_cleanup (function, arg)
+ void (*function) ();
+ int arg;
+{
+ register struct cleanup *new
+ = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+ register struct cleanup *old_chain = cleanup_chain;
+
+ new->next = cleanup_chain;
+ new->function = function;
+ new->arg = arg;
+ cleanup_chain = new;
+
+ return old_chain;
+}
+
+/* Discard cleanups and do the actions they describe
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+do_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ (*ptr->function) (ptr->arg);
+ cleanup_chain = ptr->next;
+ free (ptr);
+ }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+discard_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ cleanup_chain = ptr->next;
+ free (ptr);
+ }
+}
+
+/* Set the cleanup_chain to 0, and return the old cleanup chain. */
+struct cleanup *
+save_cleanups ()
+{
+ struct cleanup *old_chain = cleanup_chain;
+
+ cleanup_chain = 0;
+ return old_chain;
+}
+
+/* Restore the cleanup chain from a previously saved chain. */
+void
+restore_cleanups (chain)
+ struct cleanup *chain;
+{
+ cleanup_chain = chain;
+}
+
+/* This function is useful for cleanups.
+ Do
+
+ foo = xmalloc (...);
+ old_chain = make_cleanup (free_current_contents, &foo);
+
+ to arrange to free the object thus allocated. */
+
+void
+free_current_contents (location)
+ char **location;
+{
+ free (*location);
+}
+
+/* Generally useful subroutines used throughout the program. */
+
+/* Like malloc but get error if no storage available. */
+
+char *
+xmalloc (size)
+ long size;
+{
+ register char *val = (char *) malloc (size);
+ if (!val)
+ fatal ("virtual memory exhausted.", 0);
+ return val;
+}
+
+/* Like realloc but get error if no storage available. */
+
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ long size;
+{
+ register char *val = (char *) realloc (ptr, size);
+ if (!val)
+ fatal ("virtual memory exhausted.", 0);
+ return val;
+}
+
+/* Print the system error message for errno, and also mention STRING
+ as the file name for which the error was encountered.
+ Then return to command level. */
+
+void
+perror_with_name (string)
+ char *string;
+{
+ extern int sys_nerr;
+ extern int errno;
+ char *err;
+ char *combined;
+
+ if (errno < sys_nerr)
+ err = sys_errlist[errno];
+ else
+ err = "unknown error";
+
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ error ("%s.", combined);
+}
+
+/* Print the system error message for ERRCODE, and also mention STRING
+ as the file name for which the error was encountered. */
+
+void
+print_sys_errmsg (string, errcode)
+ char *string;
+ int errcode;
+{
+ extern int sys_nerr;
+ char *err;
+ char *combined;
+
+ if (errcode < sys_nerr)
+ err = sys_errlist[errcode];
+ else
+ err = "unknown error";
+
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ printf ("%s.\n", combined);
+}
+
+void
+quit ()
+{
+#ifdef HAVE_TERMIO
+ ioctl (fileno (stdout), TCFLSH, 1);
+#else /* not HAVE_TERMIO */
+ ioctl (fileno (stdout), TIOCFLUSH, 0);
+#endif /* not HAVE_TERMIO */
+#ifdef TIOCGPGRP
+ error ("Quit");
+#else
+ error ("Quit (expect signal %d when inferior is resumed)", SIGINT);
+#endif /* TIOCGPGRP */
+}
+
+/* Control C comes here */
+
+void
+request_quit ()
+{
+ extern int remote_debugging;
+
+ quit_flag = 1;
+
+#ifdef USG
+ /* Restore the signal handler. */
+ signal (SIGINT, request_quit);
+#endif
+
+ if (immediate_quit)
+ quit();
+}
+
+/* Print an error message and return to command level.
+ STRING is the error message, used as a fprintf string,
+ and ARG is passed as an argument to it. */
+
+void
+error (string, arg1, arg2, arg3)
+ char *string;
+ int arg1, arg2, arg3;
+{
+ terminal_ours (); /* Should be ok even if no inf. */
+ fflush (stdout);
+ fprintf (stderr, string, arg1, arg2, arg3);
+ fprintf (stderr, "\n");
+ return_to_top_level ();
+}
+
+/* Print an error message and exit reporting failure.
+ This is for a error that we cannot continue from.
+ STRING and ARG are passed to fprintf. */
+
+void
+fatal (string, arg)
+ char *string;
+ int arg;
+{
+ fprintf (stderr, "gdb: ");
+ fprintf (stderr, string, arg);
+ fprintf (stderr, "\n");
+ exit (1);
+}
+
+/* Print an error message and exit, dumping core.
+ STRING is a printf-style control string, and ARG is a corresponding
+ argument. */
+void
+fatal_dump_core (string, arg)
+ char *string;
+ int arg;
+{
+ /* "internal error" is always correct, since GDB should never dump
+ core, no matter what the input. */
+ fprintf (stderr, "gdb internal error: ");
+ fprintf (stderr, string, arg);
+ fprintf (stderr, "\n");
+ signal (SIGQUIT, SIG_DFL);
+ kill (getpid (), SIGQUIT);
+ /* We should never get here, but just in case... */
+ exit (1);
+}
+
+/* Make a copy of the string at PTR with SIZE characters
+ (and add a null character at the end in the copy).
+ Uses malloc to get the space. Returns the address of the copy. */
+
+char *
+savestring (ptr, size)
+ char *ptr;
+ int size;
+{
+ register char *p = (char *) xmalloc (size + 1);
+ bcopy (ptr, p, size);
+ p[size] = 0;
+ return p;
+}
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+ register char *val = (char *) xmalloc (len);
+ strcpy (val, s1);
+ strcat (val, s2);
+ strcat (val, s3);
+ return val;
+}
+
+void
+print_spaces (n, file)
+ register int n;
+ register FILE *file;
+{
+ while (n-- > 0)
+ fputc (' ', file);
+}
+
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+ Takes three args which are given to printf to print the question.
+ The first, a control string, should end in "? ".
+ It should not say how to answer, because we do that. */
+
+int
+query (ctlstr, arg1, arg2)
+ char *ctlstr;
+{
+ register int answer;
+
+ /* Automatically answer "yes" if input is not from a terminal. */
+ if (!input_from_terminal_p ())
+ return 1;
+
+ while (1)
+ {
+ printf (ctlstr, arg1, arg2);
+ printf ("(y or n) ");
+ fflush (stdout);
+ answer = fgetc (stdin);
+ clearerr (stdin); /* in case of C-d */
+ if (answer != '\n')
+ while (fgetc (stdin) != '\n') clearerr (stdin);
+ if (answer >= 'a')
+ answer -= 040;
+ if (answer == 'Y')
+ return 1;
+ if (answer == 'N')
+ return 0;
+ printf ("Please answer y or n.\n");
+ }
+}
+
+/* Parse a C escape sequence. STRING_PTR points to a variable
+ containing a pointer to the string to parse. That pointer
+ is updated past the characters we use. The value of the
+ escape sequence is returned.
+
+ A negative value means the sequence \ newline was seen,
+ which is supposed to be equivalent to nothing at all.
+
+ If \ is followed by a null character, we return a negative
+ value and leave the string pointer pointing at the null character.
+
+ If \ is followed by 000, we return 0 and leave the string pointer
+ after the zeros. A value of 0 does not mean end of string. */
+
+int
+parse_escape (string_ptr)
+ char **string_ptr;
+{
+ register int c = *(*string_ptr)++;
+ switch (c)
+ {
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+ case 'e':
+ return 033;
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case '\n':
+ return -2;
+ case 0:
+ (*string_ptr)--;
+ return 0;
+ case '^':
+ c = *(*string_ptr)++;
+ if (c == '\\')
+ c = parse_escape (string_ptr);
+ if (c == '?')
+ return 0177;
+ return (c & 0200) | (c & 037);
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ register int i = c - '0';
+ register int count = 0;
+ while (++count < 3)
+ {
+ if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+ {
+ i *= 8;
+ i += c - '0';
+ }
+ else
+ {
+ (*string_ptr)--;
+ break;
+ }
+ }
+ return i;
+ }
+ default:
+ return c;
+ }
+}
+
+/* Print the character CH on STREAM as part of the contents
+ of a literal string whose delimiter is QUOTER. */
+
+void
+printchar (ch, stream, quoter)
+ unsigned char ch;
+ FILE *stream;
+ int quoter;
+{
+ register int c = ch;
+ if (c < 040 || c >= 0177)
+ switch (c)
+ {
+ case '\n':
+ fputs_filtered ("\\n", stream);
+ break;
+ case '\b':
+ fputs_filtered ("\\b", stream);
+ break;
+ case '\t':
+ fputs_filtered ("\\t", stream);
+ break;
+ case '\f':
+ fputs_filtered ("\\f", stream);
+ break;
+ case '\r':
+ fputs_filtered ("\\r", stream);
+ break;
+ case '\033':
+ fputs_filtered ("\\e", stream);
+ break;
+ case '\007':
+ fputs_filtered ("\\a", stream);
+ break;
+ default:
+ fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
+ break;
+ }
+ else
+ {
+ if (c == '\\' || c == quoter)
+ fputs_filtered ("\\", stream);
+ fprintf_filtered (stream, "%c", c);
+ }
+}
+
+static int lines_per_page, lines_printed, chars_per_line, chars_printed;
+
+/* Set values of page and line size. */
+static void
+set_screensize_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char *p = arg;
+ char *p1;
+ int tolinesize = lines_per_page;
+ int tocharsize = chars_per_line;
+
+ if (p == 0)
+ error_no_arg ("set screensize");
+
+ while (*p >= '0' && *p <= '9')
+ p++;
+
+ if (*p && *p != ' ' && *p != '\t')
+ error ("Non-integral argument given to \"set screensize\".");
+
+ tolinesize = atoi (arg);
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ if (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9')
+ p1++;
+
+ if (*p1)
+ error ("Non-integral second argument given to \"set screensize\".");
+
+ tocharsize = atoi (p);
+ }
+
+ lines_per_page = tolinesize;
+ chars_per_line = tocharsize;
+}
+
+static void
+instream_cleanup(stream)
+ FILE *stream;
+{
+ instream = stream;
+}
+
+static void
+prompt_for_continue ()
+{
+ if (ISATTY(stdin) && ISATTY(stdout))
+ {
+ struct cleanup *old_chain = make_cleanup(instream_cleanup, instream);
+ char *cp, *gdb_readline();
+
+ instream = stdin;
+ immediate_quit++;
+ if (cp = gdb_readline ("---Type <return> to continue---"))
+ free(cp);
+ chars_printed = lines_printed = 0;
+ immediate_quit--;
+ do_cleanups(old_chain);
+ }
+}
+
+/* Reinitialize filter; ie. tell it to reset to original values. */
+
+void
+reinitialize_more_filter ()
+{
+ lines_printed = 0;
+ chars_printed = 0;
+}
+
+static void
+screensize_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (arg)
+ error ("\"info screensize\" does not take any arguments.");
+
+ if (!lines_per_page)
+ printf ("Output more filtering is disabled.\n");
+ else
+ {
+ printf ("Output more filtering is enabled with\n");
+ printf ("%d lines per page and %d characters per line.\n",
+ lines_per_page, chars_per_line);
+ }
+}
+
+/* Like fputs but pause after every screenful.
+ Unlike fputs, fputs_filtered does not return a value.
+ It is OK for LINEBUFFER to be NULL, in which case just don't print
+ anything.
+
+ Note that a longjmp to top level may occur in this routine
+ (since prompt_for_continue may do so) so this routine should not be
+ called when cleanups are not in place. */
+
+void
+fputs_filtered (linebuffer, stream)
+ char *linebuffer;
+ FILE *stream;
+{
+ char *lineptr;
+
+ if (linebuffer == 0)
+ return;
+
+ /* Don't do any filtering if it is disabled. */
+ if (stream != stdout || !ISATTY(stdout) || lines_per_page == 0)
+ {
+ fputs (linebuffer, stream);
+ return;
+ }
+
+ /* Go through and output each character. Show line extension
+ when this is necessary; prompt user for new page when this is
+ necessary. */
+
+ lineptr = linebuffer;
+ while (*lineptr)
+ {
+ /* Possible new page. */
+ if (lines_printed >= lines_per_page - 1)
+ prompt_for_continue ();
+
+ while (*lineptr && *lineptr != '\n')
+ {
+ /* Print a single line. */
+ if (*lineptr == '\t')
+ {
+ putc ('\t', stream);
+ /* Shifting right by 3 produces the number of tab stops
+ we have already passed, and then adding one and
+ shifting left 3 advances to the next tab stop. */
+ chars_printed = ((chars_printed >> 3) + 1) << 3;
+ lineptr++;
+ }
+ else
+ {
+ putc (*lineptr, stream);
+ chars_printed++;
+ lineptr++;
+ }
+
+ if (chars_printed >= chars_per_line)
+ {
+ chars_printed = 0;
+ lines_printed++;
+ /* Possible new page. */
+ if (lines_printed >= lines_per_page - 1)
+ prompt_for_continue ();
+ }
+ }
+
+ if (*lineptr == '\n')
+ {
+ lines_printed++;
+ putc ('\n', stream);
+ lineptr++;
+ chars_printed = 0;
+ }
+ }
+}
+
+/* fputs_demangled is a variant of fputs_filtered that
+ demangles g++ names.*/
+
+void
+fputs_demangled (linebuffer, stream, arg_mode)
+ char *linebuffer;
+ FILE *stream;
+{
+#ifdef __STDC__
+ extern char *cplus_demangle (const char *, int);
+#else
+ extern char *cplus_demangle ();
+#endif
+#define SYMBOL_MAX 1024
+
+#define SYMBOL_CHAR(c) (isascii(c) && (isalnum(c) || (c) == '_' || (c) == '$'))
+
+ char buf[SYMBOL_MAX+1];
+ char *p;
+
+ if (linebuffer == NULL)
+ return;
+
+ p = linebuffer;
+
+ while ( *p != (char) 0 ) {
+ int i = 0;
+
+ /* collect non-interesting characters into buf */
+ while ( *p != (char) 0 && !SYMBOL_CHAR(*p) ) {
+ buf[i++] = *p;
+ p++;
+ }
+ if (i > 0) {
+ /* output the non-interesting characters without demangling */
+ buf[i] = (char) 0;
+ fputs_filtered(buf, stream);
+ i = 0; /* reset buf */
+ }
+
+ /* and now the interesting characters */
+ while (i < SYMBOL_MAX && *p != (char) 0 && SYMBOL_CHAR(*p) ) {
+ buf[i++] = *p;
+ p++;
+ }
+ buf[i] = (char) 0;
+ if (i > 0) {
+ char * result;
+
+ if ( (result = cplus_demangle(buf, arg_mode)) != NULL ) {
+ fputs_filtered(result, stream);
+ free(result);
+ }
+ else {
+ fputs_filtered(buf, stream);
+ }
+ }
+ }
+}
+
+/* Print ARG1, ARG2, and ARG3 on stdout using format FORMAT. If this
+ information is going to put the amount written since the last call
+ to INIIALIZE_MORE_FILTER or the last page break over the page size,
+ print out a pause message and do a gdb_readline to get the users
+ permision to continue.
+
+ Unlike fprintf, this function does not return a value.
+
+ Note that this routine has a restriction that the length of the
+ final output line must be less than 255 characters *or* it must be
+ less than twice the size of the format string. This is a very
+ arbitrary restriction, but it is an internal restriction, so I'll
+ put it in. This means that the %s format specifier is almost
+ useless; unless the caller can GUARANTEE that the string is short
+ enough, fputs_filtered should be used instead.
+
+ Note also that a longjmp to top level may occur in this routine
+ (since prompt_for_continue may do so) so this routine should not be
+ called when cleanups are not in place. */
+
+void
+fprintf_filtered (stream, format, arg1, arg2, arg3, arg4, arg5, arg6)
+ FILE *stream;
+ char *format;
+ int arg1, arg2, arg3, arg4, arg5, arg6;
+{
+ static char *linebuffer = (char *) 0;
+ static int line_size;
+ int format_length = strlen (format);
+ int numchars;
+
+ /* Allocated linebuffer for the first time. */
+ if (!linebuffer)
+ {
+ linebuffer = (char *) xmalloc (255);
+ line_size = 255;
+ }
+
+ /* Reallocate buffer to a larger size if this is necessary. */
+ if (format_length * 2 > line_size)
+ {
+ line_size = format_length * 2;
+
+ /* You don't have to copy. */
+ free (linebuffer);
+ linebuffer = (char *) xmalloc (line_size);
+ }
+
+ /* This won't blow up if the restrictions described above are
+ followed. */
+ (void) sprintf (linebuffer, format, arg1, arg2, arg3, arg4, arg5, arg6);
+
+ fputs_filtered (linebuffer, stream);
+}
+
+void
+printf_filtered (format, arg1, arg2, arg3, arg4, arg5, arg6)
+ char *format;
+ int arg1, arg2, arg3, arg4, arg5, arg6;
+{
+ fprintf_filtered (stdout, format, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+/* Print N spaces. */
+void
+print_spaces_filtered (n, stream)
+ int n;
+ FILE *stream;
+{
+ register char *s = (char *) alloca (n + 1);
+ register char *t = s;
+
+ while (n--)
+ *t++ = ' ';
+ *t = '\0';
+
+ fputs_filtered (s, stream);
+}
+
+
+#ifdef USG
+bcopy (from, to, count)
+char *from, *to;
+{
+ memcpy (to, from, count);
+}
+
+bcmp (from, to, count)
+{
+ return (memcmp (to, from, count));
+}
+
+bzero (to, count)
+char *to;
+{
+ while (count--)
+ *to++ = 0;
+}
+
+getwd (buf)
+char *buf;
+{
+ getcwd (buf, MAXPATHLEN);
+}
+
+char *
+index (s, c)
+ char *s;
+{
+ char *strchr ();
+ return strchr (s, c);
+}
+
+char *
+rindex (s, c)
+ char *s;
+{
+ char *strrchr ();
+ return strrchr (s, c);
+}
+
+#ifndef USG
+char *sys_siglist[32] = {
+ "SIG0",
+ "SIGHUP",
+ "SIGINT",
+ "SIGQUIT",
+ "SIGILL",
+ "SIGTRAP",
+ "SIGIOT",
+ "SIGEMT",
+ "SIGFPE",
+ "SIGKILL",
+ "SIGBUS",
+ "SIGSEGV",
+ "SIGSYS",
+ "SIGPIPE",
+ "SIGALRM",
+ "SIGTERM",
+ "SIGUSR1",
+ "SIGUSR2",
+ "SIGCLD",
+ "SIGPWR",
+ "SIGWIND",
+ "SIGPHONE",
+ "SIGPOLL",
+};
+#endif
+
+/* Queue routines */
+
+struct queue {
+ struct queue *forw;
+ struct queue *back;
+};
+
+insque (item, after)
+struct queue *item;
+struct queue *after;
+{
+ item->forw = after->forw;
+ after->forw->back = item;
+
+ item->back = after;
+ after->forw = item;
+}
+
+remque (item)
+struct queue *item;
+{
+ item->forw->back = item->back;
+ item->back->forw = item->forw;
+}
+#endif /* USG */
+
+#ifdef USG
+/* There is too much variation in Sys V signal numbers and names, so
+ we must initialize them at runtime. */
+static char undoc[] = "(undocumented)";
+
+char *sys_siglist[NSIG];
+#endif /* USG */
+
+extern struct cmd_list_element *setlist;
+
+void
+_initialize_utils ()
+{
+ int i;
+ add_cmd ("screensize", class_support, set_screensize_command,
+ "Change gdb's notion of the size of the output screen.\n\
+The first argument is the number of lines on a page.\n\
+The second argument (optional) is the number of characters on a line.",
+ &setlist);
+ add_info ("screensize", screensize_info,
+ "Show gdb's current notion of the size of the output screen.");
+
+ /* These defaults will be used if we are unable to get the correct
+ values from termcap. */
+ lines_per_page = 24;
+ chars_per_line = 80;
+ /* Initialize the screen height and width from termcap. */
+ {
+ int termtype = getenv ("TERM");
+
+ /* Positive means success, nonpositive means failure. */
+ int status;
+
+ /* 2048 is large enough for all known terminals, according to the
+ GNU termcap manual. */
+ char term_buffer[2048];
+
+ if (termtype)
+ {
+ status = tgetent (term_buffer, termtype);
+ if (status > 0)
+ {
+ int val;
+
+ val = tgetnum ("li");
+ if (val >= 0)
+ lines_per_page = val;
+ else
+ /* The number of lines per page is not mentioned
+ in the terminal description. This probably means
+ that paging is not useful (e.g. emacs shell window),
+ so disable paging. */
+ lines_per_page = 0;
+
+ val = tgetnum ("co");
+ if (val >= 0)
+ chars_per_line = val;
+ }
+ }
+ }
+
+#ifdef USG
+ /* Initialize signal names. */
+ for (i = 0; i < NSIG; i++)
+ sys_siglist[i] = undoc;
+
+#ifdef SIGHUP
+ sys_siglist[SIGHUP ] = "SIGHUP";
+#endif
+#ifdef SIGINT
+ sys_siglist[SIGINT ] = "SIGINT";
+#endif
+#ifdef SIGQUIT
+ sys_siglist[SIGQUIT ] = "SIGQUIT";
+#endif
+#ifdef SIGILL
+ sys_siglist[SIGILL ] = "SIGILL";
+#endif
+#ifdef SIGTRAP
+ sys_siglist[SIGTRAP ] = "SIGTRAP";
+#endif
+#ifdef SIGIOT
+ sys_siglist[SIGIOT ] = "SIGIOT";
+#endif
+#ifdef SIGEMT
+ sys_siglist[SIGEMT ] = "SIGEMT";
+#endif
+#ifdef SIGFPE
+ sys_siglist[SIGFPE ] = "SIGFPE";
+#endif
+#ifdef SIGKILL
+ sys_siglist[SIGKILL ] = "SIGKILL";
+#endif
+#ifdef SIGBUS
+ sys_siglist[SIGBUS ] = "SIGBUS";
+#endif
+#ifdef SIGSEGV
+ sys_siglist[SIGSEGV ] = "SIGSEGV";
+#endif
+#ifdef SIGSYS
+ sys_siglist[SIGSYS ] = "SIGSYS";
+#endif
+#ifdef SIGPIPE
+ sys_siglist[SIGPIPE ] = "SIGPIPE";
+#endif
+#ifdef SIGALRM
+ sys_siglist[SIGALRM ] = "SIGALRM";
+#endif
+#ifdef SIGTERM
+ sys_siglist[SIGTERM ] = "SIGTERM";
+#endif
+#ifdef SIGUSR1
+ sys_siglist[SIGUSR1 ] = "SIGUSR1";
+#endif
+#ifdef SIGUSR2
+ sys_siglist[SIGUSR2 ] = "SIGUSR2";
+#endif
+#ifdef SIGCLD
+ sys_siglist[SIGCLD ] = "SIGCLD";
+#endif
+#ifdef SIGCHLD
+ sys_siglist[SIGCHLD ] = "SIGCHLD";
+#endif
+#ifdef SIGPWR
+ sys_siglist[SIGPWR ] = "SIGPWR";
+#endif
+#ifdef SIGTSTP
+ sys_siglist[SIGTSTP ] = "SIGTSTP";
+#endif
+#ifdef SIGTTIN
+ sys_siglist[SIGTTIN ] = "SIGTTIN";
+#endif
+#ifdef SIGTTOU
+ sys_siglist[SIGTTOU ] = "SIGTTOU";
+#endif
+#ifdef SIGSTOP
+ sys_siglist[SIGSTOP ] = "SIGSTOP";
+#endif
+#ifdef SIGXCPU
+ sys_siglist[SIGXCPU ] = "SIGXCPU";
+#endif
+#ifdef SIGXFSZ
+ sys_siglist[SIGXFSZ ] = "SIGXFSZ";
+#endif
+#ifdef SIGVTALRM
+ sys_siglist[SIGVTALRM ] = "SIGVTALRM";
+#endif
+#ifdef SIGPROF
+ sys_siglist[SIGPROF ] = "SIGPROF";
+#endif
+#ifdef SIGWINCH
+ sys_siglist[SIGWINCH ] = "SIGWINCH";
+#endif
+#ifdef SIGCONT
+ sys_siglist[SIGCONT ] = "SIGCONT";
+#endif
+#ifdef SIGURG
+ sys_siglist[SIGURG ] = "SIGURG";
+#endif
+#ifdef SIGIO
+ sys_siglist[SIGIO ] = "SIGIO";
+#endif
+#ifdef SIGWIND
+ sys_siglist[SIGWIND ] = "SIGWIND";
+#endif
+#ifdef SIGPHONE
+ sys_siglist[SIGPHONE ] = "SIGPHONE";
+#endif
+#ifdef SIGPOLL
+ sys_siglist[SIGPOLL ] = "SIGPOLL";
+#endif
+#endif /* USG */
+}
diff --git a/gnu/usr.bin/kgdb/valarith.c b/gnu/usr.bin/kgdb/valarith.c
new file mode 100644
index 000000000000..8e76899884b8
--- /dev/null
+++ b/gnu/usr.bin/kgdb/valarith.c
@@ -0,0 +1,690 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)valarith.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Perform arithmetic and other operations on values, for GDB.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "expression.h"
+
+
+value value_x_binop ();
+value value_subscripted_rvalue ();
+
+value
+value_add (arg1, arg2)
+ value arg1, arg2;
+{
+ register value val, valint, valptr;
+ register int len;
+
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
+
+ if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+ || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR)
+ &&
+ (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT
+ || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT))
+ /* Exactly one argument is a pointer, and one is an integer. */
+ {
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
+ {
+ valptr = arg1;
+ valint = arg2;
+ }
+ else
+ {
+ valptr = arg2;
+ valint = arg1;
+ }
+ len = TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (valptr)));
+ if (len == 0) len = 1; /* For (void *) */
+ val = value_from_long (builtin_type_long,
+ value_as_long (valptr)
+ + (len * value_as_long (valint)));
+ VALUE_TYPE (val) = VALUE_TYPE (valptr);
+ return val;
+ }
+
+ return value_binop (arg1, arg2, BINOP_ADD);
+}
+
+value
+value_sub (arg1, arg2)
+ value arg1, arg2;
+{
+ register value val;
+
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+ &&
+ TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)
+ {
+ val = value_from_long (builtin_type_long,
+ value_as_long (arg1)
+ - TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) * value_as_long (arg2));
+ VALUE_TYPE (val) = VALUE_TYPE (arg1);
+ return val;
+ }
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
+ &&
+ VALUE_TYPE (arg1) == VALUE_TYPE (arg2))
+ {
+ val = value_from_long (builtin_type_long,
+ (value_as_long (arg1) - value_as_long (arg2))
+ / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))));
+ return val;
+ }
+
+ return value_binop (arg1, arg2, BINOP_SUB);
+}
+
+/* Return the value of ARRAY[IDX]. */
+
+value
+value_subscript (array, idx)
+ value array, idx;
+{
+ if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY
+ && VALUE_LVAL (array) != lval_memory)
+ return value_subscripted_rvalue (array, idx);
+ else
+ return value_ind (value_add (array, idx));
+}
+
+/* Return the value of EXPR[IDX], expr an aggregate rvalue
+ (eg, a vector register) */
+
+value
+value_subscripted_rvalue (array, idx)
+ value array, idx;
+{
+ struct type *elt_type = TYPE_TARGET_TYPE (VALUE_TYPE (array));
+ int elt_size = TYPE_LENGTH (elt_type);
+ int elt_offs = elt_size * value_as_long (idx);
+ value v;
+
+ if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array)))
+ error ("no such vector element");
+
+ if (TYPE_CODE (elt_type) == TYPE_CODE_FLT)
+ {
+ if (elt_size == sizeof (float))
+ v = value_from_double (elt_type, (double) *(float *)
+ (VALUE_CONTENTS (array) + elt_offs));
+ else
+ v = value_from_double (elt_type, *(double *)
+ (VALUE_CONTENTS (array) + elt_offs));
+ }
+ else
+ {
+ int offs;
+ union {int i; char c;} test;
+ test.i = 1;
+ if (test.c == 1)
+ offs = 0;
+ else
+ offs = sizeof (LONGEST) - elt_size;
+ v = value_from_long (elt_type, *(LONGEST *)
+ (VALUE_CONTENTS (array) + elt_offs - offs));
+ }
+
+ if (VALUE_LVAL (array) == lval_internalvar)
+ VALUE_LVAL (v) = lval_internalvar_component;
+ else
+ VALUE_LVAL (v) = not_lval;
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (array);
+ VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs;
+ VALUE_BITSIZE (v) = elt_size * 8;
+ return v;
+}
+
+/* Check to see if either argument is a structure. This is called so
+ we know whether to go ahead with the normal binop or look for a
+ user defined function instead.
+
+ For now, we do not overload the `=' operator. */
+
+int
+binop_user_defined_p (op, arg1, arg2)
+ enum exp_opcode op;
+ value arg1, arg2;
+{
+ if (op == BINOP_ASSIGN)
+ return 0;
+ return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_STRUCT
+ || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
+ && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT)
+ || (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_REF
+ && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_STRUCT));
+}
+
+/* Check to see if argument is a structure. This is called so
+ we know whether to go ahead with the normal unop or look for a
+ user defined function instead.
+
+ For now, we do not overload the `&' operator. */
+
+int unop_user_defined_p (op, arg1)
+ enum exp_opcode op;
+ value arg1;
+{
+ if (op == UNOP_ADDR)
+ return 0;
+ return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
+ || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
+ && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT));
+}
+
+/* We know either arg1 or arg2 is a structure, so try to find the right
+ user defined function. Create an argument vector that calls
+ arg1.operator @ (arg1,arg2) and return that value (where '@' is any
+ binary operator which is legal for GNU C++). */
+
+value
+value_x_binop (arg1, arg2, op, otherop)
+ value arg1, arg2;
+ int op, otherop;
+{
+ value * argvec;
+ char *ptr;
+ char tstr[13];
+ int static_memfuncp;
+
+ COERCE_ENUM (arg1);
+ COERCE_ENUM (arg2);
+
+ /* now we know that what we have to do is construct our
+ arg vector and find the right function to call it with. */
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
+ error ("friend functions not implemented yet");
+
+ argvec = (value *) alloca (sizeof (value) * 4);
+ argvec[1] = value_addr (arg1);
+ argvec[2] = arg2;
+ argvec[3] = 0;
+
+ /* make the right function name up */
+ strcpy(tstr, "operator __");
+ ptr = tstr+9;
+ switch (op)
+ {
+ case BINOP_ADD: strcpy(ptr,"+"); break;
+ case BINOP_SUB: strcpy(ptr,"-"); break;
+ case BINOP_MUL: strcpy(ptr,"*"); break;
+ case BINOP_DIV: strcpy(ptr,"/"); break;
+ case BINOP_REM: strcpy(ptr,"%"); break;
+ case BINOP_LSH: strcpy(ptr,"<<"); break;
+ case BINOP_RSH: strcpy(ptr,">>"); break;
+ case BINOP_LOGAND: strcpy(ptr,"&"); break;
+ case BINOP_LOGIOR: strcpy(ptr,"|"); break;
+ case BINOP_LOGXOR: strcpy(ptr,"^"); break;
+ case BINOP_AND: strcpy(ptr,"&&"); break;
+ case BINOP_OR: strcpy(ptr,"||"); break;
+ case BINOP_MIN: strcpy(ptr,"<?"); break;
+ case BINOP_MAX: strcpy(ptr,">?"); break;
+ case BINOP_ASSIGN: strcpy(ptr,"="); break;
+ case BINOP_ASSIGN_MODIFY:
+ switch (otherop)
+ {
+ case BINOP_ADD: strcpy(ptr,"+="); break;
+ case BINOP_SUB: strcpy(ptr,"-="); break;
+ case BINOP_MUL: strcpy(ptr,"*="); break;
+ case BINOP_DIV: strcpy(ptr,"/="); break;
+ case BINOP_REM: strcpy(ptr,"%="); break;
+ case BINOP_LOGAND: strcpy(ptr,"&="); break;
+ case BINOP_LOGIOR: strcpy(ptr,"|="); break;
+ case BINOP_LOGXOR: strcpy(ptr,"^="); break;
+ default:
+ error ("Invalid binary operation specified.");
+ }
+ break;
+ case BINOP_SUBSCRIPT: strcpy(ptr,"[]"); break;
+ case BINOP_EQUAL: strcpy(ptr,"=="); break;
+ case BINOP_NOTEQUAL: strcpy(ptr,"!="); break;
+ case BINOP_LESS: strcpy(ptr,"<"); break;
+ case BINOP_GTR: strcpy(ptr,">"); break;
+ case BINOP_GEQ: strcpy(ptr,">="); break;
+ case BINOP_LEQ: strcpy(ptr,"<="); break;
+ default:
+ error ("Invalid binary operation specified.");
+ }
+ argvec[0] = value_struct_elt (arg1, argvec+1, tstr, &static_memfuncp, "structure");
+ if (argvec[0])
+ {
+ if (static_memfuncp)
+ {
+ argvec[1] = argvec[0];
+ argvec++;
+ }
+ return call_function (argvec[0], 2 - static_memfuncp, argvec + 1);
+ }
+ error ("member function %s not found", tstr);
+}
+
+/* We know that arg1 is a structure, so try to find a unary user
+ defined operator that matches the operator in question.
+ Create an argument vector that calls arg1.operator @ (arg1)
+ and return that value (where '@' is (almost) any unary operator which
+ is legal for GNU C++). */
+
+value
+value_x_unop (arg1, op)
+ value arg1;
+ int op;
+{
+ value * argvec;
+ char *ptr;
+ char tstr[13];
+ int static_memfuncp;
+
+ COERCE_ENUM (arg1);
+
+ /* now we know that what we have to do is construct our
+ arg vector and find the right function to call it with. */
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
+ error ("friend functions not implemented yet");
+
+ argvec = (value *) alloca (sizeof (value) * 3);
+ argvec[1] = value_addr (arg1);
+ argvec[2] = 0;
+
+ /* make the right function name up */
+ strcpy(tstr,"operator __");
+ ptr = tstr+9;
+ switch (op)
+ {
+ case UNOP_PREINCREMENT: strcpy(ptr,"++"); break;
+ case UNOP_PREDECREMENT: strcpy(ptr,"++"); break;
+ case UNOP_POSTINCREMENT: strcpy(ptr,"++"); break;
+ case UNOP_POSTDECREMENT: strcpy(ptr,"++"); break;
+ case UNOP_ZEROP: strcpy(ptr,"!"); break;
+ case UNOP_LOGNOT: strcpy(ptr,"~"); break;
+ case UNOP_NEG: strcpy(ptr,"-"); break;
+ default:
+ error ("Invalid binary operation specified.");
+ }
+ argvec[0] = value_struct_elt (arg1, argvec+1, tstr, &static_memfuncp, "structure");
+ if (argvec[0])
+ {
+ if (static_memfuncp)
+ {
+ argvec[1] = argvec[0];
+ argvec++;
+ }
+ return call_function (argvec[0], 1 - static_memfuncp, argvec + 1);
+ }
+ error ("member function %s not found", tstr);
+}
+
+/* Perform a binary operation on two integers or two floats.
+ Does not support addition and subtraction on pointers;
+ use value_add or value_sub if you want to handle those possibilities. */
+
+value
+value_binop (arg1, arg2, op)
+ value arg1, arg2;
+ int op;
+{
+ register value val;
+
+ COERCE_ENUM (arg1);
+ COERCE_ENUM (arg2);
+
+ if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT
+ &&
+ TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
+ ||
+ (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT
+ &&
+ TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT))
+ error ("Argument to arithmetic operation not a number.");
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT
+ ||
+ TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT)
+ {
+ double v1, v2, v;
+ v1 = value_as_double (arg1);
+ v2 = value_as_double (arg2);
+ switch (op)
+ {
+ case BINOP_ADD:
+ v = v1 + v2;
+ break;
+
+ case BINOP_SUB:
+ v = v1 - v2;
+ break;
+
+ case BINOP_MUL:
+ v = v1 * v2;
+ break;
+
+ case BINOP_DIV:
+ v = v1 / v2;
+ break;
+
+ default:
+ error ("Integer-only operation on floating point number.");
+ }
+
+ val = allocate_value (builtin_type_double);
+ *(double *) VALUE_CONTENTS (val) = v;
+ }
+ else
+ /* Integral operations here. */
+ {
+ /* Should we promote to unsigned longest? */
+ if ((TYPE_UNSIGNED (VALUE_TYPE (arg1))
+ || TYPE_UNSIGNED (VALUE_TYPE (arg2)))
+ && (TYPE_LENGTH (VALUE_TYPE (arg1)) >= sizeof (unsigned LONGEST)
+ || TYPE_LENGTH (VALUE_TYPE (arg2)) >= sizeof (unsigned LONGEST)))
+ {
+ unsigned LONGEST v1, v2, v;
+ v1 = (unsigned LONGEST) value_as_long (arg1);
+ v2 = (unsigned LONGEST) value_as_long (arg2);
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ v = v1 + v2;
+ break;
+
+ case BINOP_SUB:
+ v = v1 - v2;
+ break;
+
+ case BINOP_MUL:
+ v = v1 * v2;
+ break;
+
+ case BINOP_DIV:
+ v = v1 / v2;
+ break;
+
+ case BINOP_REM:
+ v = v1 % v2;
+ break;
+
+ case BINOP_LSH:
+ v = v1 << v2;
+ break;
+
+ case BINOP_RSH:
+ v = v1 >> v2;
+ break;
+
+ case BINOP_LOGAND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_LOGIOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_LOGXOR:
+ v = v1 ^ v2;
+ break;
+
+ case BINOP_AND:
+ v = v1 && v2;
+ break;
+
+ case BINOP_OR:
+ v = v1 || v2;
+ break;
+
+ case BINOP_MIN:
+ v = v1 < v2 ? v1 : v2;
+ break;
+
+ case BINOP_MAX:
+ v = v1 > v2 ? v1 : v2;
+ break;
+
+ default:
+ error ("Invalid binary operation on numbers.");
+ }
+
+ val = allocate_value (BUILTIN_TYPE_UNSIGNED_LONGEST);
+ *(unsigned LONGEST *) VALUE_CONTENTS (val) = v;
+ }
+ else
+ {
+ LONGEST v1, v2, v;
+ v1 = value_as_long (arg1);
+ v2 = value_as_long (arg2);
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ v = v1 + v2;
+ break;
+
+ case BINOP_SUB:
+ v = v1 - v2;
+ break;
+
+ case BINOP_MUL:
+ v = v1 * v2;
+ break;
+
+ case BINOP_DIV:
+ v = v1 / v2;
+ break;
+
+ case BINOP_REM:
+ v = v1 % v2;
+ break;
+
+ case BINOP_LSH:
+ v = v1 << v2;
+ break;
+
+ case BINOP_RSH:
+ v = v1 >> v2;
+ break;
+
+ case BINOP_LOGAND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_LOGIOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_LOGXOR:
+ v = v1 ^ v2;
+ break;
+
+ case BINOP_AND:
+ v = v1 && v2;
+ break;
+
+ case BINOP_OR:
+ v = v1 || v2;
+ break;
+
+ case BINOP_MIN:
+ v = v1 < v2 ? v1 : v2;
+ break;
+
+ case BINOP_MAX:
+ v = v1 > v2 ? v1 : v2;
+ break;
+
+ default:
+ error ("Invalid binary operation on numbers.");
+ }
+
+ val = allocate_value (BUILTIN_TYPE_LONGEST);
+ *(LONGEST *) VALUE_CONTENTS (val) = v;
+ }
+ }
+
+ return val;
+}
+
+/* Simulate the C operator ! -- return 1 if ARG1 contains zeros. */
+
+int
+value_zerop (arg1)
+ value arg1;
+{
+ register int len;
+ register char *p;
+
+ COERCE_ARRAY (arg1);
+
+ len = TYPE_LENGTH (VALUE_TYPE (arg1));
+ p = VALUE_CONTENTS (arg1);
+
+ while (--len >= 0)
+ {
+ if (*p++)
+ break;
+ }
+
+ return len < 0;
+}
+
+/* Simulate the C operator == by returning a 1
+ iff ARG1 and ARG2 have equal contents. */
+
+int
+value_equal (arg1, arg2)
+ register value arg1, arg2;
+
+{
+ register int len;
+ register char *p1, *p2;
+ enum type_code code1;
+ enum type_code code2;
+
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
+
+ code1 = TYPE_CODE (VALUE_TYPE (arg1));
+ code2 = TYPE_CODE (VALUE_TYPE (arg2));
+
+ if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+ return value_as_long (arg1) == value_as_long (arg2);
+ else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+ && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+ return value_as_double (arg1) == value_as_double (arg2);
+ else if ((code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
+ || (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT))
+ return (char *) value_as_long (arg1) == (char *) value_as_long (arg2);
+ else if (code1 == code2
+ && ((len = TYPE_LENGTH (VALUE_TYPE (arg1)))
+ == TYPE_LENGTH (VALUE_TYPE (arg2))))
+ {
+ p1 = VALUE_CONTENTS (arg1);
+ p2 = VALUE_CONTENTS (arg2);
+ while (--len >= 0)
+ {
+ if (*p1++ != *p2++)
+ break;
+ }
+ return len < 0;
+ }
+ else
+ error ("Invalid type combination in equality test.");
+}
+
+/* Simulate the C operator < by returning 1
+ iff ARG1's contents are less than ARG2's. */
+
+int
+value_less (arg1, arg2)
+ register value arg1, arg2;
+{
+ register enum type_code code1;
+ register enum type_code code2;
+
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
+
+ code1 = TYPE_CODE (VALUE_TYPE (arg1));
+ code2 = TYPE_CODE (VALUE_TYPE (arg2));
+
+ if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+ return value_as_long (arg1) < value_as_long (arg2);
+ else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+ && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+ return value_as_double (arg1) < value_as_double (arg2);
+ else if ((code1 == TYPE_CODE_PTR || code1 == TYPE_CODE_INT)
+ && (code2 == TYPE_CODE_PTR || code2 == TYPE_CODE_INT))
+ return (char *) value_as_long (arg1) < (char *) value_as_long (arg2);
+ else
+ error ("Invalid type combination in ordering comparison.");
+}
+
+/* The unary operators - and ~. Both free the argument ARG1. */
+
+value
+value_neg (arg1)
+ register value arg1;
+{
+ register struct type *type;
+
+ COERCE_ENUM (arg1);
+
+ type = VALUE_TYPE (arg1);
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return value_from_double (type, - value_as_double (arg1));
+ else if (TYPE_CODE (type) == TYPE_CODE_INT)
+ return value_from_long (type, - value_as_long (arg1));
+ else
+ error ("Argument to negate operation not a number.");
+}
+
+value
+value_lognot (arg1)
+ register value arg1;
+{
+ COERCE_ENUM (arg1);
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
+ error ("Argument to complement operation not an integer.");
+
+ return value_from_long (VALUE_TYPE (arg1), ~ value_as_long (arg1));
+}
+
diff --git a/gnu/usr.bin/kgdb/valops.c b/gnu/usr.bin/kgdb/valops.c
new file mode 100644
index 000000000000..ab5652cc187a
--- /dev/null
+++ b/gnu/usr.bin/kgdb/valops.c
@@ -0,0 +1,1418 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)valops.c 6.4 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Perform non-arithmetic operations on values, for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "stdio.h"
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+
+/* Cast value ARG2 to type TYPE and return as a value.
+ More general than a C cast: accepts any two types of the same length,
+ and if ARG2 is an lvalue it can be cast into anything at all. */
+
+value
+value_cast (type, arg2)
+ struct type *type;
+ register value arg2;
+{
+ register enum type_code code1;
+ register enum type_code code2;
+ register int scalar;
+
+ /* Coerce arrays but not enums. Enums will work as-is
+ and coercing them would cause an infinite recursion. */
+ if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_ENUM)
+ COERCE_ARRAY (arg2);
+
+ code1 = TYPE_CODE (type);
+ code2 = TYPE_CODE (VALUE_TYPE (arg2));
+ scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
+ || code2 == TYPE_CODE_ENUM);
+
+ if (code1 == TYPE_CODE_FLT && scalar)
+ return value_from_double (type, value_as_double (arg2));
+ else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM)
+ && (scalar || code2 == TYPE_CODE_PTR))
+ return value_from_long (type, value_as_long (arg2));
+ else if (TYPE_LENGTH (type) == TYPE_LENGTH (VALUE_TYPE (arg2)))
+ {
+ VALUE_TYPE (arg2) = type;
+ return arg2;
+ }
+ else if (VALUE_LVAL (arg2) == lval_memory)
+ {
+ return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
+ }
+ else
+ error ("Invalid cast.");
+}
+
+/* Create a value of type TYPE that is zero, and return it. */
+
+value
+value_zero (type, lv)
+ struct type *type;
+ enum lval_type lv;
+{
+ register value val = allocate_value (type);
+
+ bzero (VALUE_CONTENTS (val), TYPE_LENGTH (type));
+ VALUE_LVAL (val) = lv;
+
+ return val;
+}
+
+/* Return the value with a specified type located at specified address. */
+
+value
+value_at (type, addr)
+ struct type *type;
+ CORE_ADDR addr;
+{
+ register value val = allocate_value (type);
+ int temp;
+
+ temp = read_memory (addr, VALUE_CONTENTS (val), TYPE_LENGTH (type));
+ if (temp)
+ {
+ if (have_inferior_p () && !remote_debugging)
+ print_sys_errmsg ("ptrace", temp);
+ /* Actually, address between addr and addr + len was out of bounds. */
+ error ("Cannot read memory: address 0x%x out of bounds.", addr);
+ }
+
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = addr;
+
+ return val;
+}
+
+/* Store the contents of FROMVAL into the location of TOVAL.
+ Return a new value with the location of TOVAL and contents of FROMVAL. */
+
+value
+value_assign (toval, fromval)
+ register value toval, fromval;
+{
+ register struct type *type = VALUE_TYPE (toval);
+ register value val;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+ int use_buffer = 0;
+
+ extern CORE_ADDR find_saved_register ();
+
+ COERCE_ARRAY (fromval);
+
+ if (VALUE_LVAL (toval) != lval_internalvar)
+ fromval = value_cast (type, fromval);
+
+ /* If TOVAL is a special machine register requiring conversion
+ of program values to a special raw format,
+ convert FROMVAL's contents now, with result in `raw_buffer',
+ and set USE_BUFFER to the number of bytes to write. */
+
+ if (VALUE_REGNO (toval) >= 0
+ && REGISTER_CONVERTIBLE (VALUE_REGNO (toval)))
+ {
+ int regno = VALUE_REGNO (toval);
+ if (VALUE_TYPE (fromval) != REGISTER_VIRTUAL_TYPE (regno))
+ fromval = value_cast (REGISTER_VIRTUAL_TYPE (regno), fromval);
+ bcopy (VALUE_CONTENTS (fromval), virtual_buffer,
+ REGISTER_VIRTUAL_SIZE (regno));
+ REGISTER_CONVERT_TO_RAW (regno, virtual_buffer, raw_buffer);
+ use_buffer = REGISTER_RAW_SIZE (regno);
+ }
+
+ switch (VALUE_LVAL (toval))
+ {
+ case lval_internalvar:
+ set_internalvar (VALUE_INTERNALVAR (toval), fromval);
+ break;
+
+ case lval_internalvar_component:
+ set_internalvar_component (VALUE_INTERNALVAR (toval),
+ VALUE_OFFSET (toval),
+ VALUE_BITPOS (toval),
+ VALUE_BITSIZE (toval),
+ fromval);
+ break;
+
+ case lval_memory:
+ if (VALUE_BITSIZE (toval))
+ {
+ int val;
+ read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ &val, sizeof val);
+ modify_field (&val, (int) value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ &val, sizeof val);
+ }
+ else if (use_buffer)
+ write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ raw_buffer, use_buffer);
+ else
+ write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+ break;
+
+ case lval_register:
+ if (VALUE_BITSIZE (toval))
+ {
+ int val;
+
+ read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ &val, sizeof val);
+ modify_field (&val, (int) value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ &val, sizeof val);
+ }
+ else if (use_buffer)
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ raw_buffer, use_buffer);
+ else
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+ break;
+
+ case lval_reg_frame_relative:
+ {
+ /* value is stored in a series of registers in the frame
+ specified by the structure. Copy that value out, modify
+ it, and copy it back in. */
+ int amount_to_copy = (VALUE_BITSIZE (toval) ? 1 : TYPE_LENGTH (type));
+ int reg_size = REGISTER_RAW_SIZE (VALUE_FRAME_REGNUM (toval));
+ int byte_offset = VALUE_OFFSET (toval) % reg_size;
+ int reg_offset = VALUE_OFFSET (toval) / reg_size;
+ int amount_copied;
+ char *buffer = (char *) alloca (amount_to_copy);
+ int regno;
+ FRAME frame;
+ CORE_ADDR addr;
+
+ /* Figure out which frame this is in currently. */
+ for (frame = get_current_frame ();
+ frame && FRAME_FP (frame) != VALUE_FRAME (toval);
+ frame = get_prev_frame (frame))
+ ;
+
+ if (!frame)
+ error ("Value being assigned to is no longer active.");
+
+ amount_to_copy += (reg_size - amount_to_copy % reg_size);
+
+ /* Copy it out. */
+ for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
+ amount_copied = 0);
+ amount_copied < amount_to_copy;
+ amount_copied += reg_size, regno++)
+ {
+ addr = find_saved_register (frame, regno);
+ if (addr == 0)
+ read_register_bytes (REGISTER_BYTE (regno),
+ buffer + amount_copied,
+ reg_size);
+ else
+ read_memory (addr, buffer + amount_copied, reg_size);
+ }
+
+ /* Modify what needs to be modified. */
+ if (VALUE_BITSIZE (toval))
+ modify_field (buffer + byte_offset,
+ (int) value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ else if (use_buffer)
+ bcopy (raw_buffer, buffer + byte_offset, use_buffer);
+ else
+ bcopy (VALUE_CONTENTS (fromval), buffer + byte_offset,
+ TYPE_LENGTH (type));
+
+ /* Copy it back. */
+ for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
+ amount_copied = 0);
+ amount_copied < amount_to_copy;
+ amount_copied += reg_size, regno++)
+ {
+ addr = find_saved_register (frame, regno);
+ if (addr == 0)
+ write_register_bytes (REGISTER_BYTE (regno),
+ buffer + amount_copied,
+ reg_size);
+ else
+ write_memory (addr, buffer + amount_copied, reg_size);
+ }
+ }
+ break;
+
+
+ default:
+ error ("Left side of = operation is not an lvalue.");
+ }
+
+ /* Return a value just like TOVAL except with the contents of FROMVAL
+ (except in the case of the type if TOVAL is an internalvar). */
+
+ if (VALUE_LVAL (toval) == lval_internalvar
+ || VALUE_LVAL (toval) == lval_internalvar_component)
+ {
+ type = VALUE_TYPE (fromval);
+ }
+
+ val = allocate_value (type);
+ bcopy (toval, val, VALUE_CONTENTS (val) - (char *) val);
+ bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS (val), TYPE_LENGTH (type));
+ VALUE_TYPE (val) = type;
+
+ return val;
+}
+
+/* Extend a value VAL to COUNT repetitions of its type. */
+
+value
+value_repeat (arg1, count)
+ value arg1;
+ int count;
+{
+ register value val;
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Only values in memory can be extended with '@'.");
+ if (count < 1)
+ error ("Invalid number %d of repetitions.", count);
+
+ val = allocate_repeat_value (VALUE_TYPE (arg1), count);
+
+ read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),
+ VALUE_CONTENTS (val),
+ TYPE_LENGTH (VALUE_TYPE (val)) * count);
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);
+
+ return val;
+}
+
+value
+value_of_variable (var)
+ struct symbol *var;
+{
+ return read_var_value (var, (FRAME) 0);
+}
+
+/* Given a value which is an array, return a value which is
+ a pointer to its first element. */
+
+value
+value_coerce_array (arg1)
+ value arg1;
+{
+ register struct type *type;
+ register value val;
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Attempt to take address of value not located in memory.");
+
+ /* Get type of elements. */
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY)
+ type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1));
+ else
+ /* A phony array made by value_repeat.
+ Its type is the type of the elements, not an array type. */
+ type = VALUE_TYPE (arg1);
+
+ /* Get the type of the result. */
+ type = lookup_pointer_type (type);
+ val = value_from_long (builtin_type_long,
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+ VALUE_TYPE (val) = type;
+ return val;
+}
+
+/* Return a pointer value for the object for which ARG1 is the contents. */
+
+value
+value_addr (arg1)
+ value arg1;
+{
+ register struct type *type;
+ register value val, arg1_coerced;
+
+ /* Taking the address of an array is really a no-op
+ once the array is coerced to a pointer to its first element. */
+ arg1_coerced = arg1;
+ COERCE_ARRAY (arg1_coerced);
+ if (arg1 != arg1_coerced)
+ return arg1_coerced;
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Attempt to take address of value not located in memory.");
+
+ /* Get the type of the result. */
+ type = lookup_pointer_type (VALUE_TYPE (arg1));
+ val = value_from_long (builtin_type_long,
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+ VALUE_TYPE (val) = type;
+ return val;
+}
+
+/* Given a value of a pointer type, apply the C unary * operator to it. */
+
+value
+value_ind (arg1)
+ value arg1;
+{
+ /* Must do this before COERCE_ARRAY, otherwise an infinite loop
+ will result */
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF)
+ return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+ (CORE_ADDR) value_as_long (arg1));
+
+ COERCE_ARRAY (arg1);
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_MEMBER)
+ error ("not implemented: member types in value_ind");
+
+ /* Allow * on an integer so we can cast it to whatever we want.
+ This returns an int, which seems like the most C-like thing
+ to do. "long long" variables are rare enough that
+ BUILTIN_TYPE_LONGEST would seem to be a mistake. */
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
+ return value_at (builtin_type_int,
+ (CORE_ADDR) value_as_long (arg1));
+ else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
+ return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+ (CORE_ADDR) value_as_long (arg1));
+ else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF)
+ return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
+ (CORE_ADDR) value_as_long (arg1));
+ error ("Attempt to take contents of a non-pointer value.");
+}
+
+/* Pushing small parts of stack frames. */
+
+/* Push one word (the size of object that a register holds). */
+
+CORE_ADDR
+push_word (sp, buffer)
+ CORE_ADDR sp;
+ REGISTER_TYPE buffer;
+{
+ register int len = sizeof (REGISTER_TYPE);
+
+#if 1 INNER_THAN 2
+ sp -= len;
+ write_memory (sp, &buffer, len);
+#else /* stack grows upward */
+ write_memory (sp, &buffer, len);
+ sp += len;
+#endif /* stack grows upward */
+
+ return sp;
+}
+
+/* Push LEN bytes with data at BUFFER. */
+
+CORE_ADDR
+push_bytes (sp, buffer, len)
+ CORE_ADDR sp;
+ char *buffer;
+ int len;
+{
+#if 1 INNER_THAN 2
+ sp -= len;
+ write_memory (sp, buffer, len);
+#else /* stack grows upward */
+ write_memory (sp, buffer, len);
+ sp += len;
+#endif /* stack grows upward */
+
+ return sp;
+}
+
+/* Push onto the stack the specified value VALUE. */
+
+CORE_ADDR
+value_push (sp, arg)
+ register CORE_ADDR sp;
+ value arg;
+{
+ register int len = TYPE_LENGTH (VALUE_TYPE (arg));
+
+#if 1 INNER_THAN 2
+ sp -= len;
+ write_memory (sp, VALUE_CONTENTS (arg), len);
+#else /* stack grows upward */
+ write_memory (sp, VALUE_CONTENTS (arg), len);
+ sp += len;
+#endif /* stack grows upward */
+
+ return sp;
+}
+
+/* Perform the standard coercions that are specified
+ for arguments to be passed to C functions. */
+
+value
+value_arg_coerce (arg)
+ value arg;
+{
+ register struct type *type;
+
+ COERCE_ENUM (arg);
+
+ type = VALUE_TYPE (arg);
+
+ if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) < sizeof (int))
+ return value_cast (builtin_type_int, arg);
+
+ if (type == builtin_type_float)
+ return value_cast (builtin_type_double, arg);
+
+ return arg;
+}
+
+/* Push the value ARG, first coercing it as an argument
+ to a C function. */
+
+CORE_ADDR
+value_arg_push (sp, arg)
+ register CORE_ADDR sp;
+ value arg;
+{
+ return value_push (sp, value_arg_coerce (arg));
+}
+
+#ifdef NEW_CALL_FUNCTION
+
+int
+arg_stacklen(nargs, args)
+ int nargs;
+ value *args;
+{
+ int len = 0;
+
+ while (--nargs >= 0)
+ len += TYPE_LENGTH(VALUE_TYPE(value_arg_coerce(args[nargs])));
+
+ return len;
+}
+
+CORE_ADDR
+function_address(function, type)
+ value function;
+ struct type **type;
+{
+ register CORE_ADDR funaddr;
+ register struct type *ftype = VALUE_TYPE(function);
+ register enum type_code code = TYPE_CODE(ftype);
+
+ /*
+ * If it's a member function, just look at the function part
+ * of it.
+ */
+
+ /* Determine address to call. */
+ if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD) {
+ funaddr = VALUE_ADDRESS(function);
+ *type = TYPE_TARGET_TYPE(ftype);
+ } else if (code == TYPE_CODE_PTR) {
+ funaddr = value_as_long(function);
+ if (TYPE_CODE(TYPE_TARGET_TYPE(ftype)) == TYPE_CODE_FUNC
+ || TYPE_CODE(TYPE_TARGET_TYPE(ftype)) == TYPE_CODE_METHOD)
+ *type = TYPE_TARGET_TYPE(TYPE_TARGET_TYPE(ftype));
+ else
+ *type = builtin_type_int;
+ } else if (code == TYPE_CODE_INT) {
+ /*
+ * Handle the case of functions lacking debugging
+ * info. Their values are characters since their
+ * addresses are char
+ */
+ if (TYPE_LENGTH(ftype) == 1)
+
+ funaddr = value_as_long(value_addr(function));
+ else
+ /*
+ * Handle integer used as address of a
+ * function.
+ */
+ funaddr = value_as_long(function);
+
+ *type = builtin_type_int;
+ } else
+ error("Invalid data type for function to be called.");
+
+ return funaddr;
+}
+
+/* Perform a function call in the inferior.
+ ARGS is a vector of values of arguments (NARGS of them).
+ FUNCTION is a value, the function to be called.
+ Returns a value representing what the function returned.
+ May fail to return, if a breakpoint or signal is hit
+ during the execution of the function. */
+
+value
+call_function(function, nargs, args)
+ value function;
+ int nargs;
+ value *args;
+{
+ register CORE_ADDR sp, pc;
+ struct type *value_type;
+ struct inferior_status inf_status;
+ struct cleanup *old_chain;
+ register CORE_ADDR funaddr;
+ int struct_return_bytes;
+ char retbuf[REGISTER_BYTES];
+
+ if (!have_inferior_p())
+ error("Cannot invoke functions if the inferior is not running.");
+
+ save_inferior_status(&inf_status, 1);
+ old_chain = make_cleanup(restore_inferior_status, &inf_status);
+
+ sp = read_register(SP_REGNUM);
+ funaddr = function_address(function, &value_type);
+ /*
+ * Are we returning a value using a structure return or a
+ * normal value return?
+ */
+ if (using_struct_return(function, funaddr, value_type))
+ struct_return_bytes = TYPE_LENGTH(value_type);
+ else
+ struct_return_bytes = 0;
+ /*
+ * Create a call sequence customized for this function and
+ * the number of arguments for it.
+ */
+ pc = setup_dummy(sp, funaddr, nargs, args,
+ struct_return_bytes, value_arg_push);
+
+ /*
+ * Execute the stack dummy stub. The register state will be
+ * returned in retbuf. It is restored below.
+ */
+ run_stack_dummy(pc, retbuf);
+
+ /*
+ * This will restore the register context that existed before
+ * we called the dummy function.
+ */
+ do_cleanups(old_chain);
+
+ return value_being_returned(value_type, retbuf, struct_return_bytes);
+}
+#else
+
+/* Perform a function call in the inferior.
+ ARGS is a vector of values of arguments (NARGS of them).
+ FUNCTION is a value, the function to be called.
+ Returns a value representing what the function returned.
+ May fail to return, if a breakpoint or signal is hit
+ during the execution of the function. */
+
+value
+call_function (function, nargs, args)
+ value function;
+ int nargs;
+ value *args;
+{
+ register CORE_ADDR sp;
+ register int i;
+ CORE_ADDR start_sp;
+ static REGISTER_TYPE dummy[] = CALL_DUMMY;
+ REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
+ CORE_ADDR old_sp;
+ struct type *value_type;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+ struct inferior_status inf_status;
+ struct cleanup *old_chain;
+
+ if (!have_inferior_p ())
+ error ("Cannot invoke functions if the inferior is not running.");
+
+ save_inferior_status (&inf_status, 1);
+ old_chain = make_cleanup (restore_inferior_status, &inf_status);
+
+ /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
+ (and POP_FRAME for restoring them). (At least on most machines)
+ they are saved on the stack in the inferior. */
+ PUSH_DUMMY_FRAME;
+
+ old_sp = sp = read_register (SP_REGNUM);
+
+#if 1 INNER_THAN 2 /* Stack grows down */
+ sp -= sizeof dummy;
+ start_sp = sp;
+#else /* Stack grows up */
+ start_sp = sp;
+ sp += sizeof dummy;
+#endif
+
+ {
+ register CORE_ADDR funaddr;
+ register struct type *ftype = VALUE_TYPE (function);
+ register enum type_code code = TYPE_CODE (ftype);
+
+ /* If it's a member function, just look at the function
+ part of it. */
+
+ /* Determine address to call. */
+ if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
+ {
+ funaddr = VALUE_ADDRESS (function);
+ value_type = TYPE_TARGET_TYPE (ftype);
+ }
+ else if (code == TYPE_CODE_PTR)
+ {
+ funaddr = value_as_long (function);
+ if (TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_FUNC
+ || TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_METHOD)
+ value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype));
+ else
+ value_type = builtin_type_int;
+ }
+ else if (code == TYPE_CODE_INT)
+ {
+ /* Handle the case of functions lacking debugging info.
+ Their values are characters since their addresses are char */
+ if (TYPE_LENGTH (ftype) == 1)
+ funaddr = value_as_long (value_addr (function));
+ else
+ /* Handle integer used as address of a function. */
+ funaddr = value_as_long (function);
+
+ value_type = builtin_type_int;
+ }
+ else
+ error ("Invalid data type for function to be called.");
+
+ /* Are we returning a value using a structure return or a normal
+ value return? */
+
+ struct_return = using_struct_return (function, funaddr, value_type);
+
+ /* Create a call sequence customized for this function
+ and the number of arguments for it. */
+ bcopy (dummy, dummy1, sizeof dummy);
+ FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, value_type);
+ }
+
+#ifndef CANNOT_EXECUTE_STACK
+ write_memory (start_sp, dummy1, sizeof dummy);
+
+#else
+ /* Convex Unix prohibits executing in the stack segment. */
+ /* Hope there is empty room at the top of the text segment. */
+ {
+ extern CORE_ADDR text_end;
+ static checked = 0;
+ if (!checked)
+ for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
+ if (read_memory_integer (start_sp, 1) != 0)
+ error ("text segment full -- no place to put call");
+ checked = 1;
+ sp = old_sp;
+ start_sp = text_end - sizeof dummy;
+ write_memory (start_sp, dummy1, sizeof dummy);
+ }
+#endif /* CANNOT_EXECUTE_STACK */
+#ifdef STACK_ALIGN
+ /* If stack grows down, we must leave a hole at the top. */
+ {
+ int len = 0;
+
+ /* Reserve space for the return structure to be written on the
+ stack, if necessary */
+
+ if (struct_return)
+ len += TYPE_LENGTH (value_type);
+
+ for (i = nargs - 1; i >= 0; i--)
+ len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
+#ifdef CALL_DUMMY_STACK_ADJUST
+ len += CALL_DUMMY_STACK_ADJUST;
+#endif
+#if 1 INNER_THAN 2
+ sp -= STACK_ALIGN (len) - len;
+#else
+ sp += STACK_ALIGN (len) - len;
+#endif
+ }
+#endif /* STACK_ALIGN */
+
+ /* Reserve space for the return structure to be written on the
+ stack, if necessary */
+
+ if (struct_return)
+ {
+#if 1 INNER_THAN 2
+ sp -= TYPE_LENGTH (value_type);
+ struct_addr = sp;
+#else
+ struct_addr = sp;
+ sp += TYPE_LENGTH (value_type);
+#endif
+ }
+
+ for (i = nargs - 1; i >= 0; i--)
+ sp = value_arg_push (sp, args[i]);
+
+#ifdef CALL_DUMMY_STACK_ADJUST
+#if 1 INNER_THAN 2
+ sp -= CALL_DUMMY_STACK_ADJUST;
+#else
+ sp += CALL_DUMMY_STACK_ADJUST;
+#endif
+#endif /* CALL_DUMMY_STACK_ADJUST */
+
+ /* Store the address at which the structure is supposed to be
+ written. Note that this (and the code which reserved the space
+ above) assumes that gcc was used to compile this function. Since
+ it doesn't cost us anything but space and if the function is pcc
+ it will ignore this value, we will make that assumption.
+
+ Also note that on some machines (like the sparc) pcc uses this
+ convention in a slightly twisted way also. */
+
+ if (struct_return)
+ STORE_STRUCT_RETURN (struct_addr, sp);
+
+ /* Write the stack pointer. This is here because the statement above
+ might fool with it */
+ write_register (SP_REGNUM, sp);
+
+ /* Figure out the value returned by the function. */
+ {
+ char retbuf[REGISTER_BYTES];
+
+ /* Execute the stack dummy routine, calling FUNCTION.
+ When it is done, discard the empty frame
+ after storing the contents of all regs into retbuf. */
+ run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
+
+ do_cleanups (old_chain);
+
+ return value_being_returned (value_type, retbuf, struct_return);
+ }
+}
+#endif
+
+/* Create a value for a string constant:
+ Call the function malloc in the inferior to get space for it,
+ then copy the data into that space
+ and then return the address with type char *.
+ PTR points to the string constant data; LEN is number of characters. */
+
+value
+value_string (ptr, len)
+ char *ptr;
+ int len;
+{
+ register value val;
+ register struct symbol *sym;
+ value blocklen;
+ register char *copy = (char *) alloca (len + 1);
+ char *i = ptr;
+ register char *o = copy, *ibeg = ptr;
+ register int c;
+#ifdef KERNELDEBUG
+ extern int kernel_debugging;
+
+ if (kernel_debugging)
+ error("Can't stuff string constants into kernel (yet).");
+#endif
+
+ /* Copy the string into COPY, processing escapes.
+ We could not conveniently process them in expread
+ because the string there wants to be a substring of the input. */
+
+ while (i - ibeg < len)
+ {
+ c = *i++;
+ if (c == '\\')
+ {
+ c = parse_escape (&i);
+ if (c == -1)
+ continue;
+ }
+ *o++ = c;
+ }
+ *o = 0;
+
+ /* Get the length of the string after escapes are processed. */
+
+ len = o - copy;
+
+ /* Find the address of malloc in the inferior. */
+
+ sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE, 0);
+ if (sym != 0)
+ {
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ error ("\"malloc\" exists in this program but is not a function.");
+ val = value_of_variable (sym);
+ }
+ else
+ {
+ register int i;
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, "malloc"))
+ break;
+ if (i < misc_function_count)
+ val = value_from_long (builtin_type_long,
+ (LONGEST) misc_function_vector[i].address);
+ else
+ error ("String constants require the program to have a function \"malloc\".");
+ }
+
+ blocklen = value_from_long (builtin_type_int, (LONGEST) (len + 1));
+ val = call_function (val, 1, &blocklen);
+ if (value_zerop (val))
+ error ("No memory available for string constant.");
+ write_memory ((CORE_ADDR) value_as_long (val), copy, len + 1);
+ VALUE_TYPE (val) = lookup_pointer_type (builtin_type_char);
+ return val;
+}
+
+static int
+type_field_index(t, name)
+ register struct type *t;
+ register char *name;
+{
+ register int i;
+
+ for (i = TYPE_NFIELDS(t); --i >= 0;)
+ {
+ register char *t_field_name = TYPE_FIELD_NAME (t, i);
+
+ if (t_field_name && !strcmp (t_field_name, name))
+ break;
+ }
+ return (i);
+}
+
+/* Given ARG1, a value of type (pointer to a)* structure/union,
+ extract the component named NAME from the ultimate target structure/union
+ and return it as a value with its appropriate type.
+ ERR is used in the error message if ARG1's type is wrong.
+
+ C++: ARGS is a list of argument types to aid in the selection of
+ an appropriate method. Also, handle derived types.
+
+ STATIC_MEMFUNCP, if non-NULL, points to a caller-supplied location
+ where the truthvalue of whether the function that was resolved was
+ a static member function or not.
+
+ ERR is an error message to be printed in case the field is not found. */
+
+value
+value_struct_elt (arg1, args, name, static_memfuncp, err)
+ register value arg1, *args;
+ char *name;
+ int *static_memfuncp;
+ char *err;
+{
+ register struct type *t;
+ register int i;
+ int found = 0;
+
+ struct type *baseclass;
+
+ COERCE_ARRAY (arg1);
+
+ t = VALUE_TYPE (arg1);
+
+ /* Check for the usual case: we have pointer, target type is a struct
+ * and `name' is a legal field of the struct. In this case, we can
+ * just snarf the value of the field & not waste time while value_ind
+ * sucks over the entire struct. */
+ if (! args)
+ {
+ if (TYPE_CODE(t) == TYPE_CODE_PTR
+ && (TYPE_CODE((baseclass = TYPE_TARGET_TYPE(t))) == TYPE_CODE_STRUCT
+ || TYPE_CODE(baseclass) == TYPE_CODE_UNION)
+ && (i = type_field_index(baseclass, name)) >= 0)
+ {
+ register int offset;
+ register struct type *f = TYPE_FIELD_TYPE(baseclass, i);
+
+ offset = TYPE_FIELD_BITPOS(baseclass, i) >> 3;
+ if (TYPE_FIELD_BITSIZE(baseclass, i) == 0)
+ return value_at(f, (CORE_ADDR)(value_as_long(arg1) + offset));
+ }
+ }
+
+ /* Follow pointers until we get to a non-pointer. */
+
+ while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+ {
+ arg1 = value_ind (arg1);
+ COERCE_ARRAY (arg1);
+ t = VALUE_TYPE (arg1);
+ }
+
+ if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+ error ("not implemented: member type in value_struct_elt");
+
+ if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Attempt to extract a component of a value that is not a %s.", err);
+
+ baseclass = t;
+
+ /* Assume it's not, unless we see that it is. */
+ if (static_memfuncp)
+ *static_memfuncp =0;
+
+ if (!args)
+ {
+ /* if there are no arguments ...do this... */
+
+ /* Try as a variable first, because if we succeed, there
+ is less work to be done. */
+ while (t)
+ {
+ i = type_field_index(t, name);
+ if (i >= 0)
+ return TYPE_FIELD_STATIC (t, i)
+ ? value_static_field (t, name, i) : value_field (arg1, i);
+
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ VALUE_TYPE (arg1) = t; /* side effect! */
+ }
+
+ /* C++: If it was not found as a data field, then try to
+ return it as a pointer to a method. */
+ t = baseclass;
+ VALUE_TYPE (arg1) = t; /* side effect! */
+
+ if (destructor_name_p (name, t))
+ error ("use `info method' command to print out value of destructor");
+
+ while (t)
+ {
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
+ {
+ if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
+ {
+ error ("use `info method' command to print value of method \"%s\"", name);
+ }
+ }
+
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ }
+
+ error ("There is no field named %s.", name);
+ return 0;
+ }
+
+ if (destructor_name_p (name, t))
+ {
+ if (!args[1])
+ {
+ /* destructors are a special case. */
+ return (value)value_fn_field (arg1, 0,
+ TYPE_FN_FIELDLIST_LENGTH (t, 0));
+ }
+ else
+ {
+ error ("destructor should not have any argument");
+ }
+ }
+
+ /* This following loop is for methods with arguments. */
+ while (t)
+ {
+ /* Look up as method first, because that is where we
+ expect to find it first. */
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
+
+ if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
+ {
+ int j;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
+
+ found = 1;
+ for (j = TYPE_FN_FIELDLIST_LENGTH (t, i) - 1; j >= 0; --j)
+ if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
+ TYPE_FN_FIELD_ARGS (f, j), args))
+ {
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ return (value)value_virtual_fn_field (arg1, f, j, t);
+ if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
+ *static_memfuncp = 1;
+ return (value)value_fn_field (arg1, i, j);
+ }
+ }
+ }
+
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ VALUE_TYPE (arg1) = t; /* side effect! */
+ }
+
+ if (found)
+ {
+ error ("Structure method %s not defined for arglist.", name);
+ return 0;
+ }
+ else
+ {
+ /* See if user tried to invoke data as function */
+ t = baseclass;
+ while (t)
+ {
+ i = type_field_index(t, name);
+ if (i >= 0)
+ return TYPE_FIELD_STATIC (t, i)
+ ? value_static_field (t, name, i) : value_field (arg1, i);
+
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ VALUE_TYPE (arg1) = t; /* side effect! */
+ }
+ error ("Structure has no component named %s.", name);
+ }
+}
+
+/* C++: return 1 is NAME is a legitimate name for the destructor
+ of type TYPE. If TYPE does not have a destructor, or
+ if NAME is inappropriate for TYPE, an error is signaled. */
+int
+destructor_name_p (name, type)
+ char *name;
+ struct type *type;
+{
+ /* destructors are a special case. */
+ char *dname = TYPE_NAME (type);
+
+ if (name[0] == '~')
+ {
+ if (! TYPE_HAS_DESTRUCTOR (type))
+ error ("type `%s' does not have destructor defined",
+ TYPE_NAME (type));
+ /* Skip past the "struct " at the front. */
+ while (*dname++ != ' ') ;
+ if (strcmp (dname, name+1))
+ error ("destructor specification error");
+ else
+ return 1;
+ }
+ return 0;
+}
+
+/* C++: Given ARG1, a value of type (pointer to a)* structure/union,
+ return 1 if the component named NAME from the ultimate
+ target structure/union is defined, otherwise, return 0. */
+
+int
+check_field (arg1, name)
+ register value arg1;
+ char *name;
+{
+ register struct type *t;
+ register int i;
+ int found = 0;
+
+ struct type *baseclass;
+
+ COERCE_ARRAY (arg1);
+
+ t = VALUE_TYPE (arg1);
+
+ /* Follow pointers until we get to a non-pointer. */
+
+ while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+ t = TYPE_TARGET_TYPE (t);
+
+ if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+ error ("not implemented: member type in check_field");
+
+ if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Internal error: `this' is not an aggregate");
+
+ baseclass = t;
+
+ while (t)
+ {
+ for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
+ {
+ char *t_field_name = TYPE_FIELD_NAME (t, i);
+ if (t_field_name && !strcmp (t_field_name, name))
+ goto success;
+ }
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ VALUE_TYPE (arg1) = t; /* side effect! */
+ }
+
+ /* C++: If it was not found as a data field, then try to
+ return it as a pointer to a method. */
+ t = baseclass;
+
+ /* Destructors are a special case. */
+ if (destructor_name_p (name, t))
+ goto success;
+
+ while (t)
+ {
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
+ {
+ if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
+ return 1;
+ }
+
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ }
+ return 0;
+
+ success:
+ t = VALUE_TYPE (arg1);
+ while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+ {
+ arg1 = value_ind (arg1);
+ COERCE_ARRAY (arg1);
+ t = VALUE_TYPE (arg1);
+ }
+}
+
+/* C++: Given an aggregate type DOMAIN, and a member name NAME,
+ return the address of this member as a pointer to member
+ type. If INTYPE is non-null, then it will be the type
+ of the member we are looking for. This will help us resolve
+ pointers to member functions. */
+
+value
+value_struct_elt_for_address (domain, intype, name)
+ struct type *domain, *intype;
+ char *name;
+{
+ register struct type *t = domain;
+ register int i;
+ int found = 0;
+ value v;
+
+ struct type *baseclass;
+
+ if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Internal error: non-aggregate type to value_struct_elt_for_address");
+
+ baseclass = t;
+
+ while (t)
+ {
+ for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
+ {
+ char *t_field_name = TYPE_FIELD_NAME (t, i);
+ if (t_field_name && !strcmp (t_field_name, name))
+ {
+ if (TYPE_FIELD_PACKED (t, i))
+ error ("pointers to bitfield members not allowed");
+
+ v = value_from_long (builtin_type_int,
+ (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
+ VALUE_TYPE (v) = lookup_pointer_type (
+ lookup_member_type (TYPE_FIELD_TYPE (t, i), baseclass));
+ return v;
+ }
+ }
+
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ }
+
+ /* C++: If it was not found as a data field, then try to
+ return it as a pointer to a method. */
+ t = baseclass;
+
+ /* Destructors are a special case. */
+ if (destructor_name_p (name, t))
+ {
+ error ("pointers to destructors not implemented yet");
+ }
+
+ /* Perform all necessary dereferencing. */
+ while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR)
+ intype = TYPE_TARGET_TYPE (intype);
+
+ while (t)
+ {
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
+ {
+ if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
+ {
+ int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
+
+ if (intype == 0 && j > 1)
+ error ("non-unique member `%s' requires type instantiation", name);
+ if (intype)
+ {
+ while (j--)
+ if (TYPE_FN_FIELD_TYPE (f, j) == intype)
+ break;
+ if (j < 0)
+ error ("no member function matches that type instantiation");
+ }
+ else
+ j = 0;
+
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ {
+ v = value_from_long (builtin_type_long,
+ (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ }
+ else
+ {
+ struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
+ 0, VAR_NAMESPACE, 0);
+ v = locate_var_value (s, 0);
+ }
+ VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), baseclass));
+ return v;
+ }
+ }
+
+ if (TYPE_N_BASECLASSES (t) == 0)
+ break;
+
+ t = TYPE_BASECLASS (t, 1);
+ }
+ return 0;
+}
+
+/* Compare two argument lists and return the position in which they differ,
+ or zero if equal.
+
+ STATICP is nonzero if the T1 argument list came from a
+ static member function.
+
+ For non-static member functions, we ignore the first argument,
+ which is the type of the instance variable. This is because we want
+ to handle calls with objects from derived classes. This is not
+ entirely correct: we should actually check to make sure that a
+ requested operation is type secure, shouldn't we? */
+
+int
+typecmp (staticp, t1, t2)
+ int staticp;
+ struct type *t1[];
+ value t2[];
+{
+ int i;
+
+ if (staticp && t1 == 0)
+ return t2[1] != 0;
+ if (t1 == 0)
+ return 1;
+ if (t1[0]->code == TYPE_CODE_VOID) return 0;
+ if (t1[!staticp] == 0) return 0;
+ for (i = !staticp; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++)
+ {
+ if (! t2[i]
+ || t1[i]->code != t2[i]->type->code
+ || t1[i]->target_type != t2[i]->type->target_type)
+ return i+1;
+ }
+ if (!t1[i]) return 0;
+ return t2[i] ? i+1 : 0;
+}
+
+/* C++: return the value of the class instance variable, if one exists.
+ Flag COMPLAIN signals an error if the request is made in an
+ inappropriate context. */
+value
+value_of_this (complain)
+ int complain;
+{
+ extern FRAME selected_frame;
+ struct symbol *func, *sym;
+ char *funname = 0;
+ struct block *b;
+ int i;
+
+ if (selected_frame == 0)
+ if (complain)
+ error ("no frame selected");
+ else return 0;
+
+ func = get_frame_function (selected_frame);
+ if (func)
+ funname = SYMBOL_NAME (func);
+ else
+ if (complain)
+ error ("no `this' in nameless context");
+ else return 0;
+
+ b = SYMBOL_BLOCK_VALUE (func);
+ i = BLOCK_NSYMS (b);
+ if (i <= 0)
+ if (complain)
+ error ("no args, no `this'");
+ else return 0;
+
+ sym = BLOCK_SYM (b, 0);
+ if (strncmp ("$this", SYMBOL_NAME (sym), 5))
+ if (complain)
+ error ("current stack frame not in method");
+ else return 0;
+
+ return read_var_value (sym, selected_frame);
+}
diff --git a/gnu/usr.bin/kgdb/valprint.c b/gnu/usr.bin/kgdb/valprint.c
new file mode 100644
index 000000000000..781eb296d391
--- /dev/null
+++ b/gnu/usr.bin/kgdb/valprint.c
@@ -0,0 +1,1430 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)valprint.c 6.5 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Print values for GNU debugger gdb.
+ Copyright (C) 1986, 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+
+/* GNU software is only expected to run on systems with 32-bit integers. */
+#define UINT_MAX 0xffffffff
+
+/* Maximum number of chars to print for a string pointer value
+ or vector contents, or UINT_MAX for no limit. */
+
+static unsigned int print_max;
+
+static void type_print_varspec_suffix ();
+static void type_print_varspec_prefix ();
+static void type_print_base ();
+static void type_print_method_args ();
+
+
+char **unsigned_type_table;
+char **signed_type_table;
+char **float_type_table;
+
+
+/* Print repeat counts if there are more than this
+ many repetitions of an element in an array. */
+#define REPEAT_COUNT_THRESHOLD 10
+
+/* Print the character string STRING, printing at most LENGTH characters.
+ Printing stops early if the number hits print_max; repeat counts
+ are printed as appropriate. Print ellipses at the end if we
+ had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. */
+
+void
+print_string (stream, string, length, force_ellipses)
+ FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ register unsigned int i;
+ unsigned int things_printed = 0;
+ int in_quotes = 0;
+ int need_comma = 0;
+
+ if (length == 0)
+ {
+ fputs_filtered ("\"\"", stdout);
+ return;
+ }
+
+ for (i = 0; i < length && things_printed < print_max; ++i)
+ {
+ /* Position of the character we are examining
+ to see whether it is repeated. */
+ unsigned int rep1;
+ /* Number of repititions we have detected so far. */
+ unsigned int reps;
+
+ QUIT;
+
+ if (need_comma)
+ {
+ fputs_filtered (", ", stream);
+ need_comma = 0;
+ }
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < length && string[rep1] == string[i])
+ {
+ ++rep1;
+ ++reps;
+ }
+
+ if (reps > REPEAT_COUNT_THRESHOLD)
+ {
+ if (in_quotes)
+ {
+ fputs_filtered ("\", ", stream);
+ in_quotes = 0;
+ }
+ fputs_filtered ("'", stream);
+ printchar (string[i], stream, '\'');
+ fprintf_filtered (stream, "' <repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += REPEAT_COUNT_THRESHOLD;
+ need_comma = 1;
+ }
+ else
+ {
+ if (!in_quotes)
+ {
+ fputs_filtered ("\"", stream);
+ in_quotes = 1;
+ }
+ printchar (string[i], stream, '"');
+ ++things_printed;
+ }
+ }
+
+ /* Terminate the quotes if necessary. */
+ if (in_quotes)
+ fputs_filtered ("\"", stream);
+
+ if (force_ellipses || i < length)
+ fputs_filtered ("...", stream);
+}
+
+/* Print the value VAL in C-ish syntax on stream STREAM.
+ FORMAT is a format-letter, or 0 for print in natural format of data type.
+ If the object printed is a string pointer, returns
+ the number of string bytes printed. */
+
+int
+value_print (val, stream, format, pretty)
+ value val;
+ FILE *stream;
+ char format;
+ enum val_prettyprint pretty;
+{
+ register unsigned int i, n, typelen;
+
+ /* A "repeated" value really contains several values in a row.
+ They are made by the @ operator.
+ Print such values as if they were arrays. */
+
+ if (VALUE_REPEATED (val))
+ {
+ n = VALUE_REPETITIONS (val);
+ typelen = TYPE_LENGTH (VALUE_TYPE (val));
+ fprintf_filtered (stream, "{");
+ /* Print arrays of characters using string syntax. */
+ if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT
+ && format == 0)
+ print_string (stream, VALUE_CONTENTS (val), n, 0);
+ else
+ {
+ unsigned int things_printed = 0;
+
+ for (i = 0; i < n && things_printed < print_max; i++)
+ {
+ /* Position of the array element we are examining to see
+ whether it is repeated. */
+ unsigned int rep1;
+ /* Number of repititions we have detected so far. */
+ unsigned int reps;
+
+ if (i != 0)
+ fprintf_filtered (stream, ", ");
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < n
+ && !bcmp (VALUE_CONTENTS (val) + typelen * i,
+ VALUE_CONTENTS (val) + typelen * rep1, typelen))
+ {
+ ++reps;
+ ++rep1;
+ }
+
+ if (reps > REPEAT_COUNT_THRESHOLD)
+ {
+ val_print (VALUE_TYPE (val),
+ VALUE_CONTENTS (val) + typelen * i,
+ VALUE_ADDRESS (val) + typelen * i,
+ stream, format, 1, 0, pretty);
+ fprintf (stream, " <repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += REPEAT_COUNT_THRESHOLD;
+ }
+ else
+ {
+ val_print (VALUE_TYPE (val),
+ VALUE_CONTENTS (val) + typelen * i,
+ VALUE_ADDRESS (val) + typelen * i,
+ stream, format, 1, 0, pretty);
+ things_printed++;
+ }
+ }
+ if (i < n)
+ fprintf_filtered (stream, "...");
+ }
+ fprintf_filtered (stream, "}");
+ return n * typelen;
+ }
+ else
+ {
+ /* If it is a pointer, indicate what it points to.
+
+ Print type also if it is a reference.
+
+ C++: if it is a member pointer, we will take care
+ of that when we print it. */
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF)
+ {
+ fprintf_filtered (stream, "(");
+ type_print (VALUE_TYPE (val), "", stream, -1);
+ fprintf_filtered (stream, ") ");
+
+ /* If this is a function pointer, try to print what
+ function it is pointing to by name. */
+ if (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (val)))
+ == TYPE_CODE_FUNC)
+ {
+ print_address (((int *) VALUE_CONTENTS (val))[0], stream);
+ /* Return value is irrelevant except for string pointers. */
+ return 0;
+ }
+ }
+ return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+ VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
+ }
+}
+
+static int prettyprint; /* Controls prettyprinting of structures. */
+int unionprint; /* Controls printing of nested unions. */
+static void scalar_print_hack();
+void (*default_scalar_print)() = scalar_print_hack;
+
+/* Print data of type TYPE located at VALADDR (within GDB),
+ which came from the inferior at address ADDRESS,
+ onto stdio stream STREAM according to FORMAT
+ (a letter or 0 for natural format).
+
+ If the data are a string pointer, returns the number of
+ sting characters printed.
+
+ if DEREF_REF is nonzero, then dereference references,
+ otherwise just print them like pointers.
+
+ The PRETTY parameter controls prettyprinting. */
+
+int
+val_print (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ char format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ register unsigned int i;
+ int len, n_baseclasses;
+ struct type *elttype;
+ int eltlen;
+ LONGEST val;
+ unsigned char c;
+
+ if (pretty == Val_pretty_default)
+ {
+ pretty = prettyprint ? Val_prettyprint : Val_no_prettyprint;
+ }
+
+ QUIT;
+
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ {
+ fprintf_filtered (stream, "<Type not defined in this context>");
+ fflush (stream);
+ return 0;
+ }
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (TYPE_LENGTH (type) >= 0
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ {
+ elttype = TYPE_TARGET_TYPE (type);
+ eltlen = TYPE_LENGTH (elttype);
+ len = TYPE_LENGTH (type) / eltlen;
+ fprintf_filtered (stream, "{");
+ /* For an array of chars, print with string syntax. */
+ if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && format == 0)
+ print_string (stream, valaddr, len, 0);
+ else
+ {
+ unsigned int things_printed = 0;
+
+ for (i = 0; i < len && things_printed < print_max; i++)
+ {
+ /* Position of the array element we are examining to see
+ whether it is repeated. */
+ unsigned int rep1;
+ /* Number of repititions we have detected so far. */
+ unsigned int reps;
+
+ if (i > 0)
+ fprintf_filtered (stream, ", ");
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < len
+ && !bcmp (valaddr + i * eltlen,
+ valaddr + rep1 * eltlen, eltlen))
+ {
+ ++reps;
+ ++rep1;
+ }
+
+ if (reps > REPEAT_COUNT_THRESHOLD)
+ {
+ val_print (elttype, valaddr + i * eltlen,
+ 0, stream, format, deref_ref,
+ recurse + 1, pretty);
+ fprintf_filtered (stream, " <repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += REPEAT_COUNT_THRESHOLD;
+ }
+ else
+ {
+ val_print (elttype, valaddr + i * eltlen,
+ 0, stream, format, deref_ref,
+ recurse + 1, pretty);
+ things_printed++;
+ }
+ }
+ if (i < len)
+ fprintf_filtered (stream, "...");
+ }
+ fprintf_filtered (stream, "}");
+ break;
+ }
+ /* Array of unspecified length: treat like pointer to first elt. */
+ valaddr = (char *) &address;
+
+ case TYPE_CODE_PTR:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
+ {
+ struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
+ struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type));
+ struct fn_field *f;
+ int j, len2;
+ char *kind = "";
+
+ val = unpack_long (builtin_type_int, valaddr);
+ if (val < 128)
+ {
+ len = TYPE_NFN_FIELDS (domain);
+ for (i = 0; i < len; i++)
+ {
+ f = TYPE_FN_FIELDLIST1 (domain, i);
+ len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ if (TYPE_FN_FIELD_VOFFSET (f, j) == val)
+ {
+ kind = "virtual";
+ goto common;
+ }
+ }
+ }
+ }
+ else
+ {
+ struct symbol *sym = find_pc_function ((CORE_ADDR) val);
+ if (sym == 0)
+ error ("invalid pointer to member function");
+ len = TYPE_NFN_FIELDS (domain);
+ for (i = 0; i < len; i++)
+ {
+ f = TYPE_FN_FIELDLIST1 (domain, i);
+ len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
+ goto common;
+ }
+ }
+ }
+ common:
+ if (i < len)
+ {
+ fprintf_filtered (stream, "&");
+ type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
+ fprintf (stream, kind);
+ if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+ && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+ TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream);
+ else
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j), "",
+ TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream);
+ break;
+ }
+ fprintf_filtered (stream, "(");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, ") %d", (int) val >> 3);
+ }
+ else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
+ {
+ struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
+ struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type));
+ char *kind = "";
+
+ /* VAL is a byte offset into the structure type DOMAIN.
+ Find the name of the field for that offset and
+ print it. */
+ int extra = 0;
+ int bits = 0;
+ len = TYPE_NFIELDS (domain);
+ /* @@ Make VAL into bit offset */
+ val = unpack_long (builtin_type_int, valaddr) << 3;
+ for (i = 0; i < len; i++)
+ {
+ int bitpos = TYPE_FIELD_BITPOS (domain, i);
+ QUIT;
+ if (val == bitpos)
+ break;
+ if (val < bitpos && i > 0)
+ {
+ int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
+ /* Somehow pointing into a field. */
+ i -= 1;
+ extra = (val - TYPE_FIELD_BITPOS (domain, i));
+ if (extra & 0x3)
+ bits = 1;
+ else
+ extra >>= 3;
+ break;
+ }
+ }
+ if (i < len)
+ {
+ fprintf_filtered (stream, "&");
+ type_print_base (domain, stream, 0, 0);
+ fprintf_filtered (stream, "::");
+ fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
+ if (extra)
+ fprintf_filtered (stream, " + %d bytes", extra);
+ if (bits)
+ fprintf_filtered (stream, " (offset in bits)");
+ break;
+ }
+ fprintf_filtered (stream, "%d", val >> 3);
+ }
+ else
+ {
+ fprintf_filtered (stream, "0x%x", * (int *) valaddr);
+ /* For a pointer to char or unsigned char,
+ also print the string pointed to, unless pointer is null. */
+
+ /* For an array of chars, print with string syntax. */
+ elttype = TYPE_TARGET_TYPE (type);
+ i = 0; /* Number of characters printed. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && format == 0
+ && unpack_long (type, valaddr) != 0
+ /* If print_max is UINT_MAX, the alloca below will fail.
+ In that case don't try to print the string. */
+ && print_max < UINT_MAX)
+ {
+ fprintf_filtered (stream, " ");
+
+ /* Get first character. */
+ if (read_memory ( (CORE_ADDR) unpack_long (type, valaddr),
+ &c, 1))
+ {
+ /* First address out of bounds. */
+ fprintf_filtered (stream, "<Address 0x%x out of bounds>",
+ (* (int *) valaddr));
+ break;
+ }
+ else
+ {
+ /* A real string. */
+ int out_of_bounds = 0;
+ char *string = (char *) alloca (print_max);
+
+ /* If the loop ends by us hitting print_max characters,
+ we need to have elipses at the end. */
+ int force_ellipses = 1;
+
+ /* This loop only fetches print_max characters, even
+ though print_string might want to print more
+ (with repeated characters). This is so that
+ we don't spend forever fetching if we print
+ a long string consisting of the same character
+ repeated. */
+ while (i < print_max)
+ {
+ QUIT;
+ if (read_memory ((CORE_ADDR) unpack_long (type, valaddr)
+ + i, &c, 1))
+ {
+ out_of_bounds = 1;
+ force_ellipses = 0;
+ break;
+ }
+ else if (c == '\0')
+ {
+ force_ellipses = 0;
+ break;
+ }
+ else
+ string[i++] = c;
+ }
+
+ if (i != 0)
+ print_string (stream, string, i, force_ellipses);
+ if (out_of_bounds)
+ fprintf_filtered (stream,
+ " <Address 0x%x out of bounds>",
+ (*(int *) valaddr) + i);
+ }
+
+ fflush (stream);
+ }
+ /* Return number of characters printed, plus one for the
+ terminating null if we have "reached the end". */
+ return i + (print_max && i != print_max);
+ }
+ break;
+
+ case TYPE_CODE_MEMBER:
+ error ("not implemented: member type in val_print");
+ break;
+
+ case TYPE_CODE_REF:
+ fprintf_filtered (stream, "(0x%x &) = ", * (int *) valaddr);
+ /* De-reference the reference. */
+ if (deref_ref)
+ {
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
+ {
+ value val = value_at (TYPE_TARGET_TYPE (type), * (int *) valaddr);
+ val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+ VALUE_ADDRESS (val), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ else
+ fprintf_filtered (stream, "???");
+ }
+ break;
+
+ case TYPE_CODE_UNION:
+ if (recurse && !unionprint)
+ {
+ fprintf_filtered (stream, "{...}");
+ break;
+ }
+ /* Fall through. */
+ case TYPE_CODE_STRUCT:
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ n_baseclasses = TYPE_N_BASECLASSES (type);
+ for (i = 1; i <= n_baseclasses; i++)
+ {
+ fprintf_filtered (stream, "\n");
+ if (pretty)
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ fputs_filtered ("<", stream);
+ fputs_filtered (TYPE_NAME (TYPE_BASECLASS (type, i)), stream);
+ fputs_filtered ("> = ", stream);
+ val_print (TYPE_FIELD_TYPE (type, 0),
+ valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8,
+ 0, stream, 0, 0, recurse + 1, pretty);
+ }
+ if (i > 1) {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ fputs_filtered ("members of ", stream);
+ fputs_filtered (TYPE_NAME (type), stream);
+ fputs_filtered (": ", stream);
+ }
+ if (!len && i == 1)
+ fprintf_filtered (stream, "<No data fields>");
+ else
+ {
+ for (i -= 1; i < len; i++)
+ {
+ if (i > n_baseclasses) fprintf_filtered (stream, ", ");
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ fputs_filtered (" = ", stream);
+ /* check if static field */
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ value v;
+
+ v = value_static_field (type, TYPE_FIELD_NAME (type, i), i);
+ val_print (TYPE_FIELD_TYPE (type, i),
+ VALUE_CONTENTS (v), 0, stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ else if (TYPE_FIELD_PACKED (type, i))
+ {
+ char *valp = (char *) & val;
+ union {int i; char c;} test;
+ test.i = 1;
+ if (test.c != 1)
+ valp += sizeof val - TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
+ val = unpack_field_as_long (type, valaddr, i);
+ val_print (TYPE_FIELD_TYPE (type, i), valp, 0,
+ stream, format, deref_ref, recurse + 1, pretty);
+ }
+ else
+ {
+ val_print (TYPE_FIELD_TYPE (type, i),
+ valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
+ 0, stream, format, deref_ref,
+ recurse + 1, pretty);
+ }
+ }
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ }
+ fprintf_filtered (stream, "}");
+ break;
+
+ case TYPE_CODE_ENUM:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ len = TYPE_NFIELDS (type);
+ val = unpack_long (builtin_type_int, valaddr);
+ for (i = 0; i < len; i++)
+ {
+ QUIT;
+ if (val == TYPE_FIELD_BITPOS (type, i))
+ break;
+ }
+ if (i < len)
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ else
+ fprintf_filtered (stream, "%d", (int) val);
+ break;
+
+ case TYPE_CODE_FUNC:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ fprintf_filtered (stream, "{");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, "} ");
+ fprintf_filtered (stream, "0x%x", address);
+ break;
+
+ case TYPE_CODE_INT:
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ {
+ (*default_scalar_print)(stream, type, unpack_long(type, valaddr));
+#ifdef notdef
+ if (TYPE_LENGTH (type) == 1)
+ {
+ fprintf_filtered (stream, " '");
+ printchar ((unsigned char) unpack_long (type, valaddr),
+ stream, '\'');
+ fprintf_filtered (stream, "'");
+ }
+#endif
+ }
+ break;
+
+ case TYPE_CODE_FLT:
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ print_floating (valaddr, type, stream);
+ break;
+
+ case TYPE_CODE_VOID:
+ fprintf_filtered (stream, "void");
+ break;
+
+ default:
+ error ("Invalid type code in symbol table.");
+ }
+ fflush (stream);
+ return 0;
+}
+
+/* Print a description of a type TYPE
+ in the form of a declaration of a variable named VARSTRING.
+ Output goes to STREAM (via stdio).
+ If SHOW is positive, we show the contents of the outermost level
+ of structure even if there is a type name that could be used instead.
+ If SHOW is negative, we never show the details of elements' types. */
+
+void
+type_print (type, varstring, stream, show)
+ struct type *type;
+ char *varstring;
+ FILE *stream;
+ int show;
+{
+ type_print_1 (type, varstring, stream, show, 0);
+}
+
+/* LEVEL is the depth to indent lines by. */
+
+void
+type_print_1 (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ FILE *stream;
+ int show;
+ int level;
+{
+ register enum type_code code;
+ type_print_base (type, stream, show, level);
+ code = TYPE_CODE (type);
+ if ((varstring && *varstring)
+ ||
+ /* Need a space if going to print stars or brackets;
+ but not if we will print just a type name. */
+ ((show > 0 || TYPE_NAME (type) == 0)
+ &&
+ (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
+ || code == TYPE_CODE_METHOD
+ || code == TYPE_CODE_ARRAY
+ || code == TYPE_CODE_MEMBER
+ || code == TYPE_CODE_REF)))
+ fprintf_filtered (stream, " ");
+ type_print_varspec_prefix (type, stream, show, 0);
+ fputs_filtered (varstring, stream);
+ type_print_varspec_suffix (type, stream, show, 0);
+}
+
+/* Print the method arguments ARGS to the file STREAM. */
+static void
+type_print_method_args (args, prefix, varstring, staticp, stream)
+ struct type **args;
+ char *prefix, *varstring;
+ int staticp;
+ FILE *stream;
+{
+ int i;
+
+ fputs_filtered (" ", stream);
+ fputs_filtered (prefix, stream);
+ fputs_filtered (varstring, stream);
+ fputs_filtered (" (", stream);
+ if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID)
+ {
+ i = !staticp; /* skip the class variable */
+ while (1)
+ {
+ type_print (args[i++], "", stream, 0);
+ if (!args[i])
+ {
+ fprintf_filtered (stream, " ...");
+ break;
+ }
+ else if (args[i]->code != TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream, ", ");
+ }
+ else break;
+ }
+ }
+ fprintf_filtered (stream, ")");
+}
+
+/* If TYPE is a derived type, then print out derivation
+ information. Print out all layers of the type heirarchy
+ until we encounter one with multiple inheritance.
+ At that point, print out that ply, and return. */
+static void
+type_print_derivation_info (stream, type)
+ FILE *stream;
+ struct type *type;
+{
+ char *name;
+ int i, n_baseclasses = TYPE_N_BASECLASSES (type);
+ struct type *basetype = 0;
+
+ while (type && n_baseclasses == 1)
+ {
+ basetype = TYPE_BASECLASS (type, 1);
+ if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
+ {
+ while (*name != ' ') name++;
+ fprintf_filtered (stream, ": %s%s ",
+ TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
+ TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "");
+ fputs_filtered (name + 1, stream);
+ fputs_filtered (" ", stream);
+ }
+ n_baseclasses = TYPE_N_BASECLASSES (basetype);
+ type = basetype;
+ }
+
+ if (type)
+ {
+ if (n_baseclasses != 0)
+ fprintf_filtered (stream, ": ");
+ for (i = 1; i <= n_baseclasses; i++)
+ {
+ basetype = TYPE_BASECLASS (type, i);
+ if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
+ {
+ while (*name != ' ') name++;
+ fprintf_filtered (stream, "%s%s ",
+ TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
+ TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "");
+ fputs_filtered (name + 1, stream);
+ }
+ if (i < n_baseclasses)
+ fprintf_filtered (stream, ", ");
+ }
+ fprintf_filtered (stream, " ");
+ }
+}
+
+/* Print any asterisks or open-parentheses needed before the
+ variable name (to describe its type).
+
+ On outermost call, pass 0 for PASSED_A_PTR.
+ On outermost call, SHOW > 0 means should ignore
+ any typename for TYPE and show its details.
+ SHOW is always zero on recursive calls. */
+
+static void
+type_print_varspec_prefix (type, stream, show, passed_a_ptr)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int passed_a_ptr;
+{
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ fprintf_filtered (stream, "*");
+ break;
+
+ case TYPE_CODE_MEMBER:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+ 0);
+ fprintf_filtered (stream, " ");
+ type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0,
+ passed_a_ptr);
+ fprintf_filtered (stream, "::");
+ break;
+
+ case TYPE_CODE_METHOD:
+ if (passed_a_ptr)
+ fprintf (stream, "(");
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+ 0);
+ fprintf_filtered (stream, " ");
+ type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0,
+ passed_a_ptr);
+ fprintf_filtered (stream, "::");
+ break;
+
+ case TYPE_CODE_REF:
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ fprintf_filtered (stream, "&");
+ break;
+
+ case TYPE_CODE_FUNC:
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+ 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ break;
+
+ case TYPE_CODE_ARRAY:
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+ 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ }
+}
+
+/* Print any array sizes, function arguments or close parentheses
+ needed after the variable name (to describe its type).
+ Args work like type_print_varspec_prefix. */
+
+static void
+type_print_varspec_suffix (type, stream, show, passed_a_ptr)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int passed_a_ptr;
+{
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+
+ fprintf_filtered (stream, "[");
+ if (TYPE_LENGTH (type) >= 0
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ fprintf_filtered (stream, "%d",
+ (TYPE_LENGTH (type)
+ / TYPE_LENGTH (TYPE_TARGET_TYPE (type))));
+ fprintf_filtered (stream, "]");
+
+ type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+ 0);
+ break;
+
+ case TYPE_CODE_MEMBER:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ break;
+
+ case TYPE_CODE_METHOD:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ {
+ int i;
+ struct type **args = TYPE_ARG_TYPES (type);
+
+ fprintf_filtered (stream, "(");
+ if (args[1] == 0)
+ fprintf_filtered (stream, "...");
+ else for (i = 1; args[i] != 0 && args[i]->code != TYPE_CODE_VOID; i++)
+ {
+ type_print_1 (args[i], "", stream, -1, 0);
+ if (args[i+1] == 0)
+ fprintf_filtered (stream, "...");
+ else if (args[i+1]->code != TYPE_CODE_VOID)
+ fprintf_filtered (stream, ",");
+ }
+ fprintf_filtered (stream, ")");
+ }
+ break;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ break;
+
+ case TYPE_CODE_FUNC:
+ type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ fprintf_filtered (stream, "()");
+ break;
+ }
+}
+
+/* Print the name of the type (or the ultimate pointer target,
+ function value or array element), or the description of a
+ structure or union.
+
+ SHOW nonzero means don't print this type as just its name;
+ show its real definition even if it has a name.
+ SHOW zero means print just typename or struct tag if there is one
+ SHOW negative means abbreviate structure elements.
+ SHOW is decremented for printing of structure elements.
+
+ LEVEL is the depth to indent by.
+ We increase it for some recursive calls. */
+
+static void
+type_print_base (type, stream, show, level)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int level;
+{
+ char *name;
+ register int i;
+ register int len;
+ register int lastval;
+
+ QUIT;
+
+ if (type == 0)
+ {
+ fprintf_filtered (stream, "type unknown");
+ return;
+ }
+
+ if (TYPE_NAME (type) && show <= 0)
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ return;
+ }
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_METHOD:
+ type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ fprintf_filtered (stream, "struct ");
+ goto struct_union;
+
+ case TYPE_CODE_UNION:
+ fprintf_filtered (stream, "union ");
+ struct_union:
+ if (TYPE_NAME (type) && (name = TYPE_NAME (type)))
+ {
+ while (*name != ' ') name++;
+ fputs_filtered (name + 1, stream);
+ fputs_filtered (" ", stream);
+ }
+ if (show < 0)
+ fprintf_filtered (stream, "{...}");
+ else
+ {
+ int i;
+
+ type_print_derivation_info (stream, type);
+
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ if (len)
+ fprintf_filtered (stream, "\n");
+ else
+ {
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ fprintf_filtered (stream, "<incomplete type>\n");
+ else
+ fprintf_filtered (stream, "<no data fields>\n");
+ }
+
+ /* If there is a base class for this type,
+ do not print the field that it occupies. */
+ for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+ {
+ QUIT;
+ /* Don't print out virtual function table. */
+ if (! strncmp (TYPE_FIELD_NAME (type, i),
+ "_vptr$", 6))
+ continue;
+
+ print_spaces_filtered (level + 4, stream);
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ fprintf_filtered (stream, "static ");
+ }
+ type_print_1 (TYPE_FIELD_TYPE (type, i),
+ TYPE_FIELD_NAME (type, i),
+ stream, show - 1, level + 4);
+ if (!TYPE_FIELD_STATIC (type, i)
+ && TYPE_FIELD_PACKED (type, i))
+ {
+ /* It is a bitfield. This code does not attempt
+ to look at the bitpos and reconstruct filler,
+ unnamed fields. This would lead to misleading
+ results if the compiler does not put out fields
+ for such things (I don't know what it does). */
+ fprintf_filtered (stream, " : %d",
+ TYPE_FIELD_BITSIZE (type, i));
+ }
+ fprintf_filtered (stream, ";\n");
+ }
+
+ /* C++: print out the methods */
+ len = TYPE_NFN_FIELDS (type);
+ if (len) fprintf_filtered (stream, "\n");
+ for (i = 0; i < len; i++)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
+
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ print_spaces_filtered (level + 4, stream);
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ fprintf_filtered (stream, "virtual ");
+ else if (TYPE_FN_FIELD_STATIC_P (f, j))
+ fprintf_filtered (stream, "static ");
+ type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), "", stream, 0);
+ if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+ && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+ TYPE_FN_FIELDLIST_NAME (type, i), 0, stream);
+ else
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j), "",
+ TYPE_FN_FIELDLIST_NAME (type, i),
+ TYPE_FN_FIELD_STATIC_P (f, j), stream);
+
+ fprintf_filtered (stream, ";\n");
+ }
+ if (len2) fprintf_filtered (stream, "\n");
+ }
+
+ print_spaces_filtered (level, stream);
+ fprintf_filtered (stream, "}");
+ }
+ break;
+
+ case TYPE_CODE_ENUM:
+ fprintf_filtered (stream, "enum ");
+ if (TYPE_NAME (type))
+ {
+ name = TYPE_NAME (type);
+ while (*name != ' ') name++;
+ fputs_filtered (name + 1, stream);
+ fputs_filtered (" ", stream);
+ }
+ if (show < 0)
+ fprintf_filtered (stream, "{...}");
+ else
+ {
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ lastval = 0;
+ for (i = 0; i < len; i++)
+ {
+ QUIT;
+ if (i) fprintf_filtered (stream, ", ");
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ if (lastval != TYPE_FIELD_BITPOS (type, i))
+ {
+ fprintf_filtered (stream, " : %d", TYPE_FIELD_BITPOS (type, i));
+ lastval = TYPE_FIELD_BITPOS (type, i);
+ }
+ lastval++;
+ }
+ fprintf_filtered (stream, "}");
+ }
+ break;
+
+ case TYPE_CODE_INT:
+ if (TYPE_UNSIGNED (type))
+ name = unsigned_type_table[TYPE_LENGTH (type)];
+ else
+ name = signed_type_table[TYPE_LENGTH (type)];
+ fputs_filtered (name, stream);
+ break;
+
+ case TYPE_CODE_FLT:
+ name = float_type_table[TYPE_LENGTH (type)];
+ fputs_filtered (name, stream);
+ break;
+
+ case TYPE_CODE_VOID:
+ fprintf_filtered (stream, "void");
+ break;
+
+ case 0:
+ fprintf_filtered (stream, "struct unknown");
+ break;
+
+ default:
+ error ("Invalid type code in symbol table.");
+ }
+}
+
+static void
+scalar_print_decimal(stream, type, val)
+ FILE *stream;
+ struct type *type;
+ LONGEST val;
+{
+ fprintf_filtered(stream, TYPE_UNSIGNED(type)? "%lu":"%ld", val);
+}
+
+static void
+scalar_print_hex(stream, type, val)
+ FILE *stream;
+ struct type *type;
+ LONGEST val;
+{
+ switch (TYPE_LENGTH(type)) {
+ case 1:
+ fprintf_filtered (stream, "0x%02lx", val);
+ break;
+ case 2:
+ fprintf_filtered (stream, "0x%04lx", val);
+ break;
+ case 4:
+ fprintf_filtered (stream, "0x%08lx", val);
+ break;
+ default:
+ fprintf_filtered (stream, "0x%lx", val);
+ break;
+ }
+}
+
+static void
+scalar_print_octal(stream, type, val)
+ FILE *stream;
+ struct type *type;
+ LONGEST val;
+{
+ switch (TYPE_LENGTH(type)) {
+ case 1:
+ fprintf_filtered (stream, "0%03lo", val);
+ break;
+ case 2:
+ fprintf_filtered (stream, "0%06lo", val);
+ break;
+ case 4:
+ fprintf_filtered (stream, "0%012lo", val);
+ break;
+ default:
+ fprintf_filtered (stream, "0%lo", val);
+ break;
+ }
+}
+
+static void
+scalar_print_hack(stream, type, val)
+ FILE *stream;
+ struct type *type;
+ LONGEST val;
+{
+ if (TYPE_UNSIGNED(type))
+ scalar_print_hex(stream, type, val);
+ else
+ scalar_print_decimal(stream, type, val);
+}
+
+static void
+set_maximum_command (arg)
+ char *arg;
+{
+ if (!arg) error_no_arg ("value for maximum elements to print");
+ print_max = parse_and_eval_address (arg);
+ if (print_max == 0)
+ print_max = UINT_MAX;
+}
+
+static void
+set_base_command(arg)
+ char *arg;
+{
+ int base;
+
+ if (!arg)
+ base = 0;
+ else
+ base = parse_and_eval_address (arg);
+ switch (base) {
+ default:
+ default_scalar_print = scalar_print_hack;
+ break;
+ case 8:
+ default_scalar_print = scalar_print_octal;
+ break;
+ case 10:
+ default_scalar_print = scalar_print_decimal;
+ break;
+ case 16:
+ default_scalar_print = scalar_print_hex;
+ break;
+ }
+}
+
+static void
+set_prettyprint_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ prettyprint = parse_binary_operation ("set prettyprint", arg);
+}
+
+static void
+set_unionprint_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ unionprint = parse_binary_operation ("set unionprint", arg);
+}
+
+format_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (arg)
+ error ("\"info format\" does not take any arguments.");
+ printf ("Prettyprinting of structures is %s.\n",
+ prettyprint ? "on" : "off");
+ printf ("Printing of unions interior to structures is %s.\n",
+ unionprint ? "on" : "off");
+ if (print_max == UINT_MAX)
+ printf_filtered
+ ("There is no maximum number of array elements printed.\n");
+ else
+ printf_filtered
+ ("The maximum number of array elements printed is %d.\n", print_max);
+}
+
+extern struct cmd_list_element *setlist;
+
+void
+_initialize_valprint ()
+{
+ add_cmd ("base", class_support, set_base_command,
+ "Change default integer print radix to 8, 10 or 16\n\
+No args returns to the ad-hoc default of `16' for unsigned values\n\
+and `10' otherwise.",
+ &setlist);
+ add_cmd ("array-max", class_vars, set_maximum_command,
+ "Set NUMBER as limit on string chars or array elements to print.\n\
+\"set array-max 0\" causes there to be no limit.",
+ &setlist);
+
+ add_cmd ("prettyprint", class_support, set_prettyprint_command,
+ "Turn prettyprinting of structures on and off.",
+ &setlist);
+ add_alias_cmd ("pp", "prettyprint", class_support, 1, &setlist);
+
+ add_cmd ("unionprint", class_support, set_unionprint_command,
+ "Turn printing of unions interior to structures on and off.",
+ &setlist);
+
+ add_info ("format", format_info,
+ "Show current settings of data formatting options.");
+
+ /* Give people the defaults which they are used to. */
+ prettyprint = 0;
+ unionprint = 1;
+
+ print_max = 200;
+
+ unsigned_type_table
+ = (char **) xmalloc ((1 + sizeof (unsigned LONGEST)) * sizeof (char *));
+ bzero (unsigned_type_table, (1 + sizeof (unsigned LONGEST)));
+ unsigned_type_table[sizeof (unsigned char)] = "unsigned char";
+ unsigned_type_table[sizeof (unsigned short)] = "unsigned short";
+ unsigned_type_table[sizeof (unsigned long)] = "unsigned long";
+ unsigned_type_table[sizeof (unsigned int)] = "unsigned int";
+#ifdef LONG_LONG
+ unsigned_type_table[sizeof (unsigned long long)] = "unsigned long long";
+#endif
+
+ signed_type_table
+ = (char **) xmalloc ((1 + sizeof (LONGEST)) * sizeof (char *));
+ bzero (signed_type_table, (1 + sizeof (LONGEST)));
+ signed_type_table[sizeof (char)] = "char";
+ signed_type_table[sizeof (short)] = "short";
+ signed_type_table[sizeof (long)] = "long";
+ signed_type_table[sizeof (int)] = "int";
+#ifdef LONG_LONG
+ signed_type_table[sizeof (long long)] = "long long";
+#endif
+
+ float_type_table
+ = (char **) xmalloc ((1 + sizeof (double)) * sizeof (char *));
+ bzero (float_type_table, (1 + sizeof (double)));
+ float_type_table[sizeof (float)] = "float";
+ float_type_table[sizeof (double)] = "double";
+}
+
diff --git a/gnu/usr.bin/kgdb/value.h b/gnu/usr.bin/kgdb/value.h
new file mode 100644
index 000000000000..07dd8e840eb7
--- /dev/null
+++ b/gnu/usr.bin/kgdb/value.h
@@ -0,0 +1,212 @@
+/* Definitions for values of C expressions, for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * The structure which defines the type of a value. It should never
+ * be possible for a program lval value to survive over a call to the inferior
+ * (ie to be put into the history list or an internal variable).
+ */
+enum lval_type {
+ /* Not an lval. */
+ not_lval,
+ /* In memory. Could be a saved register. */
+ lval_memory,
+ /* In a register. */
+ lval_register,
+ /* In a gdb internal variable. */
+ lval_internalvar,
+ /* Part of a gdb internal variable (structure field). */
+ lval_internalvar_component,
+ /* In a register series in a frame not the current one, which may have been
+ partially saved or saved in different places (otherwise would be
+ lval_register or lval_memory). */
+ lval_reg_frame_relative,
+};
+
+struct value
+ {
+ /* Type of value; either not an lval, or one of the various
+ different possible kinds of lval. */
+ enum lval_type lval;
+ /* Location of value (if lval). */
+ union
+ {
+ /* Address in inferior or byte of registers structure. */
+ CORE_ADDR address;
+ /* Pointer to interrnal variable. */
+ struct internalvar *internalvar;
+ /* Number of register. Only used with
+ lval_reg_frame_relative. */
+ int regnum;
+ } location;
+ /* Describes offset of a value within lval a structure in bytes. */
+ int offset;
+ /* Only used for bitfields; number of bits contained in them. */
+ int bitsize;
+ /* Only used for bitfields; position of start of field. */
+ int bitpos;
+ /* Frame value is relative to. In practice, this address is only
+ used if the value is stored in several registers in other than
+ the current frame, and these registers have not all been saved
+ at the same place in memory. This will be described in the
+ lval enum above as "lval_reg_frame_relative". */
+ CORE_ADDR frame_addr;
+ /* Type of the value. */
+ struct type *type;
+ /* Values are stored in a chain, so that they can be deleted
+ easily over calls to the inferior. Values assigned to internal
+ variables or put into the value history are taken off this
+ list. */
+ struct value *next;
+ /* If an lval is forced to repeat, a new value is created with
+ these fields set. The new value is not an lval. */
+ short repeated;
+ short repetitions;
+ /* Register number if the value is from a register. Is not kept
+ if you take a field of a structure that is stored in a
+ register. Shouldn't it be? */
+ short regno;
+ /* Actual contents of the value. For use of this value; setting
+ it uses the stuff above. */
+ long contents[1];
+ };
+
+typedef struct value *value;
+
+#define VALUE_TYPE(val) (val)->type
+#define VALUE_CONTENTS(val) ((char *) (val)->contents)
+#define VALUE_LVAL(val) (val)->lval
+#define VALUE_ADDRESS(val) (val)->location.address
+#define VALUE_INTERNALVAR(val) (val)->location.internalvar
+#define VALUE_FRAME_REGNUM(val) ((val)->location.regnum)
+#define VALUE_FRAME(val) ((val)->frame_addr)
+#define VALUE_OFFSET(val) (val)->offset
+#define VALUE_BITSIZE(val) (val)->bitsize
+#define VALUE_BITPOS(val) (val)->bitpos
+#define VALUE_NEXT(val) (val)->next
+#define VALUE_REPEATED(val) (val)->repeated
+#define VALUE_REPETITIONS(val) (val)->repetitions
+#define VALUE_REGNO(val) (val)->regno
+
+/* If ARG is an array, convert it to a pointer.
+ If ARG is an enum, convert it to an integer.
+
+ References are dereferenced. */
+
+#define COERCE_ARRAY(arg) \
+{ if (TYPE_CODE ( VALUE_TYPE (arg)) == TYPE_CODE_REF) \
+ arg = value_ind (arg); \
+ if (VALUE_REPEATED (arg) \
+ || TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY) \
+ arg = value_coerce_array (arg); \
+ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
+ arg = value_cast (builtin_type_unsigned_int, arg); \
+}
+
+/* If ARG is an enum, convert it to an integer. */
+
+#define COERCE_ENUM(arg) \
+{ if (TYPE_CODE ( VALUE_TYPE (arg)) == TYPE_CODE_REF) \
+ arg = value_ind (arg); \
+ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
+ arg = value_cast (builtin_type_unsigned_int, arg); \
+}
+
+/* Internal variables (variables for convenience of use of debugger)
+ are recorded as a chain of these structures. */
+
+struct internalvar
+{
+ struct internalvar *next;
+ char *name;
+ value value;
+};
+
+LONGEST value_as_long ();
+double value_as_double ();
+LONGEST unpack_long ();
+double unpack_double ();
+long unpack_field_as_long ();
+value value_from_long ();
+value value_from_double ();
+value value_at ();
+value value_from_register ();
+value value_of_variable ();
+value value_of_register ();
+value read_var_value ();
+value locate_var_value ();
+value allocate_value ();
+value allocate_repeat_value ();
+value value_string ();
+
+value value_binop ();
+value value_add ();
+value value_sub ();
+value value_coerce_array ();
+value value_ind ();
+value value_addr ();
+value value_assign ();
+value value_neg ();
+value value_lognot ();
+value value_struct_elt (), value_struct_elt_for_address ();
+value value_field ();
+value value_cast ();
+value value_zero ();
+value value_repeat ();
+value value_subscript ();
+
+value call_function ();
+value value_being_returned ();
+int using_struct_return ();
+
+value evaluate_expression ();
+value evaluate_type ();
+value parse_and_eval ();
+value parse_to_comma_and_eval ();
+
+value access_value_history ();
+value value_of_internalvar ();
+struct internalvar *lookup_internalvar ();
+
+int value_equal ();
+int value_less ();
+int value_zerop ();
+
+/* C++ */
+value value_of_this ();
+value value_static_field ();
+value value_x_binop ();
+value value_x_unop ();
+int binop_user_defined_p ();
+int unop_user_defined_p ();
+
+void read_register_bytes ();
+void modify_field ();
+void type_print ();
+void type_print_1 ();
+
+/* Possibilities for prettyprint parameters to routines which print
+ things. */
+enum val_prettyprint {
+ Val_no_prettyprint = 0,
+ Val_prettyprint,
+ /* Use the default setting which the user has specified. */
+ Val_pretty_default
+ };
+
diff --git a/gnu/usr.bin/kgdb/values.c b/gnu/usr.bin/kgdb/values.c
new file mode 100644
index 000000000000..93a291112a65
--- /dev/null
+++ b/gnu/usr.bin/kgdb/values.c
@@ -0,0 +1,1059 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)values.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/* Low level packing and unpacking of values for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+
+/* The value-history records all the values printed
+ by print commands during this session. Each chunk
+ records 60 consecutive values. The first chunk on
+ the chain records the most recent values.
+ The total number of values is in value_history_count. */
+
+#define VALUE_HISTORY_CHUNK 60
+
+struct value_history_chunk
+{
+ struct value_history_chunk *next;
+ value values[VALUE_HISTORY_CHUNK];
+};
+
+/* Chain of chunks now in use. */
+
+static struct value_history_chunk *value_history_chain;
+
+static int value_history_count; /* Abs number of last entry stored */
+
+
+/* List of all value objects currently allocated
+ (except for those released by calls to release_value)
+ This is so they can be freed after each command. */
+
+static value all_values;
+
+/* Allocate a value that has the correct length for type TYPE. */
+
+value
+allocate_value (type)
+ struct type *type;
+{
+ register value val;
+
+ /* If the type we want had no definition in the file it first
+ * appeared in, it will be marked a `stub'. The real definition
+ * probably appeared later so try to find it. */
+ if (TYPE_FLAGS(type) & TYPE_FLAG_STUB)
+ {
+ register char *cp;
+ register struct symbol *sym;
+ extern char *index();
+
+ if (cp = index(TYPE_NAME(type), ' '))
+ ++cp;
+ else
+ cp = TYPE_NAME(type);
+
+ sym = lookup_symbol(cp, 0, STRUCT_NAMESPACE, 0);
+
+ if (sym && TYPE_CODE(SYMBOL_TYPE(sym)) == TYPE_CODE(type))
+ bcopy (SYMBOL_TYPE (sym), type, sizeof (*type));
+ }
+ val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type));
+ VALUE_NEXT (val) = all_values;
+ all_values = val;
+ VALUE_TYPE (val) = type;
+ VALUE_LVAL (val) = not_lval;
+ VALUE_ADDRESS (val) = 0;
+ VALUE_FRAME (val) = 0;
+ VALUE_OFFSET (val) = 0;
+ VALUE_BITPOS (val) = 0;
+ VALUE_BITSIZE (val) = 0;
+ VALUE_REPEATED (val) = 0;
+ VALUE_REPETITIONS (val) = 0;
+ VALUE_REGNO (val) = -1;
+ return val;
+}
+
+/* Allocate a value that has the correct length
+ for COUNT repetitions type TYPE. */
+
+value
+allocate_repeat_value (type, count)
+ struct type *type;
+ int count;
+{
+ register value val;
+
+ val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count);
+ VALUE_NEXT (val) = all_values;
+ all_values = val;
+ VALUE_TYPE (val) = type;
+ VALUE_LVAL (val) = not_lval;
+ VALUE_ADDRESS (val) = 0;
+ VALUE_FRAME (val) = 0;
+ VALUE_OFFSET (val) = 0;
+ VALUE_BITPOS (val) = 0;
+ VALUE_BITSIZE (val) = 0;
+ VALUE_REPEATED (val) = 1;
+ VALUE_REPETITIONS (val) = count;
+ VALUE_REGNO (val) = -1;
+ return val;
+}
+
+/* Free all the values that have been allocated (except for those released).
+ Called after each command, successful or not. */
+
+void
+free_all_values ()
+{
+ register value val, next;
+
+ for (val = all_values; val; val = next)
+ {
+ next = VALUE_NEXT (val);
+ free (val);
+ }
+
+ all_values = 0;
+}
+
+/* Remove VAL from the chain all_values
+ so it will not be freed automatically. */
+
+void
+release_value (val)
+ register value val;
+{
+ register value v;
+
+ if (all_values == val)
+ {
+ all_values = val->next;
+ return;
+ }
+
+ for (v = all_values; v; v = v->next)
+ {
+ if (v->next == val)
+ {
+ v->next = val->next;
+ break;
+ }
+ }
+}
+
+/* Return a copy of the value ARG.
+ It contains the same contents, for same memory address,
+ but it's a different block of storage. */
+
+static value
+value_copy (arg)
+ value arg;
+{
+ register value val;
+ register struct type *type = VALUE_TYPE (arg);
+ if (VALUE_REPEATED (arg))
+ val = allocate_repeat_value (type, VALUE_REPETITIONS (arg));
+ else
+ val = allocate_value (type);
+ VALUE_LVAL (val) = VALUE_LVAL (arg);
+ VALUE_ADDRESS (val) = VALUE_ADDRESS (arg);
+ VALUE_OFFSET (val) = VALUE_OFFSET (arg);
+ VALUE_BITPOS (val) = VALUE_BITPOS (arg);
+ VALUE_BITSIZE (val) = VALUE_BITSIZE (arg);
+ VALUE_REGNO (val) = VALUE_REGNO (arg);
+ bcopy (VALUE_CONTENTS (arg), VALUE_CONTENTS (val),
+ TYPE_LENGTH (VALUE_TYPE (arg))
+ * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
+ return val;
+}
+
+/* Access to the value history. */
+
+/* Record a new value in the value history.
+ Returns the absolute history index of the entry. */
+
+int
+record_latest_value (val)
+ value val;
+{
+ int i;
+ double foo;
+
+ /* Check error now if about to store an invalid float. We return -1
+ to the caller, but allow them to continue, e.g. to print it as "Nan". */
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) {
+ foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i);
+ if (i) return -1; /* Indicate value not saved in history */
+ }
+
+ /* Here we treat value_history_count as origin-zero
+ and applying to the value being stored now. */
+
+ i = value_history_count % VALUE_HISTORY_CHUNK;
+ if (i == 0)
+ {
+ register struct value_history_chunk *new
+ = (struct value_history_chunk *)
+ xmalloc (sizeof (struct value_history_chunk));
+ bzero (new->values, sizeof new->values);
+ new->next = value_history_chain;
+ value_history_chain = new;
+ }
+
+ value_history_chain->values[i] = val;
+ release_value (val);
+
+ /* Now we regard value_history_count as origin-one
+ and applying to the value just stored. */
+
+ return ++value_history_count;
+}
+
+/* Return a copy of the value in the history with sequence number NUM. */
+
+value
+access_value_history (num)
+ int num;
+{
+ register struct value_history_chunk *chunk;
+ register int i;
+ register int absnum = num;
+
+ if (absnum <= 0)
+ absnum += value_history_count;
+
+ if (absnum <= 0)
+ {
+ if (num == 0)
+ error ("The history is empty.");
+ else if (num == 1)
+ error ("There is only one value in the history.");
+ else
+ error ("History does not go back to $$%d.", -num);
+ }
+ if (absnum > value_history_count)
+ error ("History has not yet reached $%d.", absnum);
+
+ absnum--;
+
+ /* Now absnum is always absolute and origin zero. */
+
+ chunk = value_history_chain;
+ for (i = (value_history_count - 1) / VALUE_HISTORY_CHUNK - absnum / VALUE_HISTORY_CHUNK;
+ i > 0; i--)
+ chunk = chunk->next;
+
+ return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]);
+}
+
+/* Clear the value history entirely.
+ Must be done when new symbol tables are loaded,
+ because the type pointers become invalid. */
+
+void
+clear_value_history ()
+{
+ register struct value_history_chunk *next;
+ register int i;
+ register value val;
+
+ while (value_history_chain)
+ {
+ for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
+ if (val = value_history_chain->values[i])
+ free (val);
+ next = value_history_chain->next;
+ free (value_history_chain);
+ value_history_chain = next;
+ }
+ value_history_count = 0;
+}
+
+static void
+value_history_info (num_exp, from_tty)
+ char *num_exp;
+ int from_tty;
+{
+ register int i;
+ register value val;
+ static int num = 1;
+
+ if (num_exp)
+ {
+ if (num_exp[0] == '+' && num_exp[1] == '\0')
+ /* "info history +" should print from the stored position. */
+ ;
+ else
+ /* "info history <exp>" should print around value number <exp>. */
+ num = parse_and_eval_address (num_exp) - 5;
+ }
+ else
+ {
+ /* "info history" means print the last 10 values. */
+ num = value_history_count - 9;
+ }
+
+ if (num <= 0)
+ num = 1;
+
+ for (i = num; i < num + 10 && i <= value_history_count; i++)
+ {
+ val = access_value_history (i);
+ printf_filtered ("$%d = ", i);
+ value_print (val, stdout, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+
+ /* The next "info history +" should start after what we just printed. */
+ num += 10;
+
+ /* Hitting just return after this command should do the same thing as
+ "info history +". If num_exp is null, this is unnecessary, since
+ "info history +" is not useful after "info history". */
+ if (from_tty && num_exp)
+ {
+ num_exp[0] = '+';
+ num_exp[1] = '\0';
+ }
+}
+
+/* Internal variables. These are variables within the debugger
+ that hold values assigned by debugger commands.
+ The user refers to them with a '$' prefix
+ that does not appear in the variable names stored internally. */
+
+static struct internalvar *internalvars;
+
+/* Look up an internal variable with name NAME. NAME should not
+ normally include a dollar sign.
+
+ If the specified internal variable does not exist,
+ one is created, with a void value. */
+
+struct internalvar *
+lookup_internalvar (name)
+ char *name;
+{
+ register struct internalvar *var;
+
+ for (var = internalvars; var; var = var->next)
+ if (!strcmp (var->name, name))
+ return var;
+
+ var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
+ var->name = concat (name, "", "");
+ var->value = allocate_value (builtin_type_void);
+ release_value (var->value);
+ var->next = internalvars;
+ internalvars = var;
+ return var;
+}
+
+value
+value_of_internalvar (var)
+ struct internalvar *var;
+{
+ register value val;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ return VALUE_OF_TRAPPED_INTERNALVAR (var);
+#endif
+
+ val = value_copy (var->value);
+ VALUE_LVAL (val) = lval_internalvar;
+ VALUE_INTERNALVAR (val) = var;
+ return val;
+}
+
+void
+set_internalvar_component (var, offset, bitpos, bitsize, newval)
+ struct internalvar *var;
+ int offset, bitpos, bitsize;
+ value newval;
+{
+ register char *addr = VALUE_CONTENTS (var->value) + offset;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ SET_TRAPPED_INTERNALVAR (var, newval, bitpos, bitsize, offset);
+#endif
+
+ if (bitsize)
+ modify_field (addr, (int) value_as_long (newval),
+ bitpos, bitsize);
+ else
+ bcopy (VALUE_CONTENTS (newval), addr,
+ TYPE_LENGTH (VALUE_TYPE (newval)));
+}
+
+void
+set_internalvar (var, val)
+ struct internalvar *var;
+ value val;
+{
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0);
+#endif
+
+ free (var->value);
+ var->value = value_copy (val);
+ release_value (var->value);
+}
+
+char *
+internalvar_name (var)
+ struct internalvar *var;
+{
+ return var->name;
+}
+
+/* Free all internalvars. Done when new symtabs are loaded,
+ because that makes the values invalid. */
+
+void
+clear_internalvars ()
+{
+ register struct internalvar *var;
+
+ while (internalvars)
+ {
+ var = internalvars;
+ internalvars = var->next;
+ free (var->name);
+ free (var->value);
+ free (var);
+ }
+}
+
+static void
+convenience_info ()
+{
+ register struct internalvar *var;
+ int varseen = 0;
+
+ for (var = internalvars; var; var = var->next)
+ {
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ continue;
+#endif
+ if (!varseen)
+ {
+ printf ("Debugger convenience variables:\n\n");
+ varseen = 1;
+ }
+ printf ("$%s: ", var->name);
+ value_print (var->value, stdout, 0, Val_pretty_default);
+ printf ("\n");
+ }
+ if (!varseen)
+ printf ("No debugger convenience variables now defined.\n\
+Convenience variables have names starting with \"$\";\n\
+use \"set\" as in \"set $foo = 5\" to define them.\n");
+}
+
+/* Extract a value as a C number (either long or double).
+ Knows how to convert fixed values to double, or
+ floating values to long.
+ Does not deallocate the value. */
+
+LONGEST
+value_as_long (val)
+ register value val;
+{
+ return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
+}
+
+double
+value_as_double (val)
+ register value val;
+{
+ double foo;
+ int inv;
+
+ foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv);
+ if (inv)
+ error ("Invalid floating value found in program.");
+ return foo;
+}
+
+/* Unpack raw data (copied from debugee) at VALADDR
+ as a long, or as a double, assuming the raw data is described
+ by type TYPE. Knows how to convert different sizes of values
+ and can convert between fixed and floating point.
+
+ C++: It is assumed that the front-end has taken care of
+ all matters concerning pointers to members. A pointer
+ to member which reaches here is considered to be equivalent
+ to an INT (or some size). After all, it is only an offset. */
+
+LONGEST
+unpack_long (type, valaddr)
+ struct type *type;
+ char *valaddr;
+{
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+ register int nosign = TYPE_UNSIGNED (type);
+
+ if (code == TYPE_CODE_ENUM)
+ code = TYPE_CODE_INT;
+ if (code == TYPE_CODE_FLT)
+ {
+ if (len == sizeof (float))
+ return * (float *) valaddr;
+
+ if (len == sizeof (double))
+ return * (double *) valaddr;
+ }
+ else if (code == TYPE_CODE_INT && nosign)
+ {
+ if (len == sizeof (char))
+ return * (unsigned char *) valaddr;
+
+ if (len == sizeof (short))
+ return * (unsigned short *) valaddr;
+
+ if (len == sizeof (int))
+ return * (unsigned int *) valaddr;
+
+ if (len == sizeof (long))
+ return * (unsigned long *) valaddr;
+#ifdef LONG_LONG
+ if (len == sizeof (long long))
+ return * (unsigned long long *) valaddr;
+#endif
+ }
+ else if (code == TYPE_CODE_INT)
+ {
+ if (len == sizeof (char))
+ return * (char *) valaddr;
+
+ if (len == sizeof (short))
+ return * (short *) valaddr;
+
+ if (len == sizeof (int))
+ return * (int *) valaddr;
+
+ if (len == sizeof (long))
+ return * (long *) valaddr;
+
+#ifdef LONG_LONG
+ if (len == sizeof (long long))
+ return * (long long *) valaddr;
+#endif
+ }
+ else if (code == TYPE_CODE_PTR
+ || code == TYPE_CODE_REF)
+ {
+ if (len == sizeof (char *))
+ return (CORE_ADDR) * (char **) valaddr;
+ }
+ else if (code == TYPE_CODE_MEMBER)
+ error ("not implemented: member types in unpack_long");
+
+ error ("Value not integer or pointer.");
+}
+
+/* Return a double value from the specified type and address.
+ INVP points to an int which is set to 0 for valid value,
+ 1 for invalid value (bad float format). In either case,
+ the returned double is OK to use. */
+
+double
+unpack_double (type, valaddr, invp)
+ struct type *type;
+ char *valaddr;
+ int *invp;
+{
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+ register int nosign = TYPE_UNSIGNED (type);
+
+ *invp = 0; /* Assume valid. */
+ if (code == TYPE_CODE_FLT)
+ {
+ if (INVALID_FLOAT (valaddr, len))
+ {
+ *invp = 1;
+ return 1.234567891011121314;
+ }
+
+ if (len == sizeof (float))
+ return * (float *) valaddr;
+
+ if (len == sizeof (double))
+ {
+ /* Some machines require doubleword alignment for doubles.
+ This code works on them, and on other machines. */
+ double temp;
+ bcopy ((char *) valaddr, (char *) &temp, sizeof (double));
+ return temp;
+ }
+ }
+ else if (code == TYPE_CODE_INT && nosign)
+ {
+ if (len == sizeof (char))
+ return * (unsigned char *) valaddr;
+
+ if (len == sizeof (short))
+ return * (unsigned short *) valaddr;
+
+ if (len == sizeof (int))
+ return * (unsigned int *) valaddr;
+
+ if (len == sizeof (long))
+ return * (unsigned long *) valaddr;
+
+#ifdef LONG_LONG
+ if (len == sizeof (long long))
+ return * (unsigned long long *) valaddr;
+#endif
+ }
+ else if (code == TYPE_CODE_INT)
+ {
+ if (len == sizeof (char))
+ return * (char *) valaddr;
+
+ if (len == sizeof (short))
+ return * (short *) valaddr;
+
+ if (len == sizeof (int))
+ return * (int *) valaddr;
+
+ if (len == sizeof (long))
+ return * (long *) valaddr;
+
+#ifdef LONG_LONG
+ if (len == sizeof (long long))
+ return * (long long *) valaddr;
+#endif
+ }
+
+ error ("Value not floating number.");
+ /* NOTREACHED */
+ return (double) 0; /* To silence compiler warning. */
+}
+
+/* Given a value ARG1 of a struct or union type,
+ extract and return the value of one of its fields.
+ FIELDNO says which field.
+
+ For C++, must also be able to return values from static fields */
+
+value
+value_field (arg1, fieldno)
+ register value arg1;
+ register int fieldno;
+{
+ register value v;
+ register struct type *type = TYPE_FIELD_TYPE (VALUE_TYPE (arg1), fieldno);
+ register int offset;
+
+ /* Handle packed fields */
+
+ offset = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) / 8;
+ if (TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno))
+ {
+ v = value_from_long (type,
+ unpack_field_as_long (VALUE_TYPE (arg1),
+ VALUE_CONTENTS (arg1),
+ fieldno));
+ VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) % 8;
+ VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno);
+ }
+ else
+ {
+ v = allocate_value (type);
+ bcopy (VALUE_CONTENTS (arg1) + offset,
+ VALUE_CONTENTS (v),
+ TYPE_LENGTH (type));
+ }
+ VALUE_LVAL (v) = VALUE_LVAL (arg1);
+ if (VALUE_LVAL (arg1) == lval_internalvar)
+ VALUE_LVAL (v) = lval_internalvar_component;
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
+ VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1);
+ return v;
+}
+
+value
+value_fn_field (arg1, fieldno, subfieldno)
+ register value arg1;
+ register int fieldno;
+{
+ register value v;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno);
+ register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno);
+ struct symbol *sym;
+
+ sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno),
+ 0, VAR_NAMESPACE, 0);
+ if (! sym) error ("Internal error: could not find physical method named %s",
+ TYPE_FN_FIELD_PHYSNAME (f, subfieldno));
+
+ v = allocate_value (type);
+ VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ VALUE_TYPE (v) = type;
+ return v;
+}
+
+/* Return a virtual function as a value.
+ ARG1 is the object which provides the virtual function
+ table pointer.
+ F is the list of member functions which contains the desired virtual
+ function.
+ J is an index into F which provides the desired virtual function.
+ TYPE is the basetype which first provides the virtual function table. */
+value
+value_virtual_fn_field (arg1, f, j, type)
+ value arg1;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+{
+ /* First, get the virtual function table pointer. That comes
+ with a strange type, so cast it to type `pointer to long' (which
+ should serve just fine as a function type). Then, index into
+ the table, and convert final value to appropriate function type. */
+ value vfn, vtbl;
+ value vi = value_from_long (builtin_type_int,
+ (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ VALUE_TYPE (arg1) = TYPE_VPTR_BASETYPE (type);
+
+ /* This type may have been defined before its virtual function table
+ was. If so, fill in the virtual function table entry for the
+ type now. */
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ TYPE_VPTR_FIELDNO (type)
+ = fill_in_vptr_fieldno (type);
+
+ /* The virtual function table is now an array of structures
+ which have the form { int16 offset, delta; void *pfn; }. */
+ vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (type)));
+
+ /* Index into the virtual function table. This is hard-coded because
+ looking up a field is not cheap, and it may be important to save
+ time, e.g. if the user has set a conditional breakpoint calling
+ a virtual function. */
+ vfn = value_field (value_subscript (vtbl, vi), 2);
+
+ /* Reinstantiate the function pointer with the correct type. */
+ VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+ return vfn;
+}
+
+/* The value of a static class member does not depend
+ on its instance, only on its type. If FIELDNO >= 0,
+ then fieldno is a valid field number and is used directly.
+ Otherwise, FIELDNAME is the name of the field we are
+ searching for. If it is not a static field name, an
+ error is signaled. TYPE is the type in which we look for the
+ static field member. */
+value
+value_static_field (type, fieldname, fieldno)
+ register struct type *type;
+ char *fieldname;
+ register int fieldno;
+{
+ register value v;
+ struct symbol *sym;
+
+ if (fieldno < 0)
+ {
+ register struct type *t = type;
+ /* Look for static field. */
+ while (t)
+ {
+ int i;
+ for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
+ if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
+ {
+ if (TYPE_FIELD_STATIC (t, i))
+ {
+ fieldno = i;
+ goto found;
+ }
+ else
+ error ("field `%s' is not static");
+ }
+ t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0;
+ }
+
+ t = type;
+
+ if (destructor_name_p (fieldname, t))
+ error ("use `info method' command to print out value of destructor");
+
+ while (t)
+ {
+ int i, j;
+
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
+ {
+ if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname))
+ {
+ error ("use `info method' command to print value of method \"%s\"", fieldname);
+ }
+ }
+ t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0;
+ }
+ error("there is no field named %s", fieldname);
+ }
+
+ found:
+
+ sym = lookup_symbol (TYPE_FIELD_STATIC_PHYSNAME (type, fieldno),
+ 0, VAR_NAMESPACE, 0);
+ if (! sym) error ("Internal error: could not find physical static variable named %s", TYPE_FIELD_BITSIZE (type, fieldno));
+
+ type = TYPE_FIELD_TYPE (type, fieldno);
+ v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+ return v;
+}
+
+long
+unpack_field_as_long (type, valaddr, fieldno)
+ struct type *type;
+ char *valaddr;
+ int fieldno;
+{
+ long val;
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+
+ bcopy (valaddr + bitpos / 8, &val, sizeof val);
+
+ /* Extracting bits depends on endianness of the machine. */
+#ifdef BITS_BIG_ENDIAN
+ val = val >> (sizeof val * 8 - bitpos % 8 - bitsize);
+#else
+ val = val >> (bitpos % 8);
+#endif
+
+ val &= (1 << bitsize) - 1;
+ return val;
+}
+
+void
+modify_field (addr, fieldval, bitpos, bitsize)
+ char *addr;
+ int fieldval;
+ int bitpos, bitsize;
+{
+ long oword;
+
+ /* Reject values too big to fit in the field in question.
+ Otherwise adjoining fields may be corrupted. */
+ if (fieldval & ~((1<<bitsize)-1))
+ error ("Value %d does not fit in %d bits.", fieldval, bitsize);
+
+ bcopy (addr, &oword, sizeof oword);
+
+ /* Shifting for bit field depends on endianness of the machine. */
+#ifdef BITS_BIG_ENDIAN
+ bitpos = sizeof (oword) * 8 - bitpos - bitsize;
+#endif
+
+ oword &= ~(((1 << bitsize) - 1) << bitpos);
+ oword |= fieldval << bitpos;
+ bcopy (&oword, addr, sizeof oword);
+}
+
+/* Convert C numbers into newly allocated values */
+
+value
+value_from_long (type, num)
+ struct type *type;
+ register LONGEST num;
+{
+ register value val = allocate_value (type);
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+
+ if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM)
+ {
+ if (len == sizeof (char))
+ * (char *) VALUE_CONTENTS (val) = num;
+ else if (len == sizeof (short))
+ * (short *) VALUE_CONTENTS (val) = num;
+ else if (len == sizeof (int))
+ * (int *) VALUE_CONTENTS (val) = num;
+ else if (len == sizeof (long))
+ * (long *) VALUE_CONTENTS (val) = num;
+#ifdef LONG_LONG
+ else if (len == sizeof (long long))
+ * (long long *) VALUE_CONTENTS (val) = num;
+#endif
+ else
+ error ("Integer type encountered with unexpected data length.");
+ }
+ else
+ error ("Unexpected type encountered for integer constant.");
+
+ return val;
+}
+
+value
+value_from_double (type, num)
+ struct type *type;
+ double num;
+{
+ register value val = allocate_value (type);
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+
+ if (code == TYPE_CODE_FLT)
+ {
+ if (len == sizeof (float))
+ * (float *) VALUE_CONTENTS (val) = num;
+ else if (len == sizeof (double))
+ * (double *) VALUE_CONTENTS (val) = num;
+ else
+ error ("Floating type encountered with unexpected data length.");
+ }
+ else
+ error ("Unexpected type encountered for floating constant.");
+
+ return val;
+}
+
+/* Deal with the value that is "about to be returned". */
+
+/* Return the value that a function returning now
+ would be returning to its caller, assuming its type is VALTYPE.
+ RETBUF is where we look for what ought to be the contents
+ of the registers (in raw form). This is because it is often
+ desirable to restore old values to those registers
+ after saving the contents of interest, and then call
+ this function using the saved values.
+ struct_return is non-zero when the function in question is
+ using the structure return conventions on the machine in question;
+ 0 when it is using the value returning conventions (this often
+ means returning pointer to where structure is vs. returning value). */
+
+value
+value_being_returned (valtype, retbuf, struct_return)
+ register struct type *valtype;
+ char retbuf[REGISTER_BYTES];
+ int struct_return;
+{
+ register value val;
+
+ if (struct_return)
+ return value_at (valtype, EXTRACT_STRUCT_VALUE_ADDRESS (retbuf));
+
+ val = allocate_value (valtype);
+ EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS (val));
+
+ return val;
+}
+
+/* Return true if the function specified is using the structure returning
+ convention on this machine to return arguments, or 0 if it is using
+ the value returning convention. FUNCTION is the value representing
+ the function, FUNCADDR is the address of the function, and VALUE_TYPE
+ is the type returned by the function */
+
+struct block *block_for_pc ();
+
+int
+using_struct_return (function, funcaddr, value_type)
+ value function;
+ CORE_ADDR funcaddr;
+ struct type *value_type;
+{
+ register enum type_code code = TYPE_CODE (value_type);
+
+ if (code == TYPE_CODE_STRUCT ||
+ code == TYPE_CODE_UNION ||
+ code == TYPE_CODE_ARRAY)
+ {
+ struct block *b = block_for_pc (funcaddr);
+
+ if (!(BLOCK_GCC_COMPILED (b) && TYPE_LENGTH (value_type) < 8))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Store VAL so it will be returned if a function returns now.
+ Does not verify that VAL's type matches what the current
+ function wants to return. */
+
+void
+set_return_value (val)
+ value val;
+{
+ register enum type_code code = TYPE_CODE (VALUE_TYPE (val));
+ char regbuf[REGISTER_BYTES];
+ double dbuf;
+ LONGEST lbuf;
+
+ if (code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION)
+ error ("Specifying a struct or union return value is not supported.");
+
+ if (code == TYPE_CODE_FLT)
+ {
+ dbuf = value_as_double (val);
+
+ STORE_RETURN_VALUE (VALUE_TYPE (val), &dbuf);
+ }
+ else
+ {
+ lbuf = value_as_long (val);
+ STORE_RETURN_VALUE (VALUE_TYPE (val), &lbuf);
+ }
+}
+
+void
+_initialize_values ()
+{
+ add_info ("convenience", convenience_info,
+ "Debugger convenience (\"$foo\") variables.\n\
+These variables are created when you assign them values;\n\
+thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\
+A few convenience variables are given values automatically GDB:\n\
+\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\
+\"$__\" holds the contents of the last address examined with \"x\".");
+
+ add_info ("values", value_history_info,
+ "Elements of value history (around item number IDX, or last ten).");
+ add_info_alias ("history", value_history_info, 0);
+}
diff --git a/gnu/usr.bin/kgdb/version.c b/gnu/usr.bin/kgdb/version.c
new file mode 100644
index 000000000000..2f3dd8504301
--- /dev/null
+++ b/gnu/usr.bin/kgdb/version.c
@@ -0,0 +1,20 @@
+/* Define the current version number of GDB.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+char *version = "3.5";
diff --git a/gnu/usr.bin/kgdb/wait.h b/gnu/usr.bin/kgdb/wait.h
new file mode 100644
index 000000000000..c431cb6a47a9
--- /dev/null
+++ b/gnu/usr.bin/kgdb/wait.h
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)wait.h 6.3 (Berkeley) 5/8/91
+ */
+
+/* Define how to access the structure that the wait system call stores.
+ On many systems, there is a structure defined for this.
+ But on vanilla-ish USG systems there is not. */
+
+#ifndef HAVE_WAIT_STRUCT
+
+#define WAITTYPE int
+#define WIFSTOPPED(w) (((w)&0377) == 0177)
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#define WIFEXITED(w) (((w)&0377) == 0)
+#define WEXITSTATUS(w) ((w) >> 8)
+#define WSTOPSIG(w) ((w) >> 8)
+#define WCOREDUMP(w) (((w)&0200) != 0)
+#define WTERMSIG(w) ((w) & 0177)
+#define WSETEXIT(w, status) ((w) = (status))
+#define WSETSTOP(w,sig) ((w) = (0177 | ((sig) << 8)))
+
+#else
+
+#include <sys/wait.h>
+
+#define WAITTYPE union wait
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (w).w_retcode
+#endif
+#ifndef WSTOPSIG
+#define WSTOPSIG(w) (w).w_stopsig
+#endif
+#ifndef WCOREDUMP
+#define WCOREDUMP(w) (w).w_coredump
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w) (w).w_termsig
+#endif
+#ifndef WSETEXIT
+#define WSETEXIT(w, status) ((w).w_status = (status))
+#endif
+#ifndef WSETSTOP
+#define WSETSTOP(w,sig) \
+ ((w).w_stopsig = (sig), (w).w_coredump = 0, (w).w_termsig = 0177)
+#endif
+
+#endif
diff --git a/gnu/usr.bin/kgdb/xgdb/Makefile b/gnu/usr.bin/kgdb/xgdb/Makefile
new file mode 100644
index 000000000000..b8a042ec8dc8
--- /dev/null
+++ b/gnu/usr.bin/kgdb/xgdb/Makefile
@@ -0,0 +1,40 @@
+# %W% (Berkeley) %G%
+
+.include "../config/Makefile.$(MACHINE)"
+
+PROG= xgdb
+SRCS= xgdb.c xgdbinit.c
+GDBOBJS+= $(CONFIGSRCS:R:S/$/.o/g) \
+ blockframe.o breakpoint.o command.o copying.o core.o \
+ cplus-dem.o dbxread.o environ.o eval.o expprint.o \
+ expread.o findvar.o infcmd.o inflow.o infrun.o \
+ main.o obstack.o printcmd.o regex.o remote.o \
+ remote-sl.o source.o stack.o symmisc.o symtab.o \
+ utils.o valarith.o valops.o valprint.o values.o \
+ version.o \
+ funmap.o history.o keymaps.o readline.o
+CFLAGS+= -I.. -I$(.CURDIR)/.. -I$(.CURDIR)/../config \
+ -DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG
+# XXX objects should be in OBJS so that bsd.prog.mk handles their dependencies
+DPADD+= $(GDBOBJS:S/^/..\//g)
+# XXX cloned X lib stuff from xditview/Makefile. Should include it
+LDDESTDIR= /usr/X386/lib
+DPADD+= ${LDDESTDIR}/libXaw.a ${LDDESTDIR}/libXmu.a \
+ ${LDDESTDIR}/libXt.a ${LDDESTDIR}/libXext.a \
+ ${LDDESTDIR}/libX11.a
+DPADD+= ${LINTERM}
+LDADD+= $(GDBOBJS:S/^/..\//g) -lXaw -lXmu -lXt -lXext -lX11 -ltermcap
+NOMAN= noman
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
+
+#
+# Generate the constructor
+#
+xgdbinit.c: ../init.c xgdb.c
+ -(sed -e '/^}$$/d' ../init.c; \
+ egrep -h '^_initialize_[^ ]* *\(\)' $(.CURDIR)/xgdb.c; \
+ echo ';}') > xgdbinit.c
+
+CLEANFILES+= xgdbinit.c
diff --git a/gnu/usr.bin/kgdb/xgdb/xgdb.c b/gnu/usr.bin/kgdb/xgdb/xgdb.c
new file mode 100644
index 000000000000..0d9bdabad8cb
--- /dev/null
+++ b/gnu/usr.bin/kgdb/xgdb/xgdb.c
@@ -0,0 +1,700 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
+ *
+ * static char rcsid[] = "/home/ncvs/src/gnu/usr.bin/kgdb/xgdb/xgdb.c,v 1.1 1993/06/29 09:48:26 nate Exp";
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)xgdb.c 6.3 (Berkeley) 5/8/91";
+#endif /* not lint */
+
+/*
+ * Interface from GDB to X windows. Copyright (C) 1987 Free Software
+ * Foundation, Inc.
+ *
+ * GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY. No author or distributor accepts responsibility to anyone for
+ * the consequences of using it or for whether it serves any particular
+ * purpose or works at all, unless he says so in writing. Refer to the GDB
+ * General Public License for full details.
+ *
+ * Everyone is granted permission to copy, modify and redistribute GDB, but only
+ * under the conditions described in the GDB General Public License. A copy
+ * of this license is supposed to have been given to you along with GDB so
+ * you can know your rights and responsibilities. It should be in a file
+ * named COPYING. Among other things, the copyright notice and this notice
+ * must be preserved on all copies.
+ *
+ * In other words, go ahead and share GDB, but don't try to stop anyone else
+ * from sharing it farther. Help stamp out software hoarding!
+ */
+
+/*
+ * Original version was contributed by Derek Beatty, 30 June 87.
+ * This version is essentially a re-write of the original by Van
+ * Jacobson (van@helios.ee.lbl.gov), Nov, 90.
+ */
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+extern int stop_breakpoint;
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/AsciiSink.h>
+#include <X11/Xaw/AsciiText.h>
+#include <X11/Xaw/Box.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Paned.h>
+#include <X11/Xaw/Text.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/file.h>
+#include <sys/errno.h>
+
+extern int errno;
+extern char *getenv();
+extern char *malloc();
+extern void bcopy();
+extern int select();
+
+extern int get_filename_and_charpos();
+extern int source_line_charpos();
+extern int source_charpos_line();
+extern void execute_command();
+extern void error_no_arg();
+extern void add_com();
+
+/* The X display where the window appears. */
+
+static char *displayname;
+static Display *display;
+
+static XtAppContext app_context;
+
+/* Windows manipulated by this package. */
+
+static Widget main_widget;
+static Widget containing_widget;
+static Widget source_name_widget;
+static Widget source_text_widget;
+static Widget button_box_widget;
+
+/* Source text display. */
+
+static struct frame_info *last_fi;
+static CORE_ADDR last_pc;
+static struct symtab *last_cur_symtab;
+static int last_cur_line;
+
+static int source_window_line;
+static char *source_window_file;
+static struct symtab *source_window_symtab;
+
+static char version_label[64];
+extern char *version;
+
+/* Forward declarations */
+
+static Widget create_text_widget();
+
+static int
+safe_strcmp(a, b)
+ register char *a, *b;
+{
+ register int i;
+
+ if (a == b)
+ return (0);
+ if (!a && b)
+ return (1);
+ if (a && !b)
+ return (-1);
+ return (strcmp(a, b));
+}
+
+
+/* Display an appropriate piece of source code in the source window. */
+
+void
+xgdb_display_source()
+{
+ char *filename = NULL;
+ struct symtab_and_line get_selected_frame_sal();
+ struct symtab_and_line sal;
+ struct frame_info *fi;
+
+ /* Do nothing if called before we are initialized */
+
+ if (!containing_widget)
+ return;
+
+ /*
+ * Figure out what to display (the appropriate hooks to tell
+ * us don't exist so we guess): If there's a current frame
+ * and it or its pc changed from the last time we were here,
+ * display appropriate source line. Otherwise if the current
+ * source symtab or line is different, display that line.
+ * Otherwise nothing changed so leave the display alone.
+ */
+ fi = get_frame_info(selected_frame);
+ if (fi && (fi != last_fi || fi->pc != last_pc)) {
+ last_fi = fi;
+ last_pc = fi->pc;
+ sal = find_pc_line(fi->pc, fi->next_frame);
+ if (sal.symtab == NULL) { /* XXX */
+ sal.symtab = current_source_symtab;
+ sal.line = current_source_line;
+ }
+ current_source_symtab = sal.symtab;
+ current_source_line = sal.line;
+ } else if (current_source_symtab != last_cur_symtab ||
+ current_source_line != last_cur_line) {
+ sal.symtab = last_cur_symtab = current_source_symtab;
+ sal.line = last_cur_line = current_source_line;
+ } else
+ return;
+ /*
+ * Do a path search and get the exact filename of this source file.
+ * Also scan it and find its source lines if not already done.
+ */
+ if (sal.symtab && filename == NULL) {
+ if (get_filename_and_charpos(sal.symtab, sal.line, &filename))
+ /* line numbers may have changed - force highlight */
+ source_window_line = -1;
+ }
+
+ /*
+ * If the source window is wrong, destroy it and make a new one.
+ */
+ if (safe_strcmp(filename, source_window_file)) {
+ Arg args[1];
+ Widget src = XawTextGetSource(source_text_widget);
+
+ if (filename) {
+ XtSetArg(args[0], XtNstring, filename);
+ XtSetValues(src, args, XtNumber(args));
+ args[0].name = XtNlabel;
+ XtSetValues(source_name_widget, args, XtNumber(args));
+ } else {
+ XtSetArg(args[0], XtNstring, "/dev/null");
+ XtSetValues(src, args, XtNumber(args));
+ XtSetArg(args[0], XtNlabel, "");
+ XtSetValues(source_name_widget, args, XtNumber(args));
+ }
+ if (source_window_file)
+ free(source_window_file);
+ source_window_file = filename;
+ source_window_line = sal.line + 1; /* force highlight */
+ }
+ if (sal.symtab && source_window_line != sal.line) {
+ /*
+ * Update display and cursor positions as necessary.
+ * Cursor should be placed on line sal.line.
+ */
+ XawTextPosition l, r;
+
+ source_window_symtab = sal.symtab;
+ source_window_line = sal.line;
+ l = source_line_charpos(source_window_symtab, sal.line);
+ r = source_line_charpos(source_window_symtab, sal.line + 1);
+ if (r < l)
+ r = l + 1;
+ XawTextSetSelection(source_text_widget, l, r);
+ XawTextScrollToLine(source_text_widget, l, 10, 3);
+ XawTextSetInsertionPoint(source_text_widget, l);
+ }
+}
+
+
+/*
+ * Handlers for buttons.
+ */
+
+static int
+current_lineno()
+{
+ XawTextPosition start, finish;
+
+ XawTextGetSelectionPos(source_text_widget, &start, &finish);
+ if (start >= finish)
+ start = XawTextGetInsertionPoint(source_text_widget);
+
+ return (source_charpos_line(source_window_symtab, start));
+}
+
+static char *
+append_selection(cp)
+ char *cp;
+{
+ int len;
+ XawTextPosition l, r;
+
+ XawTextGetSelectionPos(source_text_widget, &l, &r);
+ if ((len = r - l) > 0) {
+ Widget src = XawTextGetSource(source_text_widget);
+
+ while (len > 0) {
+ XawTextBlock tb;
+
+ XawTextSourceRead(src, l, &tb, len);
+ bcopy(tb.ptr, cp, tb.length);
+ cp += tb.length;
+ len -= tb.length;
+ }
+ if (cp[-1] == 0)
+ --cp;
+ }
+ return (cp);
+}
+
+static char *
+append_selection_word(cp)
+ register char *cp;
+{
+ register int len;
+ XawTextPosition l, r;
+ XawTextBlock tb;
+ register char c;
+ register Widget src = XawTextGetSource(source_text_widget);
+
+ XawTextGetSelectionPos(source_text_widget, &l, &r);
+ if ((len = r - l) <= 0) {
+ l = XawTextGetInsertionPoint(source_text_widget);
+ len = 128; /* XXX */
+
+ /* might have clicked in middle of word -- back up to start */
+ for ( ; l > 0; --l) {
+ XawTextSourceRead(src, l - 1, &tb, 1);
+ c = tb.ptr[0];
+ if (! isalnum(c) && c != '_' && c != '$')
+ break;
+ }
+ }
+ while (len > 0) {
+ char *sp;
+ int i;
+
+ XawTextSourceRead(src, l, &tb, len);
+ for (sp = tb.ptr, i = tb.length; --i >= 0; ) {
+ c = *sp++;
+ if (!isalnum(c) && c != '_' && c != '$')
+ return (cp);
+ *cp++ = c;
+ }
+ len -= tb.length;
+ }
+ return (cp);
+}
+
+static char *
+append_selection_expr(cp)
+ char *cp;
+{
+ int len;
+ XawTextPosition l, r;
+ Widget src = XawTextGetSource(source_text_widget);
+ XawTextBlock tb;
+ char *sp;
+ char c;
+
+ XawTextGetSelectionPos(source_text_widget, &l, &r);
+ if (r > l)
+ return (append_selection(cp));
+
+ l = XawTextGetInsertionPoint(source_text_widget);
+
+ /* might have clicked in middle of word -- back up to start */
+ for ( ; l > 0; --l) {
+ XawTextSourceRead(src, l - 1, &tb, 1);
+ c = tb.ptr[0];
+ if (! isalnum(c) && c != '_' && c != '$')
+ break;
+ }
+
+ len = 128; /* XXX */
+ while (len > 0) {
+ int i;
+ char pstack[64];
+ int pcnt = 0;
+
+ XawTextSourceRead(src, l, &tb, len);
+ for (sp = tb.ptr, i = tb.length; --i >= 0; ) {
+ switch (c = *sp++) {
+ case '\n':
+ case ';':
+ return (cp);
+ case '=':
+ if (cp[-1] != '=')
+ return (cp - 1);
+ if (len == 128)
+ return (cp);
+ break;
+ case ',':
+ if (pcnt <= 0)
+ return (cp);
+ break;
+ case '(':
+ pstack[pcnt] = ')';
+ if (++pcnt >= sizeof(pstack))
+ return (cp);
+ break;
+ case '[':
+ pstack[pcnt] = ']';
+ if (++pcnt >= sizeof(pstack))
+ return (cp);
+ break;
+ case ')':
+ case ']':
+ if (--pcnt < 0 || pstack[pcnt] != c)
+ return (cp);
+ break;
+ }
+ *cp++ = c;
+ }
+ len -= tb.length;
+ }
+ return (cp);
+}
+
+static int input_avail; /* XXX kluge: do_command sets this when command
+ * data from button is avaialble to force top level
+ * to break out of its loop. */
+/*
+ * Handle a button by running the command COMMAND.
+ */
+static void
+do_command(w, command, call_data)
+ Widget w;
+ register char *command;
+ caddr_t call_data;
+{
+ char cmd_line[256];
+ char buf[256];
+ register char *out = cmd_line;
+ char *cp;
+ register char c;
+ extern char *finish_command_input();
+
+ while (c = *command++) {
+ if (c == '%') {
+ switch (*command++) {
+ case 's': /* current selection */
+ out = append_selection(out);
+ break;
+ case 'S': /* 1st selected "word" at curor */
+ out = append_selection_word(out);
+ break;
+ case 'e': /* echo cmd before executing */
+ break;
+ case 'E': /* 1st selected expression at curor */
+ out = append_selection_expr(out);
+ break;
+
+ case 'l': /* current line number */
+ (void) sprintf(buf, "%d", current_lineno());
+ for (cp = buf; c = *cp++; *out++ = c)
+ ;
+ break;
+ case 'L': /* line we're stopped at */
+ (void) sprintf(buf, "%d", source_window_line);
+ for (cp = buf; c = *cp++; *out++ = c)
+ ;
+ break;
+ case 'f': /* current file name */
+ for (cp = source_window_symtab->filename;
+ c = *cp++; *out++ = c)
+ ;
+ break;
+ case 'b': /* break # we're stopped at */
+ if (stop_breakpoint <= 0)
+ /* if no breakpoint, don't do cmd */
+ return;
+
+ (void) sprintf(buf, "%d", stop_breakpoint);
+ for (cp = buf; c = *cp++; *out++ = c)
+ ;
+ break;
+ }
+ } else
+ *out++ = c;
+ }
+ *out = 0;
+ reinitialize_more_filter();
+ /* have to exit via readline or tty modes stay messed up */
+ for (cp = cmd_line; c = *cp++; )
+ rl_stuff_char(c);
+ rl_stuff_char('\n');
+ input_avail = 1;
+}
+
+/*
+ * Define and display all the buttons.
+ */
+static void
+addbutton(parent, name, function, closure)
+ Widget parent;
+ char *name;
+ void (*function) ();
+ caddr_t closure;
+{
+ static XtCallbackRec Callback[] = {
+ {NULL, (caddr_t) NULL},
+ {NULL, (caddr_t) NULL},
+ };
+ static Arg commandArgs[] = {
+ {XtNlabel, (XtArgVal) NULL},
+ {XtNcallback, (XtArgVal) Callback},
+ };
+ Widget w;
+ char wname[128];
+ register char *cp;
+
+ strcpy(wname, name);
+ while ((cp = index(wname, '*')) || (cp = index(wname, '.')))
+ *cp -= 0x10;
+
+ if (w = XtNameToWidget(parent, wname))
+ XtDestroyWidget(w);
+
+ Callback[0].callback = (XtCallbackProc) function;
+ Callback[0].closure = (caddr_t) closure;
+ commandArgs[0].value = (XtArgVal) name;
+ XtCreateManagedWidget(wname, commandWidgetClass, parent,
+ commandArgs, XtNumber(commandArgs));
+}
+
+/*
+ * Create the button windows and store them in `buttons'.
+ */
+static void
+create_buttons(parent)
+ Widget parent;
+{
+ addbutton(parent, "quit", do_command, "quit");
+}
+
+static void
+button_command(arg)
+ char *arg;
+{
+ char *label;
+ unsigned int len;
+
+ if (! arg)
+ error_no_arg("button label and command");
+
+ for (len = strlen(arg); len > 0 && isspace(arg[len - 1]); --len)
+ ;
+ if (len == 0)
+ error_no_arg("button label and command");
+ arg[len] = 0;
+
+ /* make a copy of button label & command for toolkit to use */
+ label = malloc(len + 1);
+ strcpy(label, arg);
+
+ /* find the end of the label */
+ if (*label == '"') {
+ if ((arg = index(++label, '"')) == 0) {
+ printf("button label missing closing quote\n");
+ return;
+ }
+ *arg++ = 0;
+ } else if (arg = index(label, ' '))
+ *arg++ = 0;
+ else
+ arg = label;
+
+ while (*arg && isspace(*arg))
+ ++arg;
+
+ addbutton(button_box_widget, label, do_command, arg);
+}
+
+static void
+button_delete_command(arg)
+ char *arg;
+{
+ unsigned int len;
+ Widget w;
+ register char *cp;
+
+ if (! arg)
+ error_no_arg("button name");
+
+ for (len = strlen(arg); len > 0 && isspace(arg[len - 1]); --len)
+ ;
+ if (len == 0)
+ error_no_arg("button name");
+ arg[len] = 0;
+
+ /* find the end of the label */
+ if (*arg == '"') {
+ if ((cp = index(++arg, '"')) == 0) {
+ printf("button label missing closing quote\n");
+ return;
+ }
+ *cp++ = 0;
+ }
+ while ((cp = index(arg, '*')) || (cp = index(arg, '.')))
+ *cp -= 0x10;
+
+ if (w = XtNameToWidget(button_box_widget, arg))
+ XtDestroyWidget(w);
+}
+
+/*
+ * Create a "label window" that just displays the string LABEL.
+ */
+static Widget
+create_label(name, label)
+ char *name, *label;
+{
+ Arg args[1];
+ Widget w;
+
+ XtSetArg(args[0], XtNlabel, label);
+ w = XtCreateManagedWidget(name, labelWidgetClass, containing_widget,
+ args, XtNumber(args));
+ return (w);
+}
+
+/*
+ * Create a subwindow of PARENT that displays and scrolls the contents of
+ * file FILENAME.
+ */
+static Widget
+create_text_widget(parent, filename)
+ Widget parent;
+ char *filename;
+{
+ static Arg arg[] = {
+ {XtNstring, NULL},
+ {XtNtype, XawAsciiFile},
+ {XtNcursor, None},
+ };
+ Widget text_widget;
+
+ arg[0].value = (XtArgVal)filename;
+ text_widget = XtCreateManagedWidget("src", asciiTextWidgetClass,
+ parent, arg, XtNumber(arg));
+ return (text_widget);
+}
+
+/*
+ * Entry point to create the widgets representing our display.
+ */
+void
+xgdb_create_window()
+{
+ /* initialize toolkit, setup defaults */
+#ifdef notyet
+ main_widget = XtAppInitialize(&app_context, "Xgdb", NULL, 0,
+ argcptr, argv, NULL, NULL, 0);
+#else
+ char *dummy_argv[] = { "xgdb", 0 };
+ int dummy_argc = 1;
+ main_widget = XtAppInitialize(&app_context, "Xgdb", NULL, 0,
+ &dummy_argc, dummy_argv, NULL, NULL, 0);
+#endif
+ display = XtDisplay(main_widget);
+ containing_widget = XtCreateManagedWidget("frame", panedWidgetClass,
+ main_widget, NULL, 0);
+
+ sprintf(version_label, "XGDB %s", version);
+ button_box_widget = XtCreateManagedWidget("buttons", boxWidgetClass,
+ containing_widget, NULL, 0);
+ create_buttons(button_box_widget);
+ source_name_widget = create_label("srcLabel", "No source file yet.");
+ source_text_widget = create_text_widget(containing_widget, "/dev/null");
+
+ XtRealizeWidget(main_widget);
+ XFlush(display);
+}
+
+/*
+ * If we use an X window, the readline input loop is told to call
+ * this function before reading a character from stdin.
+ */
+/*ARGSUSED*/
+static void
+xgdb_window_hook()
+{
+ register int inmask = 1 << fileno(stdin);
+ register int xmask = 1 << ConnectionNumber(display);
+ register int nfds, pend;
+ int input_rfds;
+ XEvent ev;
+
+ /*
+ * Display our current idea of the `interesting' source file then
+ * loop, dispatching window events until data is available on
+ * stdin. Then return so the input data can be processed.
+ */
+ input_avail = 0;
+ xgdb_display_source();
+
+ input_rfds = 0;
+ while (input_avail == 0 && (input_rfds & inmask) == 0) {
+ pend = XPending(display);
+ if (!pend) {
+ input_rfds = inmask | xmask;
+ nfds = select(32, &input_rfds, 0, 0,
+ (struct timeval *)0);
+ if (nfds == -1 && errno == EINTR)
+ continue;
+ }
+ if (pend || (input_rfds & xmask)) {
+ XNextEvent(display, &ev);
+ XtDispatchEvent(&ev);
+ }
+ }
+}
+
+void
+_initialize_xgdb()
+{
+ extern void (*window_hook) ();
+ extern int inhibit_windows;
+ extern struct cmd_list_element *deletelist;
+
+ if (inhibit_windows)
+ return;
+
+ if (! displayname) {
+ displayname = getenv("DISPLAY");
+ if (! displayname) {
+ fprintf(stderr, "xgdb: no display name\n");
+ inhibit_windows = 1;
+ return;
+ }
+ }
+ xgdb_create_window();
+ window_hook = xgdb_window_hook;
+ add_com("button", class_support, button_command,
+"Add command button to xgdb window. First argument is button\n\
+label, second is command associated with button. Command can\n\
+include printf-like escapes:\n\
+ %s for current selection,\n\
+ %S for first 'word' of current selection,\n\
+ %e for current selection or expression at insertion pt,\n\
+ %E for current selection or expression at insertion pt,\n\
+ %l for current line number,\n\
+ %L for line program stopped at,\n\
+ %f for current file name,\n\
+ %b for current breakpoint number.");
+ add_cmd("button", class_support, button_delete_command,
+"Delete a button from the xgdb window.\n\
+Argument is name of button to be deleted.",
+ &deletelist);
+}
diff --git a/gnu/usr.bin/ld/Makefile b/gnu/usr.bin/ld/Makefile
index 6b484e68fe75..b0b631bd3d01 100644
--- a/gnu/usr.bin/ld/Makefile
+++ b/gnu/usr.bin/ld/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.14 1994/02/14 10:02:13 rgrimes Exp $
+# Makefile,v 1.15 1994/08/19 12:24:45 davidg Exp
#
PROG= ld
diff --git a/gnu/usr.bin/ld/cplus-dem.c b/gnu/usr.bin/ld/cplus-dem.c
index 808db5e1cdfe..15fa17e73069 100644
--- a/gnu/usr.bin/ld/cplus-dem.c
+++ b/gnu/usr.bin/ld/cplus-dem.c
@@ -5,7 +5,7 @@
#ifndef lint
/*static char sccsid[] = "from: @(#)cplus-dem.c 5.4 (Berkeley) 4/30/91";*/
-static char rcsid[] = "$Id: cplus-dem.c,v 1.2 1993/08/01 18:46:58 mycroft Exp $";
+static char rcsid[] = "cplus-dem.c,v 1.3 1993/11/09 04:18:51 paul Exp";
#endif /* not lint */
/* Demangler for GNU C++
diff --git a/gnu/usr.bin/ld/etc.c b/gnu/usr.bin/ld/etc.c
index 59e0a18c6de4..0d4034abffe0 100644
--- a/gnu/usr.bin/ld/etc.c
+++ b/gnu/usr.bin/ld/etc.c
@@ -1,5 +1,5 @@
/*
- * $Id: etc.c,v 1.7 1994/02/13 20:41:05 jkh Exp $
+ * etc.c,v 1.8 1994/06/15 22:39:32 rich Exp
*/
#include <err.h>
diff --git a/gnu/usr.bin/ld/i386/md-static-funcs.c b/gnu/usr.bin/ld/i386/md-static-funcs.c
index 47416856e4e9..7f4e5fe77071 100644
--- a/gnu/usr.bin/ld/i386/md-static-funcs.c
+++ b/gnu/usr.bin/ld/i386/md-static-funcs.c
@@ -1,5 +1,5 @@
/*
- * $Id: md-static-funcs.c,v 1.2 1993/12/08 10:14:44 pk Exp $
+ * md-static-funcs.c,v 1.2 1994/02/13 20:42:06 jkh Exp
*
* Called by ld.so when onanating.
* This *must* be a static function, so it is not called through a jmpslot.
diff --git a/gnu/usr.bin/ld/i386/md.c b/gnu/usr.bin/ld/i386/md.c
index ce61355fe24a..c9c0354ff5cb 100644
--- a/gnu/usr.bin/ld/i386/md.c
+++ b/gnu/usr.bin/ld/i386/md.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: md.c,v 1.9 1994/02/13 20:42:09 jkh Exp $
+ * md.c,v 1.10 1994/06/15 22:40:44 rich Exp
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/i386/md.h b/gnu/usr.bin/ld/i386/md.h
index 1209aeeb036f..40cc59a440ef 100644
--- a/gnu/usr.bin/ld/i386/md.h
+++ b/gnu/usr.bin/ld/i386/md.h
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: md.h,v 1.9 1994/02/13 20:42:11 jkh Exp $
+ * md.h,v 1.10 1994/06/15 22:40:46 rich Exp
*/
diff --git a/gnu/usr.bin/ld/i386/mdprologue.S b/gnu/usr.bin/ld/i386/mdprologue.S
index 6a582be2b8f5..9fc192ebf7f9 100644
--- a/gnu/usr.bin/ld/i386/mdprologue.S
+++ b/gnu/usr.bin/ld/i386/mdprologue.S
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: mdprologue.S,v 1.3 1993/12/10 10:16:00 jkh Exp $
+ * mdprologue.S,v 1.4 1994/06/15 22:40:49 rich Exp
*/
/*
diff --git a/gnu/usr.bin/ld/ld.1 b/gnu/usr.bin/ld/ld.1
index efbe7ee2d427..20f040d1f3fe 100644
--- a/gnu/usr.bin/ld/ld.1
+++ b/gnu/usr.bin/ld/ld.1
@@ -27,7 +27,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $Id: ld.1,v 1.6 1994/03/09 14:28:02 davidg Exp $
+.\" ld.1,v 1.7 1994/06/15 22:39:35 rich Exp
.\"
.Dd October 14, 1993
.Dt LD 8
diff --git a/gnu/usr.bin/ld/ld.c b/gnu/usr.bin/ld/ld.c
index 3cb49d2b02bf..f137482be960 100644
--- a/gnu/usr.bin/ld/ld.c
+++ b/gnu/usr.bin/ld/ld.c
@@ -32,7 +32,7 @@ static char sccsid[] = "@(#)ld.c 6.10 (Berkeley) 5/22/91";
Set, indirect, and warning symbol features added by Randy Smith. */
/*
- * $Id: ld.c,v 1.21 1994/02/17 03:57:00 davidg Exp $
+ * ld.c,v 1.22 1994/06/15 22:39:40 rich Exp
*/
/* Define how to initialize system-dependent header fields. */
diff --git a/gnu/usr.bin/ld/ld.h b/gnu/usr.bin/ld/ld.h
index 3c1b1951a369..7e730c4e1dc8 100644
--- a/gnu/usr.bin/ld/ld.h
+++ b/gnu/usr.bin/ld/ld.h
@@ -1,5 +1,5 @@
/*
- * $Id: ld.h,v 1.10 1994/02/13 20:41:34 jkh Exp $
+ * ld.h,v 1.11 1994/06/15 22:39:46 rich Exp
*/
/*-
* This code is derived from software copyrighted by the Free Software
diff --git a/gnu/usr.bin/ld/ldconfig/Makefile b/gnu/usr.bin/ld/ldconfig/Makefile
index 28cbe5180ea4..b45aa331c53c 100644
--- a/gnu/usr.bin/ld/ldconfig/Makefile
+++ b/gnu/usr.bin/ld/ldconfig/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.6 1994/02/13 20:42:18 jkh Exp $
+# Makefile,v 1.7 1994/04/13 20:49:42 ats Exp
PROG= ldconfig
SRCS= ldconfig.c shlib.c etc.c
diff --git a/gnu/usr.bin/ld/ldconfig/ldconfig.c b/gnu/usr.bin/ld/ldconfig/ldconfig.c
index b31271f4cf19..ba492bcc0905 100644
--- a/gnu/usr.bin/ld/ldconfig/ldconfig.c
+++ b/gnu/usr.bin/ld/ldconfig/ldconfig.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: ldconfig.c,v 1.6 1994/06/05 19:04:11 ats Exp $
+ * ldconfig.c,v 1.7 1994/06/15 22:40:56 rich Exp
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/ldd/Makefile b/gnu/usr.bin/ld/ldd/Makefile
index 282a8fdb57f6..aa91a0553832 100644
--- a/gnu/usr.bin/ld/ldd/Makefile
+++ b/gnu/usr.bin/ld/ldd/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 1993/11/09 04:19:24 paul Exp $
+# Makefile,v 1.3 1993/12/16 21:51:27 nate Exp
PROG= ldd
SRCS= ldd.c
diff --git a/gnu/usr.bin/ld/ldd/ldd.c b/gnu/usr.bin/ld/ldd/ldd.c
index 1072d80d28de..e1e8589a2efa 100644
--- a/gnu/usr.bin/ld/ldd/ldd.c
+++ b/gnu/usr.bin/ld/ldd/ldd.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: ldd.c,v 1.3 1994/02/13 20:42:43 jkh Exp $
+ * ldd.c,v 1.4 1994/06/15 22:41:03 rich Exp
*/
#include <sys/types.h>
diff --git a/gnu/usr.bin/ld/lib.c b/gnu/usr.bin/ld/lib.c
index 7eaaa98608dd..5d26b6b79a02 100644
--- a/gnu/usr.bin/ld/lib.c
+++ b/gnu/usr.bin/ld/lib.c
@@ -1,5 +1,5 @@
/*
- * $Id: lib.c,v 1.9 1994/02/13 20:41:37 jkh Exp $ - library routines
+ * lib.c,v 1.10 1994/06/15 22:39:49 rich Exp - library routines
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/rrs.c b/gnu/usr.bin/ld/rrs.c
index a0627e7764e4..c6df2f22ccdf 100644
--- a/gnu/usr.bin/ld/rrs.c
+++ b/gnu/usr.bin/ld/rrs.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rrs.c,v 1.11 1994/02/13 20:41:40 jkh Exp $
+ * rrs.c,v 1.12 1994/06/15 22:39:52 rich Exp
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/rtld/Makefile b/gnu/usr.bin/ld/rtld/Makefile
index d8c91654e405..d23e019762db 100644
--- a/gnu/usr.bin/ld/rtld/Makefile
+++ b/gnu/usr.bin/ld/rtld/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.12 1994/08/28 18:48:32 bde Exp $
+# Makefile,v 1.13 1994/09/18 19:41:38 swallace Exp
PROG= ld.so
SRCS= mdprologue.S rtld.c malloc.c shlib.c etc.c md.c
diff --git a/gnu/usr.bin/ld/rtld/malloc.c b/gnu/usr.bin/ld/rtld/malloc.c
index b5c54f8d60ac..2d1d8dd31167 100644
--- a/gnu/usr.bin/ld/rtld/malloc.c
+++ b/gnu/usr.bin/ld/rtld/malloc.c
@@ -33,7 +33,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/
-static char *rcsid = "$Id: malloc.c,v 1.1 1994/02/13 20:44:09 jkh Exp $";
+static char *rcsid = "malloc.c,v 1.2 1994/06/15 22:41:13 rich Exp";
#endif /* LIBC_SCCS and not lint */
/*
diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c
index d1ab40829355..78b1d3779529 100644
--- a/gnu/usr.bin/ld/rtld/rtld.c
+++ b/gnu/usr.bin/ld/rtld/rtld.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rtld.c,v 1.17 1994/06/15 22:41:15 rich Exp $
+ * rtld.c,v 1.18 1994/09/15 20:48:55 bde Exp
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/rtld/sbrk.c b/gnu/usr.bin/ld/rtld/sbrk.c
index 2d2c610dedb9..7d02484fd4a4 100644
--- a/gnu/usr.bin/ld/rtld/sbrk.c
+++ b/gnu/usr.bin/ld/rtld/sbrk.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id$
+ * sbrk.c,v 1.1 1993/12/11 21:06:36 jkh Exp
*/
#include <machine/vmparam.h>
diff --git a/gnu/usr.bin/ld/shlib.c b/gnu/usr.bin/ld/shlib.c
index 2e8dfe99226e..4dd651066159 100644
--- a/gnu/usr.bin/ld/shlib.c
+++ b/gnu/usr.bin/ld/shlib.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: shlib.c,v 1.8 1994/02/13 20:41:43 jkh Exp $
+ * shlib.c,v 1.9 1994/06/15 22:39:54 rich Exp
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/sparc/md-static-funcs.c b/gnu/usr.bin/ld/sparc/md-static-funcs.c
index 2672cb596be6..3300f2b883d3 100644
--- a/gnu/usr.bin/ld/sparc/md-static-funcs.c
+++ b/gnu/usr.bin/ld/sparc/md-static-funcs.c
@@ -1,6 +1,6 @@
/*
- * $Id: md-static-funcs.c,v 1.2 1993/12/08 10:28:56 pk Exp $
+ * md-static-funcs.c,v 1.2 1993/12/11 12:02:08 jkh Exp
*
* Simple SPARC relocations for the benefit of self-relocation of ld.so
* avoiding the use of global variables (ie. reloc_bitshift[] et. al.).
diff --git a/gnu/usr.bin/ld/sparc/md.c b/gnu/usr.bin/ld/sparc/md.c
index 508d37de41f4..a1716e7a6c6d 100644
--- a/gnu/usr.bin/ld/sparc/md.c
+++ b/gnu/usr.bin/ld/sparc/md.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: md.c,v 1.7 1994/02/13 20:43:03 jkh Exp $
+ * md.c,v 1.8 1994/06/15 22:41:19 rich Exp
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/sparc/md.h b/gnu/usr.bin/ld/sparc/md.h
index 3545d97d92d8..f4f396ca68b0 100644
--- a/gnu/usr.bin/ld/sparc/md.h
+++ b/gnu/usr.bin/ld/sparc/md.h
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: md.h,v 1.5 1993/12/02 01:03:47 jkh Exp $
+ * md.h,v 1.6 1994/02/13 20:43:07 jkh Exp
*/
/*
diff --git a/gnu/usr.bin/ld/sparc/mdprologue.S b/gnu/usr.bin/ld/sparc/mdprologue.S
index 0d006d0c0dac..65b245da2b86 100644
--- a/gnu/usr.bin/ld/sparc/mdprologue.S
+++ b/gnu/usr.bin/ld/sparc/mdprologue.S
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: mdprologue.S,v 1.2 1993/11/09 04:19:36 paul Exp $
+ * mdprologue.S,v 1.3 1994/02/13 20:43:13 jkh Exp
*/
/*
diff --git a/gnu/usr.bin/ld/symbol.c b/gnu/usr.bin/ld/symbol.c
index f355b3e62bb5..50bbe8e55172 100644
--- a/gnu/usr.bin/ld/symbol.c
+++ b/gnu/usr.bin/ld/symbol.c
@@ -1,5 +1,5 @@
/*
- * $Id: symbol.c,v 1.4 1994/02/13 20:41:46 jkh Exp $ - symbol table routines
+ * symbol.c,v 1.5 1994/06/15 22:39:56 rich Exp - symbol table routines
*/
/* Create the symbol table entries for `etext', `edata' and `end'. */
diff --git a/gnu/usr.bin/ld/symseg.h b/gnu/usr.bin/ld/symseg.h
index 5e11b0b31961..91a4ec4a6b69 100644
--- a/gnu/usr.bin/ld/symseg.h
+++ b/gnu/usr.bin/ld/symseg.h
@@ -4,7 +4,7 @@
* Foundation.
*
* from: @(#)symseg.h 5.4 (Berkeley) 4/30/91
- * $Id: symseg.h,v 1.2 1993/08/01 18:46:59 mycroft Exp $
+ * symseg.h,v 1.3 1993/11/09 04:19:05 paul Exp
*/
/* GDB symbol table format definitions.
diff --git a/gnu/usr.bin/ld/warnings.c b/gnu/usr.bin/ld/warnings.c
index 6ae1be9557cb..1ec92add8451 100644
--- a/gnu/usr.bin/ld/warnings.c
+++ b/gnu/usr.bin/ld/warnings.c
@@ -1,5 +1,5 @@
/*
- * $Id: warnings.c,v 1.7 1994/06/14 12:45:41 csgr Exp $
+ * warnings.c,v 1.8 1994/06/15 22:40:00 rich Exp
*/
#include <sys/param.h>
diff --git a/gnu/usr.bin/ld/xbits.c b/gnu/usr.bin/ld/xbits.c
index 6374bebe23c5..4102b5810357 100644
--- a/gnu/usr.bin/ld/xbits.c
+++ b/gnu/usr.bin/ld/xbits.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: xbits.c,v 1.2 1993/11/09 04:19:08 paul Exp $
+ * xbits.c,v 1.3 1994/02/13 20:41:50 jkh Exp
*/
/*
diff --git a/gnu/usr.bin/man/apropos/Makefile b/gnu/usr.bin/man/apropos/Makefile
index bc6bdec90242..b47286adcb47 100644
--- a/gnu/usr.bin/man/apropos/Makefile
+++ b/gnu/usr.bin/man/apropos/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.7 1994/06/05 21:57:03 csgr Exp $
+# Makefile,v 1.8 1994/08/28 18:33:42 bde Exp
.if exists(${.CURDIR}/obj)
MAN1= ${.CURDIR}/obj/apropos.1
diff --git a/gnu/usr.bin/patch/EXTERN.h b/gnu/usr.bin/patch/EXTERN.h
index bdc1ef9195af..8f3e00aafed8 100644
--- a/gnu/usr.bin/patch/EXTERN.h
+++ b/gnu/usr.bin/patch/EXTERN.h
@@ -1,6 +1,9 @@
-/* $Header: EXTERN.h,v 2.0 86/09/17 15:35:37 lwall Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/EXTERN.h,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * EXTERN.h,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: EXTERN.h,v $
* Revision 2.0 86/09/17 15:35:37 lwall
* Baseline for netwide release.
*
diff --git a/gnu/usr.bin/patch/INTERN.h b/gnu/usr.bin/patch/INTERN.h
index 38574ef40108..88a57d6959c7 100644
--- a/gnu/usr.bin/patch/INTERN.h
+++ b/gnu/usr.bin/patch/INTERN.h
@@ -1,6 +1,9 @@
-/* $Header: INTERN.h,v 2.0 86/09/17 15:35:58 lwall Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/INTERN.h,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * INTERN.h,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: INTERN.h,v $
* Revision 2.0 86/09/17 15:35:58 lwall
* Baseline for netwide release.
*
diff --git a/gnu/usr.bin/patch/common.h b/gnu/usr.bin/patch/common.h
index 9bae5bd1c45e..b9d32d4295d1 100644
--- a/gnu/usr.bin/patch/common.h
+++ b/gnu/usr.bin/patch/common.h
@@ -1,6 +1,10 @@
-/* $Header: /a/cvs/386BSD/src/gnu/patch/common.h,v 1.1.1.1 1993/06/19 14:21:52 paul Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/common.h,v 1.2 1993/09/22 16:51:03 rich Exp
+ *
+ * common.h,v
+ * Revision 1.2 1993/09/22 16:51:03 rich
+ * Increaed the fixed static buffer sizes and maximum hunk size that
+ * otherwise causes the XFree86 1.3 patch set to fail.
*
- * $Log: common.h,v $
* Revision 1.1.1.1 1993/06/19 14:21:52 paul
* b-maked patch-2.10
*
diff --git a/gnu/usr.bin/patch/inp.c b/gnu/usr.bin/patch/inp.c
index c99054f3da20..66809205d0e2 100644
--- a/gnu/usr.bin/patch/inp.c
+++ b/gnu/usr.bin/patch/inp.c
@@ -1,6 +1,9 @@
-/* $Header: inp.c,v 2.0.1.1 88/06/03 15:06:13 lwall Locked $
+/* /home/ncvs/src/gnu/usr.bin/patch/inp.c,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * inp.c,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: inp.c,v $
* Revision 2.0.1.1 88/06/03 15:06:13 lwall
* patch10: made a little smarter about sccs files
*
diff --git a/gnu/usr.bin/patch/inp.h b/gnu/usr.bin/patch/inp.h
index c6d2a917d5c4..f788375fd169 100644
--- a/gnu/usr.bin/patch/inp.h
+++ b/gnu/usr.bin/patch/inp.h
@@ -1,6 +1,9 @@
-/* $Header: inp.h,v 2.0 86/09/17 15:37:25 lwall Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/inp.h,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * inp.h,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: inp.h,v $
* Revision 2.0 86/09/17 15:37:25 lwall
* Baseline for netwide release.
*
diff --git a/gnu/usr.bin/patch/patch.1 b/gnu/usr.bin/patch/patch.1
index 6af062a28896..bc7088373906 100644
--- a/gnu/usr.bin/patch/patch.1
+++ b/gnu/usr.bin/patch/patch.1
@@ -1,8 +1,11 @@
.\" -*- nroff -*-
.rn '' }`
-'\" $Header: /home/cvs/386BSD/src/gnu/usr.bin/patch/patch.1,v 1.3 1994/02/17 22:20:33 jkh Exp $
+'\" /home/ncvs/src/gnu/usr.bin/patch/patch.1,v 1.4 1994/02/25 21:45:59 phk Exp
'\"
-'\" $Log: patch.1,v $
+'\" patch.1,v
+.\" Revision 1.4 1994/02/25 21:45:59 phk
+.\" added the -C/-check again.
+.\"
.\" Revision 1.3 1994/02/17 22:20:33 jkh
.\" Put this back - I was somehow under the erroneous impression that patch was in
.\" ports, until I saw the the commit messages, that is! :-) All changed backed out.
diff --git a/gnu/usr.bin/patch/patch.c b/gnu/usr.bin/patch/patch.c
index 626c4535233a..5725c5623e94 100644
--- a/gnu/usr.bin/patch/patch.c
+++ b/gnu/usr.bin/patch/patch.c
@@ -1,5 +1,5 @@
char rcsid[] =
- "$Header: /home/cvs/386BSD/src/gnu/usr.bin/patch/patch.c,v 1.3 1994/02/17 22:20:34 jkh Exp $";
+ "/home/ncvs/src/gnu/usr.bin/patch/patch.c,v 1.4 1994/02/25 21:46:04 phk Exp";
/* patch - a program to apply diffs to original files
*
@@ -8,7 +8,10 @@ char rcsid[] =
* 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 $
+ * patch.c,v
+ * Revision 1.4 1994/02/25 21:46:04 phk
+ * added the -C/-check again.
+ *
* Revision 1.3 1994/02/17 22:20:34 jkh
* Put this back - I was somehow under the erroneous impression that patch was in
* ports, until I saw the the commit messages, that is! :-) All changed backed out.
diff --git a/gnu/usr.bin/patch/pch.c b/gnu/usr.bin/patch/pch.c
index 0a844f2cb09c..e0997de379b4 100644
--- a/gnu/usr.bin/patch/pch.c
+++ b/gnu/usr.bin/patch/pch.c
@@ -1,6 +1,9 @@
-/* $Header: /home/cvs/386BSD/src/gnu/usr.bin/patch/pch.c,v 1.3 1994/02/17 22:20:36 jkh Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/pch.c,v 1.4 1994/02/25 21:46:07 phk Exp
+ *
+ * pch.c,v
+ * Revision 1.4 1994/02/25 21:46:07 phk
+ * added the -C/-check again.
*
- * $Log: pch.c,v $
* Revision 1.3 1994/02/17 22:20:36 jkh
* Put this back - I was somehow under the erroneous impression that patch was in
* ports, until I saw the the commit messages, that is! :-) All changed backed out.
diff --git a/gnu/usr.bin/patch/pch.h b/gnu/usr.bin/patch/pch.h
index 97a5b28a338f..11573dcc9141 100644
--- a/gnu/usr.bin/patch/pch.h
+++ b/gnu/usr.bin/patch/pch.h
@@ -1,6 +1,9 @@
-/* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/pch.h,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * pch.h,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: pch.h,v $
* Revision 2.0.1.1 87/01/30 22:47:16 lwall
* Added do_ed_script().
*
diff --git a/gnu/usr.bin/patch/util.h b/gnu/usr.bin/patch/util.h
index d8e46bb0c180..02f852a2d343 100644
--- a/gnu/usr.bin/patch/util.h
+++ b/gnu/usr.bin/patch/util.h
@@ -1,6 +1,9 @@
-/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/util.h,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * util.h,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: util.h,v $
* Revision 2.0 86/09/17 15:40:06 lwall
* Baseline for netwide release.
*
diff --git a/gnu/usr.bin/patch/version.c b/gnu/usr.bin/patch/version.c
index f0b5223330fa..e84055dead0e 100644
--- a/gnu/usr.bin/patch/version.c
+++ b/gnu/usr.bin/patch/version.c
@@ -1,6 +1,9 @@
-/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/version.c,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * version.c,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: version.c,v $
* Revision 2.0 86/09/17 15:40:11 lwall
* Baseline for netwide release.
*
diff --git a/gnu/usr.bin/patch/version.h b/gnu/usr.bin/patch/version.h
index 08fe68d97388..0f802b693eb4 100644
--- a/gnu/usr.bin/patch/version.h
+++ b/gnu/usr.bin/patch/version.h
@@ -1,6 +1,9 @@
-/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $
+/* /home/ncvs/src/gnu/usr.bin/patch/version.h,v 1.1.1.1 1993/06/19 14:21:52 paul Exp
+ *
+ * version.h,v
+ * Revision 1.1.1.1 1993/06/19 14:21:52 paul
+ * b-maked patch-2.10
*
- * $Log: version.h,v $
* Revision 2.0 86/09/17 15:40:14 lwall
* Baseline for netwide release.
*
diff --git a/gnu/usr.bin/perl/eg/ADB b/gnu/usr.bin/perl/eg/ADB
index 09b93c302aae..558962c713bd 100644
--- a/gnu/usr.bin/perl/eg/ADB
+++ b/gnu/usr.bin/perl/eg/ADB
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/ADB,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/ADB,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
# This script is only useful when used in your crash directory.
diff --git a/gnu/usr.bin/perl/eg/changes b/gnu/usr.bin/perl/eg/changes
index 9835e1b6ddc2..0674aa236f10 100644
--- a/gnu/usr.bin/perl/eg/changes
+++ b/gnu/usr.bin/perl/eg/changes
@@ -1,6 +1,6 @@
#!/usr/bin/perl -P
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/changes,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/changes,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
($dir, $days) = @ARGV;
$dir = '/' if $dir eq '';
diff --git a/gnu/usr.bin/perl/eg/dus b/gnu/usr.bin/perl/eg/dus
index 94c648bd7626..bda5ee422799 100644
--- a/gnu/usr.bin/perl/eg/dus
+++ b/gnu/usr.bin/perl/eg/dus
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/dus,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/dus,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
# This script does a du -s on any directories in the current directory that
# are not mount points for another filesystem.
diff --git a/gnu/usr.bin/perl/eg/findcp b/gnu/usr.bin/perl/eg/findcp
index 47e443820d88..dab7fd9e87f2 100644
--- a/gnu/usr.bin/perl/eg/findcp
+++ b/gnu/usr.bin/perl/eg/findcp
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/findcp,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/findcp,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
# This is a wrapper around the find command that pretends find has a switch
# of the form -cp host:destination. It presumes your find implements -ls.
diff --git a/gnu/usr.bin/perl/eg/findtar b/gnu/usr.bin/perl/eg/findtar
index a60f10f76c32..df8e0fc6679d 100644
--- a/gnu/usr.bin/perl/eg/findtar
+++ b/gnu/usr.bin/perl/eg/findtar
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/findtar,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/findtar,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
# findtar takes find-style arguments and spits out a tarfile on stdout.
# It won't work unless your find supports -ls and your tar the I flag.
diff --git a/gnu/usr.bin/perl/eg/g/gcp b/gnu/usr.bin/perl/eg/g/gcp
index 3e44a9cf182b..f8316c87077b 100644
--- a/gnu/usr.bin/perl/eg/g/gcp
+++ b/gnu/usr.bin/perl/eg/g/gcp
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/g/gcp,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/g/gcp,v 1.1.1.1 1994/09/10 06:27:48 gclarkii Exp
# Here is a script to do global rcps. See man page.
diff --git a/gnu/usr.bin/perl/eg/g/gcp.man b/gnu/usr.bin/perl/eg/g/gcp.man
index 8985742fa473..6d10c11bcc51 100644
--- a/gnu/usr.bin/perl/eg/g/gcp.man
+++ b/gnu/usr.bin/perl/eg/g/gcp.man
@@ -1,4 +1,4 @@
-.\" $Header: /home/cvs/386BSD/ports/lang/perl/eg/g/gcp.man,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+.\" /home/ncvs/src/gnu/usr.bin/perl/eg/g/gcp.man,v 1.1.1.1 1994/09/10 06:27:48 gclarkii Exp
.TH GCP 1C "13 May 1988"
.SH NAME
gcp \- global file copy
diff --git a/gnu/usr.bin/perl/eg/g/ged b/gnu/usr.bin/perl/eg/g/ged
index d296a84c913a..43d93a111e05 100644
--- a/gnu/usr.bin/perl/eg/g/ged
+++ b/gnu/usr.bin/perl/eg/g/ged
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/g/ged,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/g/ged,v 1.1.1.1 1994/09/10 06:27:48 gclarkii Exp
# Does inplace edits on a set of files on a set of machines.
#
diff --git a/gnu/usr.bin/perl/eg/g/gsh b/gnu/usr.bin/perl/eg/g/gsh
index 3322a02ff74f..d4d4b5819fd6 100644
--- a/gnu/usr.bin/perl/eg/g/gsh
+++ b/gnu/usr.bin/perl/eg/g/gsh
@@ -1,6 +1,6 @@
#! /usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/g/gsh,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/g/gsh,v 1.1.1.1 1994/09/10 06:27:48 gclarkii Exp
# Do rsh globally--see man page
diff --git a/gnu/usr.bin/perl/eg/g/gsh.man b/gnu/usr.bin/perl/eg/g/gsh.man
index 00eafb66d8c2..9503ad101850 100644
--- a/gnu/usr.bin/perl/eg/g/gsh.man
+++ b/gnu/usr.bin/perl/eg/g/gsh.man
@@ -1,4 +1,4 @@
-.\" $Header: /home/cvs/386BSD/ports/lang/perl/eg/g/gsh.man,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+.\" /home/ncvs/src/gnu/usr.bin/perl/eg/g/gsh.man,v 1.1.1.1 1994/09/10 06:27:48 gclarkii Exp
.TH GSH 8 "13 May 1988"
.SH NAME
gsh \- global shell
diff --git a/gnu/usr.bin/perl/eg/muck.man b/gnu/usr.bin/perl/eg/muck.man
index 1b45ee0325c0..ef1c8e936aab 100644
--- a/gnu/usr.bin/perl/eg/muck.man
+++ b/gnu/usr.bin/perl/eg/muck.man
@@ -1,4 +1,4 @@
-.\" $Header: /home/cvs/386BSD/ports/lang/perl/eg/muck.man,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+.\" /home/ncvs/src/gnu/usr.bin/perl/eg/muck.man,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
.TH MUCK 1 "10 Jan 1989"
.SH NAME
muck \- make usage checker
diff --git a/gnu/usr.bin/perl/eg/myrup b/gnu/usr.bin/perl/eg/myrup
index b3185896ef98..cd7c7a9d421d 100644
--- a/gnu/usr.bin/perl/eg/myrup
+++ b/gnu/usr.bin/perl/eg/myrup
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/myrup,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/myrup,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
# This was a customization of ruptime requested by someone here who wanted
# to be able to find the least loaded machine easily. It uses the
diff --git a/gnu/usr.bin/perl/eg/nih b/gnu/usr.bin/perl/eg/nih
index a376142cdd75..eeeeb28f3b23 100644
--- a/gnu/usr.bin/perl/eg/nih
+++ b/gnu/usr.bin/perl/eg/nih
@@ -1,7 +1,7 @@
eval "exec /usr/bin/perl -Spi.bak $0 $*"
if $running_under_some_shell;
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/nih,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/nih,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
# This script makes #! scripts directly executable on machines that don't
# support #!. It edits in place any scripts mentioned on the command line.
diff --git a/gnu/usr.bin/perl/eg/relink b/gnu/usr.bin/perl/eg/relink
index 69956c9a6738..ba5d5cad97f8 100644
--- a/gnu/usr.bin/perl/eg/relink
+++ b/gnu/usr.bin/perl/eg/relink
@@ -2,9 +2,12 @@
'di';
'ig00';
#
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/relink,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/relink,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
+#
+# relink,v
+# Revision 1.1.1.1 1994/09/10 06:27:47 gclarkii
+# Initial import of Perl 4.046 bmaked
#
-# $Log: relink,v $
# Revision 1.1.1.1 1993/08/23 21:29:43 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/eg/rename b/gnu/usr.bin/perl/eg/rename
index b568406f8603..2bd4f5cc3737 100644
--- a/gnu/usr.bin/perl/eg/rename
+++ b/gnu/usr.bin/perl/eg/rename
@@ -2,9 +2,12 @@
'di';
'ig00';
#
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/rename,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/rename,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
+#
+# rename,v
+# Revision 1.1.1.1 1994/09/10 06:27:47 gclarkii
+# Initial import of Perl 4.046 bmaked
#
-# $Log: rename,v $
# Revision 1.1.1.1 1993/08/23 21:29:43 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/eg/rmfrom b/gnu/usr.bin/perl/eg/rmfrom
index 0c8fa2c86aaf..c81b91bc4181 100644
--- a/gnu/usr.bin/perl/eg/rmfrom
+++ b/gnu/usr.bin/perl/eg/rmfrom
@@ -1,6 +1,6 @@
#!/usr/bin/perl -n
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/rmfrom,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/rmfrom,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
# A handy (but dangerous) script to put after a find ... -print.
diff --git a/gnu/usr.bin/perl/eg/scan/scan_df b/gnu/usr.bin/perl/eg/scan/scan_df
index 688738710a53..2bfd61c6ed71 100644
--- a/gnu/usr.bin/perl/eg/scan/scan_df
+++ b/gnu/usr.bin/perl/eg/scan/scan_df
@@ -1,6 +1,6 @@
#!/usr/bin/perl -P
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scan_df,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scan_df,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# This report points out filesystems that are in danger of overflowing.
diff --git a/gnu/usr.bin/perl/eg/scan/scan_last b/gnu/usr.bin/perl/eg/scan/scan_last
index 6621120d3e44..9f40cf0e6775 100644
--- a/gnu/usr.bin/perl/eg/scan/scan_last
+++ b/gnu/usr.bin/perl/eg/scan/scan_last
@@ -1,6 +1,6 @@
#!/usr/bin/perl -P
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scan_last,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scan_last,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# This reports who was logged on at weird hours
diff --git a/gnu/usr.bin/perl/eg/scan/scan_messages b/gnu/usr.bin/perl/eg/scan/scan_messages
index a28cda858a17..4591bc6a25e9 100644
--- a/gnu/usr.bin/perl/eg/scan/scan_messages
+++ b/gnu/usr.bin/perl/eg/scan/scan_messages
@@ -1,6 +1,6 @@
#!/usr/bin/perl -P
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scan_messages,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scan_messages,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# This prints out extraordinary console messages. You'll need to customize.
diff --git a/gnu/usr.bin/perl/eg/scan/scan_passwd b/gnu/usr.bin/perl/eg/scan/scan_passwd
index f9c53c7d2385..df82fe87aca4 100644
--- a/gnu/usr.bin/perl/eg/scan/scan_passwd
+++ b/gnu/usr.bin/perl/eg/scan/scan_passwd
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scan_passwd,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scan_passwd,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# This scans passwd file for security holes.
diff --git a/gnu/usr.bin/perl/eg/scan/scan_ps b/gnu/usr.bin/perl/eg/scan/scan_ps
index b0480d544c30..d064887a022b 100644
--- a/gnu/usr.bin/perl/eg/scan/scan_ps
+++ b/gnu/usr.bin/perl/eg/scan/scan_ps
@@ -1,6 +1,6 @@
#!/usr/bin/perl -P
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scan_ps,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scan_ps,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# This looks for looping processes.
diff --git a/gnu/usr.bin/perl/eg/scan/scan_sudo b/gnu/usr.bin/perl/eg/scan/scan_sudo
index a95a6092b467..2f04cfbb2ba5 100644
--- a/gnu/usr.bin/perl/eg/scan/scan_sudo
+++ b/gnu/usr.bin/perl/eg/scan/scan_sudo
@@ -1,6 +1,6 @@
#!/usr/bin/perl -P
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scan_sudo,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scan_sudo,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# Analyze the sudo log.
diff --git a/gnu/usr.bin/perl/eg/scan/scan_suid b/gnu/usr.bin/perl/eg/scan/scan_suid
index a730e0aaee16..6fe61d5d8761 100644
--- a/gnu/usr.bin/perl/eg/scan/scan_suid
+++ b/gnu/usr.bin/perl/eg/scan/scan_suid
@@ -1,6 +1,6 @@
#!/usr/bin/perl -P
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scan_suid,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scan_suid,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# Look for new setuid root files.
diff --git a/gnu/usr.bin/perl/eg/scan/scanner b/gnu/usr.bin/perl/eg/scan/scanner
index f773e87e8f8a..6c386e342331 100644
--- a/gnu/usr.bin/perl/eg/scan/scanner
+++ b/gnu/usr.bin/perl/eg/scan/scanner
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/scan/scanner,v 1.1.1.1 1993/08/23 21:29:44 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/scan/scanner,v 1.1.1.1 1994/09/10 06:27:48 gclarkii Exp
# This runs all the scan_* routines on all the machines in /etc/ghosts.
# We run this every morning at about 6 am:
diff --git a/gnu/usr.bin/perl/eg/shmkill b/gnu/usr.bin/perl/eg/shmkill
index e8d1b11b3630..3b9f399195b6 100644
--- a/gnu/usr.bin/perl/eg/shmkill
+++ b/gnu/usr.bin/perl/eg/shmkill
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/shmkill,v 1.1.1.1 1993/08/23 21:29:43 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/shmkill,v 1.1.1.1 1994/09/10 06:27:47 gclarkii Exp
# A script to call from crontab periodically when people are leaving shared
# memory sitting around unattached.
diff --git a/gnu/usr.bin/perl/eg/van/empty b/gnu/usr.bin/perl/eg/van/empty
index ee656e68563f..fe86e2a76532 100644
--- a/gnu/usr.bin/perl/eg/van/empty
+++ b/gnu/usr.bin/perl/eg/van/empty
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/van/empty,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/van/empty,v 1.1.1.1 1994/09/10 06:27:49 gclarkii Exp
# This script empties a trashcan.
diff --git a/gnu/usr.bin/perl/eg/van/unvanish b/gnu/usr.bin/perl/eg/van/unvanish
index 50459821546b..a2ec654d64fc 100644
--- a/gnu/usr.bin/perl/eg/van/unvanish
+++ b/gnu/usr.bin/perl/eg/van/unvanish
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/van/unvanish,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/van/unvanish,v 1.1.1.1 1994/09/10 06:27:50 gclarkii Exp
sub it {
if ($olddir ne '.') {
diff --git a/gnu/usr.bin/perl/eg/van/vanexp b/gnu/usr.bin/perl/eg/van/vanexp
index 79b78854d54c..1804bcdc9975 100644
--- a/gnu/usr.bin/perl/eg/van/vanexp
+++ b/gnu/usr.bin/perl/eg/van/vanexp
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/van/vanexp,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/van/vanexp,v 1.1.1.1 1994/09/10 06:27:50 gclarkii Exp
# This is for running from a find at night to expire old .deleteds
diff --git a/gnu/usr.bin/perl/eg/van/vanish b/gnu/usr.bin/perl/eg/van/vanish
index b79776a4ebdc..26c95760f21f 100644
--- a/gnu/usr.bin/perl/eg/van/vanish
+++ b/gnu/usr.bin/perl/eg/van/vanish
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/eg/van/vanish,v 1.1.1.1 1993/08/23 21:29:45 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/eg/van/vanish,v 1.1.1.1 1994/09/10 06:27:50 gclarkii Exp
sub it {
if ($olddir ne '.') {
diff --git a/gnu/usr.bin/perl/emacs/perldb.pl b/gnu/usr.bin/perl/emacs/perldb.pl
index 7c9e6513ea0c..56582c904903 100644
--- a/gnu/usr.bin/perl/emacs/perldb.pl
+++ b/gnu/usr.bin/perl/emacs/perldb.pl
@@ -3,7 +3,7 @@ package DB;
# modified Perl debugger, to be run from Emacs in perldb-mode
# Ray Lischner (uunet!mntgfx!lisch) as of 5 Nov 1990
-$header = '$Header: /home/cvs/386BSD/ports/lang/perl/emacs/perldb.pl,v 1.1.1.1 1993/08/23 21:29:46 nate Exp $';
+$header = '/home/ncvs/src/gnu/usr.bin/perl/emacs/perldb.pl,v 1.1.1.1 1994/09/10 06:27:50 gclarkii Exp';
#
# This file is automatically included if you do perl -d.
# It's probably not useful to include this yourself.
@@ -12,7 +12,10 @@ $header = '$Header: /home/cvs/386BSD/ports/lang/perl/emacs/perldb.pl,v 1.1.1.1 1
# a do DB'DB(<linenum>); in front of every place that can
# have a breakpoint. It also inserts a do 'perldb.pl' before the first line.
#
-# $Log: perldb.pl,v $
+# perldb.pl,v
+# Revision 1.1.1.1 1994/09/10 06:27:50 gclarkii
+# Initial import of Perl 4.046 bmaked
+#
# Revision 1.1.1.1 1993/08/23 21:29:46 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/lib/ctime.pl b/gnu/usr.bin/perl/lib/ctime.pl
index 4c59754b7b81..6830d7a28eb3 100644
--- a/gnu/usr.bin/perl/lib/ctime.pl
+++ b/gnu/usr.bin/perl/lib/ctime.pl
@@ -3,7 +3,7 @@
;# Waldemar Kebsch, Federal Republic of Germany, November 1988
;# kebsch.pad@nixpbe.UUCP
;# Modified March 1990, Feb 1991 to properly handle timezones
-;# $RCSfile: ctime.pl,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:52 $
+;# ctime.pl,v1.1.1.11994/09/10 06:27:52
;# Marion Hakanson (hakanson@cse.ogi.edu)
;# Oregon Graduate Institute of Science and Technology
;#
diff --git a/gnu/usr.bin/perl/lib/getopt.pl b/gnu/usr.bin/perl/lib/getopt.pl
index 6772d54aae20..80414132340f 100644
--- a/gnu/usr.bin/perl/lib/getopt.pl
+++ b/gnu/usr.bin/perl/lib/getopt.pl
@@ -1,4 +1,4 @@
-;# $RCSfile: getopt.pl,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:52 $
+;# getopt.pl,v1.1.1.11994/09/10 06:27:52
;# Process single-character switches with switch clustering. Pass one argument
;# which is a string containing all switches that take an argument. For each
diff --git a/gnu/usr.bin/perl/lib/importenv.pl b/gnu/usr.bin/perl/lib/importenv.pl
index c9ad330b6d03..b6ac38a4288b 100644
--- a/gnu/usr.bin/perl/lib/importenv.pl
+++ b/gnu/usr.bin/perl/lib/importenv.pl
@@ -1,4 +1,4 @@
-;# $Header: /home/cvs/386BSD/ports/lang/perl/lib/importenv.pl,v 1.1.1.1 1993/08/23 21:29:53 nate Exp $
+;# /home/ncvs/src/gnu/usr.bin/perl/lib/importenv.pl,v 1.1.1.1 1994/09/10 06:27:52 gclarkii Exp
;# This file, when interpreted, pulls the environment into normal variables.
;# Usage:
diff --git a/gnu/usr.bin/perl/lib/perldb.pl b/gnu/usr.bin/perl/lib/perldb.pl
index 1aadb934e979..d33784361828 100644
--- a/gnu/usr.bin/perl/lib/perldb.pl
+++ b/gnu/usr.bin/perl/lib/perldb.pl
@@ -4,7 +4,7 @@ package DB;
# Ray Lischner (uunet!mntgfx!lisch) as of 5 Nov 1990
# Johan Vromans -- upgrade to 4.0 pl 10
-$header = '$RCSfile: perldb.pl,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:51 $';
+$header = 'perldb.pl,v1.1.1.11994/09/10 06:27:53';
#
# This file is automatically included if you do perl -d.
# It's probably not useful to include this yourself.
@@ -13,7 +13,10 @@ $header = '$RCSfile: perldb.pl,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:51
# a do DB'DB(<linenum>); in front of every place that can
# have a breakpoint. It also inserts a do 'perldb.pl' before the first line.
#
-# $Log: perldb.pl,v $
+# perldb.pl,v
+# Revision 1.1.1.1 1994/09/10 06:27:53 gclarkii
+# Initial import of Perl 4.046 bmaked
+#
# Revision 1.1.1.1 1993/08/23 21:29:51 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/lib/pwd.pl b/gnu/usr.bin/perl/lib/pwd.pl
index 16baadcdcdd4..41543e46b939 100644
--- a/gnu/usr.bin/perl/lib/pwd.pl
+++ b/gnu/usr.bin/perl/lib/pwd.pl
@@ -1,8 +1,11 @@
;# pwd.pl - keeps track of current working directory in PWD environment var
;#
-;# $RCSfile: pwd.pl,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:52 $
+;# pwd.pl,v1.1.1.11994/09/10 06:27:53
;#
-;# $Log: pwd.pl,v $
+;# pwd.pl,v
+# Revision 1.1.1.1 1994/09/10 06:27:53 gclarkii
+# Initial import of Perl 4.046 bmaked
+#
# Revision 1.1.1.1 1993/08/23 21:29:52 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/lib/stat.pl b/gnu/usr.bin/perl/lib/stat.pl
index 6186f5428d18..e547e0654bd9 100644
--- a/gnu/usr.bin/perl/lib/stat.pl
+++ b/gnu/usr.bin/perl/lib/stat.pl
@@ -1,4 +1,4 @@
-;# $Header: /home/cvs/386BSD/ports/lang/perl/lib/stat.pl,v 1.1.1.1 1993/08/23 21:29:53 nate Exp $
+;# /home/ncvs/src/gnu/usr.bin/perl/lib/stat.pl,v 1.1.1.1 1994/09/10 06:27:53 gclarkii Exp
;# Usage:
;# require 'stat.pl';
diff --git a/gnu/usr.bin/perl/lib/syslog.pl b/gnu/usr.bin/perl/lib/syslog.pl
index 94a4f6a19a00..0b6e319d8768 100644
--- a/gnu/usr.bin/perl/lib/syslog.pl
+++ b/gnu/usr.bin/perl/lib/syslog.pl
@@ -1,7 +1,10 @@
#
# syslog.pl
#
-# $Log: syslog.pl,v $
+# syslog.pl,v
+# Revision 1.1.1.1 1994/09/10 06:27:53 gclarkii
+# Initial import of Perl 4.046 bmaked
+#
# Revision 1.1.1.1 1993/08/23 21:29:51 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/lib/termcap.pl b/gnu/usr.bin/perl/lib/termcap.pl
index 81556dbd3fb4..bf5c36157761 100644
--- a/gnu/usr.bin/perl/lib/termcap.pl
+++ b/gnu/usr.bin/perl/lib/termcap.pl
@@ -1,4 +1,4 @@
-;# $RCSfile: termcap.pl,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:52 $
+;# termcap.pl,v1.1.1.11994/09/10 06:27:53
;#
;# Usage:
;# require 'ioctl.pl';
diff --git a/gnu/usr.bin/perl/lib/validate.pl b/gnu/usr.bin/perl/lib/validate.pl
index 4b901b6c314e..4848168b36bd 100644
--- a/gnu/usr.bin/perl/lib/validate.pl
+++ b/gnu/usr.bin/perl/lib/validate.pl
@@ -1,4 +1,4 @@
-;# $Header: /home/cvs/386BSD/ports/lang/perl/lib/validate.pl,v 1.1.1.1 1993/08/23 21:29:51 nate Exp $
+;# /home/ncvs/src/gnu/usr.bin/perl/lib/validate.pl,v 1.1.1.1 1994/09/10 06:27:53 gclarkii Exp
;# The validate routine takes a single multiline string consisting of
;# lines containing a filename plus a file test to try on it. (The
diff --git a/gnu/usr.bin/perl/misc/c2ph b/gnu/usr.bin/perl/misc/c2ph
index 1a2e4b8306ea..bffda9919efc 100644
--- a/gnu/usr.bin/perl/misc/c2ph
+++ b/gnu/usr.bin/perl/misc/c2ph
@@ -10,7 +10,7 @@
# See the usage message for more. If this isn't enough, read the code.
#
-$RCSID = '$RCSfile: c2ph,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:31 $';
+$RCSID = 'c2ph,v1.21994/10/29 07:14:38';
######################################################################
diff --git a/gnu/usr.bin/perl/misc/pstruct b/gnu/usr.bin/perl/misc/pstruct
index 5dfea04776f6..c061912f01af 100644
--- a/gnu/usr.bin/perl/misc/pstruct
+++ b/gnu/usr.bin/perl/misc/pstruct
@@ -10,7 +10,7 @@
# See the usage message for more. If this isn't enough, read the code.
#
-$RCSID = '$RCSfile: pstruct,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:31 $';
+$RCSID = 'pstruct,v1.21994/10/29 07:14:39';
######################################################################
diff --git a/gnu/usr.bin/perl/perl/EXTERN.h b/gnu/usr.bin/perl/perl/EXTERN.h
index 181d50dd739e..e719f74b9315 100644
--- a/gnu/usr.bin/perl/perl/EXTERN.h
+++ b/gnu/usr.bin/perl/perl/EXTERN.h
@@ -1,11 +1,14 @@
-/* $RCSfile: EXTERN.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:33 $
+/* EXTERN.h,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: EXTERN.h,v $
+ * EXTERN.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:33 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/INTERN.h b/gnu/usr.bin/perl/perl/INTERN.h
index 21c90265a04b..08c3c4e630ae 100644
--- a/gnu/usr.bin/perl/perl/INTERN.h
+++ b/gnu/usr.bin/perl/perl/INTERN.h
@@ -1,11 +1,14 @@
-/* $RCSfile: INTERN.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:33 $
+/* INTERN.h,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: INTERN.h,v $
+ * INTERN.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:33 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/arg.h b/gnu/usr.bin/perl/perl/arg.h
index 813ce3adc942..3191636fcb04 100644
--- a/gnu/usr.bin/perl/perl/arg.h
+++ b/gnu/usr.bin/perl/perl/arg.h
@@ -1,11 +1,15 @@
-/* $RCSfile: arg.h,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:34 $
+/* arg.h,v1.21994/09/11 03:17:24
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: arg.h,v $
+ * arg.h,v
+ * Revision 1.2 1994/09/11 03:17:24 gclarkii
+ * Changed AF_LOCAL to AF_LOCAL_XX so as not to conflict with 4.4 socket.h
+ * Added casts to shutup warnings in doio.c
+ *
* Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
* Initial import of Perl 4.046 bmaked
*
diff --git a/gnu/usr.bin/perl/perl/array.c b/gnu/usr.bin/perl/perl/array.c
index 445bc60be7dc..488e77554268 100644
--- a/gnu/usr.bin/perl/perl/array.c
+++ b/gnu/usr.bin/perl/perl/array.c
@@ -1,11 +1,14 @@
-/* $RCSfile: array.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:34 $
+/* array.c,v1.1.1.11994/09/10 06:27:31
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: array.c,v $
+ * array.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:31 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:34 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/array.h b/gnu/usr.bin/perl/perl/array.h
index 93d4920aedcf..e4bfaf46e37a 100644
--- a/gnu/usr.bin/perl/perl/array.h
+++ b/gnu/usr.bin/perl/perl/array.h
@@ -1,11 +1,14 @@
-/* $RCSfile: array.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:34 $
+/* array.h,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: array.h,v $
+ * array.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:34 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/cmd.c b/gnu/usr.bin/perl/perl/cmd.c
index 1ddbde082a1e..47305c728117 100644
--- a/gnu/usr.bin/perl/perl/cmd.c
+++ b/gnu/usr.bin/perl/perl/cmd.c
@@ -1,11 +1,14 @@
-/* $RCSfile: cmd.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:35 $
+/* cmd.c,v1.1.1.11994/09/10 06:27:32
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: cmd.c,v $
+ * cmd.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:35 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/cmd.h b/gnu/usr.bin/perl/perl/cmd.h
index 76ef5c8b58d9..a48e10cb6d11 100644
--- a/gnu/usr.bin/perl/perl/cmd.h
+++ b/gnu/usr.bin/perl/perl/cmd.h
@@ -1,11 +1,14 @@
-/* $RCSfile: cmd.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:35 $
+/* cmd.h,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: cmd.h,v $
+ * cmd.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:35 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/cons.c b/gnu/usr.bin/perl/perl/cons.c
index c926f7a86c96..f4f4f018c507 100644
--- a/gnu/usr.bin/perl/perl/cons.c
+++ b/gnu/usr.bin/perl/perl/cons.c
@@ -1,11 +1,14 @@
-/* $RCSfile: cons.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:35 $
+/* cons.c,v1.1.1.11994/09/10 06:27:32
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: cons.c,v $
+ * cons.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:35 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/consarg.c b/gnu/usr.bin/perl/perl/consarg.c
index 440fcfd0f1e9..deacf4ee8e60 100644
--- a/gnu/usr.bin/perl/perl/consarg.c
+++ b/gnu/usr.bin/perl/perl/consarg.c
@@ -1,11 +1,15 @@
-/* $RCSfile: consarg.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $
+/* consarg.c,v1.21994/09/11 03:17:29
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: consarg.c,v $
+ * consarg.c,v
+ * Revision 1.2 1994/09/11 03:17:29 gclarkii
+ * Changed AF_LOCAL to AF_LOCAL_XX so as not to conflict with 4.4 socket.h
+ * Added casts to shutup warnings in doio.c
+ *
* Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
* Initial import of Perl 4.046 bmaked
*
diff --git a/gnu/usr.bin/perl/perl/crypt.c b/gnu/usr.bin/perl/perl/crypt.c
index 3299a8663c6e..5f0e5dc39382 100644
--- a/gnu/usr.bin/perl/perl/crypt.c
+++ b/gnu/usr.bin/perl/perl/crypt.c
@@ -36,7 +36,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/* from static char sccsid[] = "@(#)crypt.c 5.11 (Berkeley) 6/25/91"; */
-static char rcsid[] = "$Header: /home/cvs/386BSD/src/lib/libc/gen/crypt.c,v 1.6 1993/08/29 22:03:56 nate Exp $";
+static char rcsid[] = "/home/ncvs/src/gnu/usr.bin/perl/perl/crypt.c,v 1.1.1.1 1994/09/10 06:27:37 gclarkii Exp";
#endif /* LIBC_SCCS and not lint */
#include <unistd.h>
diff --git a/gnu/usr.bin/perl/perl/doarg.c b/gnu/usr.bin/perl/perl/doarg.c
index 7c03bffc9ca9..ae5d4edbb363 100644
--- a/gnu/usr.bin/perl/perl/doarg.c
+++ b/gnu/usr.bin/perl/perl/doarg.c
@@ -1,11 +1,15 @@
-/* $RCSfile: doarg.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $
+/* doarg.c,v1.21994/09/11 03:17:30
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: doarg.c,v $
+ * doarg.c,v
+ * Revision 1.2 1994/09/11 03:17:30 gclarkii
+ * Changed AF_LOCAL to AF_LOCAL_XX so as not to conflict with 4.4 socket.h
+ * Added casts to shutup warnings in doio.c
+ *
* Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
* Initial import of Perl 4.046 bmaked
*
diff --git a/gnu/usr.bin/perl/perl/doio.c b/gnu/usr.bin/perl/perl/doio.c
index a603febfc9b9..1673eedc51e3 100644
--- a/gnu/usr.bin/perl/perl/doio.c
+++ b/gnu/usr.bin/perl/perl/doio.c
@@ -1,11 +1,15 @@
-/* $RCSfile: doio.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $
+/* doio.c,v1.21994/09/11 03:17:32
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: doio.c,v $
+ * doio.c,v
+ * Revision 1.2 1994/09/11 03:17:32 gclarkii
+ * Changed AF_LOCAL to AF_LOCAL_XX so as not to conflict with 4.4 socket.h
+ * Added casts to shutup warnings in doio.c
+ *
* Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
* Initial import of Perl 4.046 bmaked
*
diff --git a/gnu/usr.bin/perl/perl/dolist.c b/gnu/usr.bin/perl/perl/dolist.c
index f966479dbef7..d8151e38d545 100644
--- a/gnu/usr.bin/perl/perl/dolist.c
+++ b/gnu/usr.bin/perl/perl/dolist.c
@@ -1,11 +1,14 @@
-/* $RCSfile: dolist.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:36 $
+/* dolist.c,v1.1.1.11994/09/10 06:27:32
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: dolist.c,v $
+ * dolist.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:36 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/dump.c b/gnu/usr.bin/perl/perl/dump.c
index c9551691fb40..beee2f148668 100644
--- a/gnu/usr.bin/perl/perl/dump.c
+++ b/gnu/usr.bin/perl/perl/dump.c
@@ -1,11 +1,15 @@
-/* $RCSfile: dump.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $
+/* dump.c,v1.21994/09/11 03:17:33
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: dump.c,v $
+ * dump.c,v
+ * Revision 1.2 1994/09/11 03:17:33 gclarkii
+ * Changed AF_LOCAL to AF_LOCAL_XX so as not to conflict with 4.4 socket.h
+ * Added casts to shutup warnings in doio.c
+ *
* Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
* Initial import of Perl 4.046 bmaked
*
diff --git a/gnu/usr.bin/perl/perl/eval.c b/gnu/usr.bin/perl/perl/eval.c
index fbd2fdd441f6..af3b8ec5b254 100644
--- a/gnu/usr.bin/perl/perl/eval.c
+++ b/gnu/usr.bin/perl/perl/eval.c
@@ -1,11 +1,14 @@
-/* $RCSfile: eval.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:36 $
+/* eval.c,v1.1.1.11994/09/10 06:27:32
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: eval.c,v $
+ * eval.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:36 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/form.c b/gnu/usr.bin/perl/perl/form.c
index 57fc5de72e99..f86c7b690878 100644
--- a/gnu/usr.bin/perl/perl/form.c
+++ b/gnu/usr.bin/perl/perl/form.c
@@ -1,11 +1,14 @@
-/* $RCSfile: form.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:36 $
+/* form.c,v1.1.1.11994/09/10 06:27:33
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: form.c,v $
+ * form.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:36 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/form.h b/gnu/usr.bin/perl/perl/form.h
index 1e3e6f458540..0f5f7d189485 100644
--- a/gnu/usr.bin/perl/perl/form.h
+++ b/gnu/usr.bin/perl/perl/form.h
@@ -1,11 +1,14 @@
-/* $RCSfile: form.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:36 $
+/* form.h,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: form.h,v $
+ * form.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:36 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/handy.h b/gnu/usr.bin/perl/perl/handy.h
index 46231aed9c6e..8d06646f133b 100644
--- a/gnu/usr.bin/perl/perl/handy.h
+++ b/gnu/usr.bin/perl/perl/handy.h
@@ -1,11 +1,14 @@
-/* $RCSfile: handy.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:36 $
+/* handy.h,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: handy.h,v $
+ * handy.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:36 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/hash.c b/gnu/usr.bin/perl/perl/hash.c
index 15cc116001b3..ba7175f679cb 100644
--- a/gnu/usr.bin/perl/perl/hash.c
+++ b/gnu/usr.bin/perl/perl/hash.c
@@ -1,11 +1,14 @@
-/* $RCSfile: hash.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:37 $
+/* hash.c,v1.1.1.11994/09/10 06:27:33
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: hash.c,v $
+ * hash.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:37 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/hash.h b/gnu/usr.bin/perl/perl/hash.h
index 858721f54318..0c5d3042db8e 100644
--- a/gnu/usr.bin/perl/perl/hash.h
+++ b/gnu/usr.bin/perl/perl/hash.h
@@ -1,11 +1,14 @@
-/* $RCSfile: hash.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:37 $
+/* hash.h,v1.1.1.11994/09/10 06:27:35
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: hash.h,v $
+ * hash.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:37 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/malloc.c b/gnu/usr.bin/perl/perl/malloc.c
index 8bfee4064576..10c409ef304e 100644
--- a/gnu/usr.bin/perl/perl/malloc.c
+++ b/gnu/usr.bin/perl/perl/malloc.c
@@ -1,6 +1,9 @@
-/* $RCSfile: malloc.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:37 $
+/* malloc.c,v1.1.1.11994/09/10 06:27:33
+ *
+ * malloc.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
+ * Initial import of Perl 4.046 bmaked
*
- * $Log: malloc.c,v $
* Revision 1.1.1.1 1993/08/23 21:29:37 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/perl.1 b/gnu/usr.bin/perl/perl/perl.1
index 15791c22b691..b73ab521a01c 100644
--- a/gnu/usr.bin/perl/perl/perl.1
+++ b/gnu/usr.bin/perl/perl/perl.1
@@ -1,7 +1,13 @@
.rn '' }`
-''' $RCSfile: perl.1,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:36 $
+''' perl.1,v1.21994/10/27 23:16:52
'''
-''' $Log: perl.1,v $
+''' perl.1,v
+.\" Revision 1.2 1994/10/27 23:16:52 wollman
+.\" Convince Perl to that is is part of the system, as /usr/bin/perl (binary)
+.\" and /usr/share/perl (library). The latter was chosen as analogous to other
+.\" directories already present in /usr/share, like /usr/share/groff_font and
+.\" (particularly) /usr/share/mk.
+.\"
.\" Revision 1.1.1.1 1994/09/10 06:27:36 gclarkii
.\" Initial import of Perl 4.046 bmaked
.\"
diff --git a/gnu/usr.bin/perl/perl/perl.c b/gnu/usr.bin/perl/perl/perl.c
index efb226c54eba..55a26ad5551d 100644
--- a/gnu/usr.bin/perl/perl/perl.c
+++ b/gnu/usr.bin/perl/perl/perl.c
@@ -1,11 +1,17 @@
-char rcsid[] = "$RCSfile: perl.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:33 $\nPatch level: ###\n";
+char rcsid[] = "perl.c,v1.21994/10/27 23:16:54\nPatch level: ###\n";
/*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: perl.c,v $
+ * perl.c,v
+ * Revision 1.2 1994/10/27 23:16:54 wollman
+ * Convince Perl to that is is part of the system, as /usr/bin/perl (binary)
+ * and /usr/share/perl (library). The latter was chosen as analogous to other
+ * directories already present in /usr/share, like /usr/share/groff_font and
+ * (particularly) /usr/share/mk.
+ *
* Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
* Initial import of Perl 4.046 bmaked
*
diff --git a/gnu/usr.bin/perl/perl/perl.h b/gnu/usr.bin/perl/perl/perl.h
index 8249c62bd492..2f5dc1f7f318 100644
--- a/gnu/usr.bin/perl/perl/perl.h
+++ b/gnu/usr.bin/perl/perl/perl.h
@@ -1,11 +1,14 @@
-/* $RCSfile: perl.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:35 $
+/* perl.h,v1.1.1.11994/09/10 06:27:35
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: perl.h,v $
+ * perl.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:35 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/regcomp.c b/gnu/usr.bin/perl/perl/regcomp.c
index 8337e9cfd0d5..12e0e4f7fece 100644
--- a/gnu/usr.bin/perl/perl/regcomp.c
+++ b/gnu/usr.bin/perl/perl/regcomp.c
@@ -7,9 +7,12 @@
* blame Henry for some of the lack of readability.
*/
-/* $RCSfile: regcomp.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* regcomp.c,v1.1.1.11994/09/10 06:27:33
+ *
+ * regcomp.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
+ * Initial import of Perl 4.046 bmaked
*
- * $Log: regcomp.c,v $
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/regcomp.h b/gnu/usr.bin/perl/perl/regcomp.h
index 6dcd482fcd5f..e0822c04d709 100644
--- a/gnu/usr.bin/perl/perl/regcomp.h
+++ b/gnu/usr.bin/perl/perl/regcomp.h
@@ -1,6 +1,9 @@
-/* $RCSfile: regcomp.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* regcomp.h,v1.1.1.11994/09/10 06:27:35
+ *
+ * regcomp.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
*
- * $Log: regcomp.h,v $
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/regexec.c b/gnu/usr.bin/perl/perl/regexec.c
index 7802465f734d..4dd52eb7272e 100644
--- a/gnu/usr.bin/perl/perl/regexec.c
+++ b/gnu/usr.bin/perl/perl/regexec.c
@@ -7,9 +7,12 @@
* blame Henry for some of the lack of readability.
*/
-/* $RCSfile: regexec.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* regexec.c,v1.1.1.11994/09/10 06:27:33
+ *
+ * regexec.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
+ * Initial import of Perl 4.046 bmaked
*
- * $Log: regexec.c,v $
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/regexp.h b/gnu/usr.bin/perl/perl/regexp.h
index 66a1b8818d8f..4220b08b0941 100644
--- a/gnu/usr.bin/perl/perl/regexp.h
+++ b/gnu/usr.bin/perl/perl/regexp.h
@@ -5,9 +5,12 @@
* not the System V one.
*/
-/* $RCSfile: regexp.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* regexp.h,v1.1.1.11994/09/10 06:27:35
+ *
+ * regexp.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
*
- * $Log: regexp.h,v $
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/spat.h b/gnu/usr.bin/perl/perl/spat.h
index 2a840e2855fb..acdee451b261 100644
--- a/gnu/usr.bin/perl/perl/spat.h
+++ b/gnu/usr.bin/perl/perl/spat.h
@@ -1,11 +1,14 @@
-/* $RCSfile: spat.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* spat.h,v1.1.1.11994/09/10 06:27:35
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: spat.h,v $
+ * spat.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/stab.c b/gnu/usr.bin/perl/perl/stab.c
index 70827255d7bf..eb3222db4b62 100644
--- a/gnu/usr.bin/perl/perl/stab.c
+++ b/gnu/usr.bin/perl/perl/stab.c
@@ -1,11 +1,14 @@
-/* $RCSfile: stab.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* stab.c,v1.1.1.11994/09/10 06:27:33
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: stab.c,v $
+ * stab.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/stab.h b/gnu/usr.bin/perl/perl/stab.h
index 7bce082e7a9a..5fcfb28a1a0e 100644
--- a/gnu/usr.bin/perl/perl/stab.h
+++ b/gnu/usr.bin/perl/perl/stab.h
@@ -1,11 +1,14 @@
-/* $RCSfile: stab.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* stab.h,v1.1.1.11994/09/10 06:27:35
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: stab.h,v $
+ * stab.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/str.c b/gnu/usr.bin/perl/perl/str.c
index f034292e1076..fd3cc5a36b91 100644
--- a/gnu/usr.bin/perl/perl/str.c
+++ b/gnu/usr.bin/perl/perl/str.c
@@ -1,11 +1,14 @@
-/* $RCSfile: str.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* str.c,v1.1.1.11994/09/10 06:27:33
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: str.c,v $
+ * str.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:33 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/str.h b/gnu/usr.bin/perl/perl/str.h
index 7eb4b6971717..650bb690ab8c 100644
--- a/gnu/usr.bin/perl/perl/str.h
+++ b/gnu/usr.bin/perl/perl/str.h
@@ -1,11 +1,14 @@
-/* $RCSfile: str.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:39 $
+/* str.h,v1.1.1.11994/09/10 06:27:35
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: str.h,v $
+ * str.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:39 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/t/Op.dbmx.db b/gnu/usr.bin/perl/perl/t/Op.dbmx.db
new file mode 100644
index 000000000000..33a09bba6d1c
--- /dev/null
+++ b/gnu/usr.bin/perl/perl/t/Op.dbmx.db
Binary files differ
diff --git a/gnu/usr.bin/perl/perl/t/TEST b/gnu/usr.bin/perl/perl/t/TEST
index 957a868c5cdd..e21749daaf22 100755
--- a/gnu/usr.bin/perl/perl/t/TEST
+++ b/gnu/usr.bin/perl/perl/t/TEST
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: TEST,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:01 $
+# TEST,v1.1.1.11994/09/10 06:27:38
# This is written in a peculiar style, since we're trying to avoid
# most of the constructs we'll be testing for.
diff --git a/gnu/usr.bin/perl/perl/t/base/cond.t b/gnu/usr.bin/perl/perl/t/base/cond.t
index 7d49f4e9b591..6f867883ba1c 100755
--- a/gnu/usr.bin/perl/perl/t/base/cond.t
+++ b/gnu/usr.bin/perl/perl/t/base/cond.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/base/cond.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/base/cond.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
# make sure conditional operators work
diff --git a/gnu/usr.bin/perl/perl/t/base/if.t b/gnu/usr.bin/perl/perl/t/base/if.t
index 2a9b82c77e7d..1e7fb1e9b092 100755
--- a/gnu/usr.bin/perl/perl/t/base/if.t
+++ b/gnu/usr.bin/perl/perl/t/base/if.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/base/if.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/base/if.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..2\n";
diff --git a/gnu/usr.bin/perl/perl/t/base/lex.t b/gnu/usr.bin/perl/perl/t/base/lex.t
index cd6321d9f081..44324526156e 100755
--- a/gnu/usr.bin/perl/perl/t/base/lex.t
+++ b/gnu/usr.bin/perl/perl/t/base/lex.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/base/lex.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/base/lex.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..18\n";
diff --git a/gnu/usr.bin/perl/perl/t/base/pat.t b/gnu/usr.bin/perl/perl/t/base/pat.t
index 2c8d9a9f2b85..b80dccbf7238 100755
--- a/gnu/usr.bin/perl/perl/t/base/pat.t
+++ b/gnu/usr.bin/perl/perl/t/base/pat.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/base/pat.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/base/pat.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..2\n";
diff --git a/gnu/usr.bin/perl/perl/t/base/term.t b/gnu/usr.bin/perl/perl/t/base/term.t
index c049c5872364..a28f11c27cb9 100755
--- a/gnu/usr.bin/perl/perl/t/base/term.t
+++ b/gnu/usr.bin/perl/perl/t/base/term.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/base/term.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/base/term.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..6\n";
diff --git a/gnu/usr.bin/perl/perl/t/cmd/elsif.t b/gnu/usr.bin/perl/perl/t/cmd/elsif.t
index 0e3457f6ad1f..7b4609a2e157 100755
--- a/gnu/usr.bin/perl/perl/t/cmd/elsif.t
+++ b/gnu/usr.bin/perl/perl/t/cmd/elsif.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/cmd/elsif.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/cmd/elsif.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
sub foo {
if ($_[0] == 1) {
diff --git a/gnu/usr.bin/perl/perl/t/cmd/for.t b/gnu/usr.bin/perl/perl/t/cmd/for.t
index 4a0c9226bae8..acdcb9e8e9af 100755
--- a/gnu/usr.bin/perl/perl/t/cmd/for.t
+++ b/gnu/usr.bin/perl/perl/t/cmd/for.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/cmd/for.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/cmd/for.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..7\n";
diff --git a/gnu/usr.bin/perl/perl/t/cmd/mod.t b/gnu/usr.bin/perl/perl/t/cmd/mod.t
index eeb44d97b5d8..7c906ab638c1 100755
--- a/gnu/usr.bin/perl/perl/t/cmd/mod.t
+++ b/gnu/usr.bin/perl/perl/t/cmd/mod.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/cmd/mod.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/cmd/mod.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..7\n";
diff --git a/gnu/usr.bin/perl/perl/t/cmd/subval.t b/gnu/usr.bin/perl/perl/t/cmd/subval.t
index f7f411b34ab1..39a646e24ede 100755
--- a/gnu/usr.bin/perl/perl/t/cmd/subval.t
+++ b/gnu/usr.bin/perl/perl/t/cmd/subval.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: subval.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:05 $
+# subval.t,v1.1.1.11994/09/10 06:27:39
sub foo1 {
'true1';
diff --git a/gnu/usr.bin/perl/perl/t/cmd/switch.t b/gnu/usr.bin/perl/perl/t/cmd/switch.t
index d0d4c932ad0d..1fcc77cee418 100755
--- a/gnu/usr.bin/perl/perl/t/cmd/switch.t
+++ b/gnu/usr.bin/perl/perl/t/cmd/switch.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/cmd/switch.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/cmd/switch.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..18\n";
diff --git a/gnu/usr.bin/perl/perl/t/cmd/while.t b/gnu/usr.bin/perl/perl/t/cmd/while.t
index 006e251a9d2e..c094e1e0f479 100755
--- a/gnu/usr.bin/perl/perl/t/cmd/while.t
+++ b/gnu/usr.bin/perl/perl/t/cmd/while.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/cmd/while.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/cmd/while.t,v 1.1.1.1 1994/09/10 06:27:39 gclarkii Exp
print "1..10\n";
diff --git a/gnu/usr.bin/perl/perl/t/comp/cmdopt.t b/gnu/usr.bin/perl/perl/t/comp/cmdopt.t
index 3c47130602ca..7f64a9957764 100755
--- a/gnu/usr.bin/perl/perl/t/comp/cmdopt.t
+++ b/gnu/usr.bin/perl/perl/t/comp/cmdopt.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/comp/cmdopt.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/comp/cmdopt.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..40\n";
diff --git a/gnu/usr.bin/perl/perl/t/comp/cpp.t b/gnu/usr.bin/perl/perl/t/comp/cpp.t
index 8cceb73ca8a0..10fb5ac84672 100755
--- a/gnu/usr.bin/perl/perl/t/comp/cpp.t
+++ b/gnu/usr.bin/perl/perl/t/comp/cpp.t
@@ -1,6 +1,6 @@
#!./perl -P
-# $RCSfile: cpp.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:06 $
+# cpp.t,v1.1.1.11994/09/10 06:27:40
open(CONFIG,"../config.sh") || die;
while (<CONFIG>) {
diff --git a/gnu/usr.bin/perl/perl/t/comp/decl.t b/gnu/usr.bin/perl/perl/t/comp/decl.t
index f1c84c2190ce..fb84a5fd26b3 100755
--- a/gnu/usr.bin/perl/perl/t/comp/decl.t
+++ b/gnu/usr.bin/perl/perl/t/comp/decl.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/comp/decl.t,v 1.1.1.1 1993/08/23 21:30:07 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/comp/decl.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
# check to see if subroutine declarations work everwhere
diff --git a/gnu/usr.bin/perl/perl/t/comp/multiline.t b/gnu/usr.bin/perl/perl/t/comp/multiline.t
index 78df482d3e7c..5634b115a3ef 100755
--- a/gnu/usr.bin/perl/perl/t/comp/multiline.t
+++ b/gnu/usr.bin/perl/perl/t/comp/multiline.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/comp/multiline.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/comp/multiline.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..5\n";
diff --git a/gnu/usr.bin/perl/perl/t/comp/script.t b/gnu/usr.bin/perl/perl/t/comp/script.t
index 9dcf90195856..867683347977 100755
--- a/gnu/usr.bin/perl/perl/t/comp/script.t
+++ b/gnu/usr.bin/perl/perl/t/comp/script.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/comp/script.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/comp/script.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/t/comp/term.t b/gnu/usr.bin/perl/perl/t/comp/term.t
index 70b23fd8a6ae..0d21e044b309 100755
--- a/gnu/usr.bin/perl/perl/t/comp/term.t
+++ b/gnu/usr.bin/perl/perl/t/comp/term.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/comp/term.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/comp/term.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
# tests that aren't important enough for base.term
diff --git a/gnu/usr.bin/perl/perl/t/io/argv.t b/gnu/usr.bin/perl/perl/t/io/argv.t
index 99c593620eee..9bf8fa4d479e 100755
--- a/gnu/usr.bin/perl/perl/t/io/argv.t
+++ b/gnu/usr.bin/perl/perl/t/io/argv.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/io/argv.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/io/argv.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..5\n";
diff --git a/gnu/usr.bin/perl/perl/t/io/dup.t b/gnu/usr.bin/perl/perl/t/io/dup.t
index 8d11eca79973..774956433e16 100755
--- a/gnu/usr.bin/perl/perl/t/io/dup.t
+++ b/gnu/usr.bin/perl/perl/t/io/dup.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/io/dup.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/io/dup.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..6\n";
diff --git a/gnu/usr.bin/perl/perl/t/io/fs.t b/gnu/usr.bin/perl/perl/t/io/fs.t
index 1d95cdc3530c..385d4e78142d 100755
--- a/gnu/usr.bin/perl/perl/t/io/fs.t
+++ b/gnu/usr.bin/perl/perl/t/io/fs.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: fs.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:05 $
+# fs.t,v1.1.1.11994/09/10 06:27:40
print "1..22\n";
diff --git a/gnu/usr.bin/perl/perl/t/io/inplace.t b/gnu/usr.bin/perl/perl/t/io/inplace.t
index b22afdaa4b98..1e21facf99a0 100755
--- a/gnu/usr.bin/perl/perl/t/io/inplace.t
+++ b/gnu/usr.bin/perl/perl/t/io/inplace.t
@@ -2,7 +2,7 @@
$^I = '.bak';
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/io/inplace.t,v 1.1.1.1 1993/08/23 21:30:05 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/io/inplace.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..2\n";
diff --git a/gnu/usr.bin/perl/perl/t/io/pipe.t b/gnu/usr.bin/perl/perl/t/io/pipe.t
index 791a9c715f85..492562072c11 100755
--- a/gnu/usr.bin/perl/perl/t/io/pipe.t
+++ b/gnu/usr.bin/perl/perl/t/io/pipe.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/io/pipe.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/io/pipe.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
$| = 1;
print "1..8\n";
diff --git a/gnu/usr.bin/perl/perl/t/io/print.t b/gnu/usr.bin/perl/perl/t/io/print.t
index 11854427410b..5a4d4ab00377 100755
--- a/gnu/usr.bin/perl/perl/t/io/print.t
+++ b/gnu/usr.bin/perl/perl/t/io/print.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/io/print.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/io/print.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..16\n";
diff --git a/gnu/usr.bin/perl/perl/t/io/tell.t b/gnu/usr.bin/perl/perl/t/io/tell.t
index 27e69a0fd7ee..101853686847 100755
--- a/gnu/usr.bin/perl/perl/t/io/tell.t
+++ b/gnu/usr.bin/perl/perl/t/io/tell.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/io/tell.t,v 1.1.1.1 1993/08/23 21:30:06 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/io/tell.t,v 1.1.1.1 1994/09/10 06:27:40 gclarkii Exp
print "1..13\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/append.t b/gnu/usr.bin/perl/perl/t/op/append.t
index 92c6f48e80c4..cdf4a8e2ef6f 100755
--- a/gnu/usr.bin/perl/perl/t/op/append.t
+++ b/gnu/usr.bin/perl/perl/t/op/append.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/append.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/append.t,v 1.1.1.1 1994/09/10 06:27:41 gclarkii Exp
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/array.t b/gnu/usr.bin/perl/perl/t/op/array.t
index 39e05e3fbbb4..1b6606997fed 100755
--- a/gnu/usr.bin/perl/perl/t/op/array.t
+++ b/gnu/usr.bin/perl/perl/t/op/array.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/array.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/array.t,v 1.1.1.1 1994/09/10 06:27:41 gclarkii Exp
print "1..36\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/auto.t b/gnu/usr.bin/perl/perl/t/op/auto.t
index 5301f934d8ed..0b5b8729a60e 100755
--- a/gnu/usr.bin/perl/perl/t/op/auto.t
+++ b/gnu/usr.bin/perl/perl/t/op/auto.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/auto.t,v 1.1.1.1 1993/08/23 21:30:01 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/auto.t,v 1.1.1.1 1994/09/10 06:27:41 gclarkii Exp
print "1..34\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/chop.t b/gnu/usr.bin/perl/perl/t/op/chop.t
index d691d734105b..39175b3b295a 100755
--- a/gnu/usr.bin/perl/perl/t/op/chop.t
+++ b/gnu/usr.bin/perl/perl/t/op/chop.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/chop.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/chop.t,v 1.1.1.1 1994/09/10 06:27:41 gclarkii Exp
print "1..4\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/cond.t b/gnu/usr.bin/perl/perl/t/op/cond.t
index 054a5ff7f0d7..22638b2750b1 100755
--- a/gnu/usr.bin/perl/perl/t/op/cond.t
+++ b/gnu/usr.bin/perl/perl/t/op/cond.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/cond.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/cond.t,v 1.1.1.1 1994/09/10 06:27:41 gclarkii Exp
print "1..4\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/dbm.t b/gnu/usr.bin/perl/perl/t/op/dbm.t
index 23d4d98c9412..0ba20372fb7a 100755
--- a/gnu/usr.bin/perl/perl/t/op/dbm.t
+++ b/gnu/usr.bin/perl/perl/t/op/dbm.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: dbm.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:02 $
+# dbm.t,v1.1.1.11994/09/10 06:27:41
if (!-r '/usr/include/dbm.h' && !-r '/usr/include/ndbm.h'
&& !-r '/usr/include/rpcsvc/dbm.h') {
diff --git a/gnu/usr.bin/perl/perl/t/op/delete.t b/gnu/usr.bin/perl/perl/t/op/delete.t
index e4e1fea10658..c8781529ef11 100755
--- a/gnu/usr.bin/perl/perl/t/op/delete.t
+++ b/gnu/usr.bin/perl/perl/t/op/delete.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/delete.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/delete.t,v 1.1.1.1 1994/09/10 06:27:41 gclarkii Exp
print "1..6\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/do.t b/gnu/usr.bin/perl/perl/t/op/do.t
index 370012c129b1..98a4243f9b04 100755
--- a/gnu/usr.bin/perl/perl/t/op/do.t
+++ b/gnu/usr.bin/perl/perl/t/op/do.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/do.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/do.t,v 1.1.1.1 1994/09/10 06:27:41 gclarkii Exp
sub foo1
{
diff --git a/gnu/usr.bin/perl/perl/t/op/each.t b/gnu/usr.bin/perl/perl/t/op/each.t
index 532d1b01f3f4..c3b985b77b72 100755
--- a/gnu/usr.bin/perl/perl/t/op/each.t
+++ b/gnu/usr.bin/perl/perl/t/op/each.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/each.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/each.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/eval.t b/gnu/usr.bin/perl/perl/t/op/eval.t
index b21b44d8354c..0c803d58e978 100755
--- a/gnu/usr.bin/perl/perl/t/op/eval.t
+++ b/gnu/usr.bin/perl/perl/t/op/eval.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: eval.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:02 $
+# eval.t,v1.1.1.11994/09/10 06:27:42
print "1..16\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/exec.t b/gnu/usr.bin/perl/perl/t/op/exec.t
index 69909f740790..7f50086c7785 100755
--- a/gnu/usr.bin/perl/perl/t/op/exec.t
+++ b/gnu/usr.bin/perl/perl/t/op/exec.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/exec.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/exec.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
$| = 1; # flush stdout
print "1..8\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/exp.t b/gnu/usr.bin/perl/perl/t/op/exp.t
index 2195e54067d6..699d6c498711 100755
--- a/gnu/usr.bin/perl/perl/t/op/exp.t
+++ b/gnu/usr.bin/perl/perl/t/op/exp.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/exp.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/exp.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..6\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/flip.t b/gnu/usr.bin/perl/perl/t/op/flip.t
index 74ba5085ac5f..b38194105fd5 100755
--- a/gnu/usr.bin/perl/perl/t/op/flip.t
+++ b/gnu/usr.bin/perl/perl/t/op/flip.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/flip.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/flip.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..8\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/fork.t b/gnu/usr.bin/perl/perl/t/op/fork.t
index 10b54a2a2c5b..3b102d580326 100755
--- a/gnu/usr.bin/perl/perl/t/op/fork.t
+++ b/gnu/usr.bin/perl/perl/t/op/fork.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/fork.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/fork.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
$| = 1;
print "1..2\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/glob.t b/gnu/usr.bin/perl/perl/t/op/glob.t
index 68b0844cad74..28e82cc4db67 100755
--- a/gnu/usr.bin/perl/perl/t/op/glob.t
+++ b/gnu/usr.bin/perl/perl/t/op/glob.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/glob.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/glob.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..4\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/goto.t b/gnu/usr.bin/perl/perl/t/op/goto.t
index 44ef343201e4..49e80938b21c 100755
--- a/gnu/usr.bin/perl/perl/t/op/goto.t
+++ b/gnu/usr.bin/perl/perl/t/op/goto.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: goto.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:03 $
+# goto.t,v1.1.1.11994/09/10 06:27:42
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/index.t b/gnu/usr.bin/perl/perl/t/op/index.t
index 769314b5e37f..c38215c8dad6 100755
--- a/gnu/usr.bin/perl/perl/t/op/index.t
+++ b/gnu/usr.bin/perl/perl/t/op/index.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/index.t,v 1.1.1.1 1993/08/23 21:30:01 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/index.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..20\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/int.t b/gnu/usr.bin/perl/perl/t/op/int.t
index 09434b8675a6..1bee49605b50 100755
--- a/gnu/usr.bin/perl/perl/t/op/int.t
+++ b/gnu/usr.bin/perl/perl/t/op/int.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/int.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/int.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..4\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/join.t b/gnu/usr.bin/perl/perl/t/op/join.t
index a6678e979011..a61f83ca3c6f 100755
--- a/gnu/usr.bin/perl/perl/t/op/join.t
+++ b/gnu/usr.bin/perl/perl/t/op/join.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/join.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/join.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/list.t b/gnu/usr.bin/perl/perl/t/op/list.t
index 52b2347bfd30..ae7fdd5c8547 100755
--- a/gnu/usr.bin/perl/perl/t/op/list.t
+++ b/gnu/usr.bin/perl/perl/t/op/list.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/list.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/list.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..27\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/local.t b/gnu/usr.bin/perl/perl/t/op/local.t
index 67396e7cddeb..2572f7fb60fe 100755
--- a/gnu/usr.bin/perl/perl/t/op/local.t
+++ b/gnu/usr.bin/perl/perl/t/op/local.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/local.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/local.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
print "1..20\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/magic.t b/gnu/usr.bin/perl/perl/t/op/magic.t
index 1f47a9936ace..adfc79bcfb28 100755
--- a/gnu/usr.bin/perl/perl/t/op/magic.t
+++ b/gnu/usr.bin/perl/perl/t/op/magic.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/magic.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/magic.t,v 1.1.1.1 1994/09/10 06:27:42 gclarkii Exp
$| = 1; # command buffering
diff --git a/gnu/usr.bin/perl/perl/t/op/mkdir.t b/gnu/usr.bin/perl/perl/t/op/mkdir.t
index 0290ed4e5bbc..fcafe3324d3f 100755
--- a/gnu/usr.bin/perl/perl/t/op/mkdir.t
+++ b/gnu/usr.bin/perl/perl/t/op/mkdir.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/mkdir.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/mkdir.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..7\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/oct.t b/gnu/usr.bin/perl/perl/t/op/oct.t
index 9322cf0e73e1..5f898887ec8c 100755
--- a/gnu/usr.bin/perl/perl/t/op/oct.t
+++ b/gnu/usr.bin/perl/perl/t/op/oct.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/oct.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/oct.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/ord.t b/gnu/usr.bin/perl/perl/t/op/ord.t
index 9d319882d4fe..6e92ce5de575 100755
--- a/gnu/usr.bin/perl/perl/t/op/ord.t
+++ b/gnu/usr.bin/perl/perl/t/op/ord.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/ord.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/ord.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..2\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/pack.t b/gnu/usr.bin/perl/perl/t/op/pack.t
index 1dfaddf370ef..1dcd519dbabf 100755
--- a/gnu/usr.bin/perl/perl/t/op/pack.t
+++ b/gnu/usr.bin/perl/perl/t/op/pack.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/pack.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/pack.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/pat.t b/gnu/usr.bin/perl/perl/t/op/pat.t
index ce9f35c6ee66..fc5ce2ceb07d 100755
--- a/gnu/usr.bin/perl/perl/t/op/pat.t
+++ b/gnu/usr.bin/perl/perl/t/op/pat.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: pat.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:01 $
+# pat.t,v1.1.1.11994/09/10 06:27:43
print "1..51\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/push.t b/gnu/usr.bin/perl/perl/t/op/push.t
index 3d738acfbda3..17116d8baeb9 100755
--- a/gnu/usr.bin/perl/perl/t/op/push.t
+++ b/gnu/usr.bin/perl/perl/t/op/push.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/push.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/push.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
@tests = split(/\n/, <<EOF);
0 3, 0 1 2, 3 4 5 6 7
diff --git a/gnu/usr.bin/perl/perl/t/op/range.t b/gnu/usr.bin/perl/perl/t/op/range.t
index 6214f9527b99..9e203022b07b 100755
--- a/gnu/usr.bin/perl/perl/t/op/range.t
+++ b/gnu/usr.bin/perl/perl/t/op/range.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/range.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/range.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..8\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/read.t b/gnu/usr.bin/perl/perl/t/op/read.t
index 4151e5c6a674..3207e42b4c40 100755
--- a/gnu/usr.bin/perl/perl/t/op/read.t
+++ b/gnu/usr.bin/perl/perl/t/op/read.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/read.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/read.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..4\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/regexp.t b/gnu/usr.bin/perl/perl/t/op/regexp.t
index 58f6666e6949..7fc17b39f1ea 100755
--- a/gnu/usr.bin/perl/perl/t/op/regexp.t
+++ b/gnu/usr.bin/perl/perl/t/op/regexp.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: regexp.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:03 $
+# regexp.t,v1.1.1.11994/09/10 06:27:43
open(TESTS,'op/re_tests') || open(TESTS,'t/op/re_tests')
|| die "Can't open re_tests";
diff --git a/gnu/usr.bin/perl/perl/t/op/repeat.t b/gnu/usr.bin/perl/perl/t/op/repeat.t
index 68c61fc6a05e..d819eea8b12f 100755
--- a/gnu/usr.bin/perl/perl/t/op/repeat.t
+++ b/gnu/usr.bin/perl/perl/t/op/repeat.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/repeat.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/repeat.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..19\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/s.t b/gnu/usr.bin/perl/perl/t/op/s.t
index 59300209cd39..51aa8f39a8a5 100755
--- a/gnu/usr.bin/perl/perl/t/op/s.t
+++ b/gnu/usr.bin/perl/perl/t/op/s.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/s.t,v 1.1.1.1 1993/08/23 21:30:01 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/s.t,v 1.1.1.1 1994/09/10 06:27:43 gclarkii Exp
print "1..51\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/sleep.t b/gnu/usr.bin/perl/perl/t/op/sleep.t
index 81113712d343..bf77a25d7033 100755
--- a/gnu/usr.bin/perl/perl/t/op/sleep.t
+++ b/gnu/usr.bin/perl/perl/t/op/sleep.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/sleep.t,v 1.1.1.1 1993/08/23 21:30:04 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/sleep.t,v 1.1.1.1 1994/09/10 06:27:45 gclarkii Exp
print "1..1\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/sort.t b/gnu/usr.bin/perl/perl/t/op/sort.t
index 4692ee4422fb..33797653c374 100755
--- a/gnu/usr.bin/perl/perl/t/op/sort.t
+++ b/gnu/usr.bin/perl/perl/t/op/sort.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: sort.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:02 $
+# sort.t,v1.1.1.11994/09/10 06:27:46
print "1..10\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/split.t b/gnu/usr.bin/perl/perl/t/op/split.t
index 63bf3c7c76da..435cccdef62e 100755
--- a/gnu/usr.bin/perl/perl/t/op/split.t
+++ b/gnu/usr.bin/perl/perl/t/op/split.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/split.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/split.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..12\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/sprintf.t b/gnu/usr.bin/perl/perl/t/op/sprintf.t
index cdb4af5a2244..df89b9fffc49 100755
--- a/gnu/usr.bin/perl/perl/t/op/sprintf.t
+++ b/gnu/usr.bin/perl/perl/t/op/sprintf.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/sprintf.t,v 1.1.1.1 1993/08/23 21:30:01 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/sprintf.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..1\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/stat.t b/gnu/usr.bin/perl/perl/t/op/stat.t
index a5db14fd124e..5af1be8cfd40 100755
--- a/gnu/usr.bin/perl/perl/t/op/stat.t
+++ b/gnu/usr.bin/perl/perl/t/op/stat.t
@@ -1,6 +1,6 @@
#!./perl
-# $RCSfile: stat.t,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:01 $
+# stat.t,v1.1.1.11994/09/10 06:27:46
print "1..56\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/study.t b/gnu/usr.bin/perl/perl/t/op/study.t
index a0fdc4cd273c..16bedbb12b47 100755
--- a/gnu/usr.bin/perl/perl/t/op/study.t
+++ b/gnu/usr.bin/perl/perl/t/op/study.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/study.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/study.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..24\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/substr.t b/gnu/usr.bin/perl/perl/t/op/substr.t
index 09f312f83762..9448f66bcd00 100755
--- a/gnu/usr.bin/perl/perl/t/op/substr.t
+++ b/gnu/usr.bin/perl/perl/t/op/substr.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/substr.t,v 1.1.1.1 1993/08/23 21:30:01 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/substr.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..22\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/time.t b/gnu/usr.bin/perl/perl/t/op/time.t
index f8e5545f7b41..13676730df12 100755
--- a/gnu/usr.bin/perl/perl/t/op/time.t
+++ b/gnu/usr.bin/perl/perl/t/op/time.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/time.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/time.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..5\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/undef.t b/gnu/usr.bin/perl/perl/t/op/undef.t
index b4827db0c547..49d331731f08 100755
--- a/gnu/usr.bin/perl/perl/t/op/undef.t
+++ b/gnu/usr.bin/perl/perl/t/op/undef.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/undef.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/undef.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..21\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/unshift.t b/gnu/usr.bin/perl/perl/t/op/unshift.t
index 53d73883822b..1ceb175f9a73 100755
--- a/gnu/usr.bin/perl/perl/t/op/unshift.t
+++ b/gnu/usr.bin/perl/perl/t/op/unshift.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/unshift.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/unshift.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..2\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/vec.t b/gnu/usr.bin/perl/perl/t/op/vec.t
index 51344769b6cf..8e33cc8d89a2 100755
--- a/gnu/usr.bin/perl/perl/t/op/vec.t
+++ b/gnu/usr.bin/perl/perl/t/op/vec.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/vec.t,v 1.1.1.1 1993/08/23 21:30:03 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/vec.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..13\n";
diff --git a/gnu/usr.bin/perl/perl/t/op/write.t b/gnu/usr.bin/perl/perl/t/op/write.t
index d17f1951bb76..009fc06c00e2 100755
--- a/gnu/usr.bin/perl/perl/t/op/write.t
+++ b/gnu/usr.bin/perl/perl/t/op/write.t
@@ -1,6 +1,6 @@
#!./perl
-# $Header: /home/cvs/386BSD/ports/lang/perl/t/op/write.t,v 1.1.1.1 1993/08/23 21:30:02 nate Exp $
+# /home/ncvs/src/gnu/usr.bin/perl/perl/t/op/write.t,v 1.1.1.1 1994/09/10 06:27:46 gclarkii Exp
print "1..3\n";
diff --git a/gnu/usr.bin/perl/perl/tdoio.c b/gnu/usr.bin/perl/perl/tdoio.c
index 5dd8065b4f95..ee3505dad65b 100644
--- a/gnu/usr.bin/perl/perl/tdoio.c
+++ b/gnu/usr.bin/perl/perl/tdoio.c
@@ -1,11 +1,14 @@
-/* $RCSfile: doio.c,v $$Revision: 1.2 $$Date: 1994/03/09 22:24:27 $
+/* tdoio.c,v1.1.1.11994/09/10 06:27:36
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: doio.c,v $
+ * tdoio.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:36 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.2 1994/03/09 22:24:27 ache
* (cast) added for last argument of semctl
*
diff --git a/gnu/usr.bin/perl/perl/toke.c b/gnu/usr.bin/perl/perl/toke.c
index 34603cedf31b..1bcd78f1f58e 100644
--- a/gnu/usr.bin/perl/perl/toke.c
+++ b/gnu/usr.bin/perl/perl/toke.c
@@ -1,11 +1,14 @@
-/* $RCSfile: toke.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:40 $
+/* toke.c,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: toke.c,v $
+ * toke.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:40 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/usersub.c b/gnu/usr.bin/perl/perl/usersub.c
index d0ee9525ef99..14b260bfbc21 100644
--- a/gnu/usr.bin/perl/perl/usersub.c
+++ b/gnu/usr.bin/perl/perl/usersub.c
@@ -1,10 +1,13 @@
-/* $RCSfile: usersub.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:40 $
+/* usersub.c,v1.1.1.11994/09/10 06:27:34
*
* This file contains stubs for routines that the user may define to
* set up glue routines for C libraries or to decrypt encrypted scripts
* for execution.
*
- * $Log: usersub.c,v $
+ * usersub.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:40 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/usub/bsdcurses.mus b/gnu/usr.bin/perl/perl/usub/bsdcurses.mus
index 1a1f11bcb21f..e6a83d593629 100644
--- a/gnu/usr.bin/perl/perl/usub/bsdcurses.mus
+++ b/gnu/usr.bin/perl/perl/usub/bsdcurses.mus
@@ -1,6 +1,9 @@
-/* $RCSfile: bsdcurses.mus,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:07 $
+/* bsdcurses.mus,v1.1.1.11994/09/10 06:27:37
*
- * $Log: bsdcurses.mus,v $
+ * bsdcurses.mus,v
+# Revision 1.1.1.1 1994/09/10 06:27:37 gclarkii
+# Initial import of Perl 4.046 bmaked
+#
# Revision 1.1.1.1 1993/08/23 21:30:07 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/perl/usub/curses.mus b/gnu/usr.bin/perl/perl/usub/curses.mus
index f305bf5920f3..bccae87bba15 100644
--- a/gnu/usr.bin/perl/perl/usub/curses.mus
+++ b/gnu/usr.bin/perl/perl/usub/curses.mus
@@ -1,6 +1,9 @@
-/* $RCSfile: curses.mus,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:07 $
+/* curses.mus,v1.1.1.11994/09/10 06:27:37
*
- * $Log: curses.mus,v $
+ * curses.mus,v
+# Revision 1.1.1.1 1994/09/10 06:27:37 gclarkii
+# Initial import of Perl 4.046 bmaked
+#
# Revision 1.1.1.1 1993/08/23 21:30:07 nate
# PERL!
#
diff --git a/gnu/usr.bin/perl/perl/usub/usersub.c b/gnu/usr.bin/perl/perl/usub/usersub.c
index ca9d2ba49b38..71c55c97955e 100644
--- a/gnu/usr.bin/perl/perl/usub/usersub.c
+++ b/gnu/usr.bin/perl/perl/usub/usersub.c
@@ -1,6 +1,9 @@
-/* $RCSfile: usersub.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:07 $
+/* usersub.c,v1.1.1.11994/09/10 06:27:37
+ *
+ * usersub.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:37 gclarkii
+ * Initial import of Perl 4.046 bmaked
*
- * $Log: usersub.c,v $
* Revision 1.1.1.1 1993/08/23 21:30:07 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/util.c b/gnu/usr.bin/perl/perl/util.c
index 574898357382..faff9a4fc14b 100644
--- a/gnu/usr.bin/perl/perl/util.c
+++ b/gnu/usr.bin/perl/perl/util.c
@@ -1,11 +1,14 @@
-/* $RCSfile: util.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:40 $
+/* util.c,v1.1.1.11994/09/10 06:27:34
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: util.c,v $
+ * util.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:40 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/perl/util.h b/gnu/usr.bin/perl/perl/util.h
index ff64f8587806..70d5f763da21 100644
--- a/gnu/usr.bin/perl/perl/util.h
+++ b/gnu/usr.bin/perl/perl/util.h
@@ -1,11 +1,14 @@
-/* $RCSfile: util.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:40 $
+/* util.h,v1.1.1.11994/09/10 06:27:35
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: util.h,v $
+ * util.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:35 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:29:40 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/EXTERN.h b/gnu/usr.bin/perl/x2p/EXTERN.h
index f3048edbc021..156804472b19 100644
--- a/gnu/usr.bin/perl/x2p/EXTERN.h
+++ b/gnu/usr.bin/perl/x2p/EXTERN.h
@@ -1,11 +1,14 @@
-/* $RCSfile: EXTERN.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:11 $
+/* EXTERN.h,v1.1.1.11994/09/10 06:27:54
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: EXTERN.h,v $
+ * EXTERN.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:11 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/INTERN.h b/gnu/usr.bin/perl/x2p/INTERN.h
index e1967d2630b0..61d262b21d4b 100644
--- a/gnu/usr.bin/perl/x2p/INTERN.h
+++ b/gnu/usr.bin/perl/x2p/INTERN.h
@@ -1,11 +1,14 @@
-/* $RCSfile: INTERN.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:11 $
+/* INTERN.h,v1.1.1.11994/09/10 06:27:54
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: INTERN.h,v $
+ * INTERN.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:11 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/a2p.1 b/gnu/usr.bin/perl/x2p/a2p.1
index 58d8c077fafd..2151f44d2bc6 100644
--- a/gnu/usr.bin/perl/x2p/a2p.1
+++ b/gnu/usr.bin/perl/x2p/a2p.1
@@ -1,7 +1,10 @@
.rn '' }`
-''' $Header: /home/cvs/386BSD/ports/lang/perl/x2p/a2p.man,v 1.1.1.1 1993/08/23 21:30:10 nate Exp $
+''' /home/ncvs/src/gnu/usr.bin/perl/x2p/a2p.1,v 1.1.1.1 1994/09/10 06:27:55 gclarkii Exp
'''
-''' $Log: a2p.man,v $
+''' a2p.1,v
+.\" Revision 1.1.1.1 1994/09/10 06:27:55 gclarkii
+.\" Initial import of Perl 4.046 bmaked
+.\"
.\" Revision 1.1.1.1 1993/08/23 21:30:10 nate
.\" PERL!
.\"
diff --git a/gnu/usr.bin/perl/x2p/a2p.c b/gnu/usr.bin/perl/x2p/a2p.c
index c44163462632..bdc11a28f4dd 100644
--- a/gnu/usr.bin/perl/x2p/a2p.c
+++ b/gnu/usr.bin/perl/x2p/a2p.c
@@ -9,14 +9,17 @@ static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
#define YYRECOVERING (yyerrflag!=0)
#define YYPREFIX "yy"
#line 2 "a2p.y"
-/* $RCSfile: a2p.y,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:09 $
+/* a2p.c,v1.1.1.11994/09/10 06:27:55
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: a2p.y,v $
+ * a2p.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:55 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:09 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/a2p.h b/gnu/usr.bin/perl/x2p/a2p.h
index 7c6a66dde29c..c81a3982dfbd 100644
--- a/gnu/usr.bin/perl/x2p/a2p.h
+++ b/gnu/usr.bin/perl/x2p/a2p.h
@@ -1,11 +1,14 @@
-/* $RCSfile: a2p.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:09 $
+/* a2p.h,v1.1.1.11994/09/10 06:27:53
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: a2p.h,v $
+ * a2p.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:53 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:09 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/a2p.y b/gnu/usr.bin/perl/x2p/a2p.y
index bc86632dd417..8e9708e5ba30 100644
--- a/gnu/usr.bin/perl/x2p/a2p.y
+++ b/gnu/usr.bin/perl/x2p/a2p.y
@@ -1,12 +1,15 @@
%{
-/* $RCSfile: a2p.y,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:09 $
+/* a2p.y,v1.1.1.11994/09/10 06:27:53
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: a2p.y,v $
+ * a2p.y,v
+ * Revision 1.1.1.1 1994/09/10 06:27:53 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:09 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/a2py.c b/gnu/usr.bin/perl/x2p/a2py.c
index 1558f9954f2e..c81d6b6a153e 100644
--- a/gnu/usr.bin/perl/x2p/a2py.c
+++ b/gnu/usr.bin/perl/x2p/a2py.c
@@ -1,11 +1,14 @@
-/* $RCSfile: a2py.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+/* a2py.c,v1.1.1.11994/09/10 06:27:53
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: a2py.c,v $
+ * a2py.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:53 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:10 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/handy.h b/gnu/usr.bin/perl/x2p/handy.h
index 85a777c2e7fb..dd377ddda16c 100644
--- a/gnu/usr.bin/perl/x2p/handy.h
+++ b/gnu/usr.bin/perl/x2p/handy.h
@@ -1,11 +1,14 @@
-/* $RCSfile: handy.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+/* handy.h,v1.1.1.11994/09/10 06:27:54
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: handy.h,v $
+ * handy.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:10 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/hash.c b/gnu/usr.bin/perl/x2p/hash.c
index d525882f9acb..8fb907bd1086 100644
--- a/gnu/usr.bin/perl/x2p/hash.c
+++ b/gnu/usr.bin/perl/x2p/hash.c
@@ -1,11 +1,14 @@
-/* $RCSfile: hash.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+/* hash.c,v1.1.1.11994/09/10 06:27:54
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: hash.c,v $
+ * hash.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:10 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/hash.h b/gnu/usr.bin/perl/x2p/hash.h
index ae4ffaff0617..97bf38ee38d6 100644
--- a/gnu/usr.bin/perl/x2p/hash.h
+++ b/gnu/usr.bin/perl/x2p/hash.h
@@ -1,11 +1,14 @@
-/* $RCSfile: hash.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+/* hash.h,v1.1.1.11994/09/10 06:27:54
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: hash.h,v $
+ * hash.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:10 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/malloc.c b/gnu/usr.bin/perl/x2p/malloc.c
index dd43390d6dca..79d62352332e 100644
--- a/gnu/usr.bin/perl/x2p/malloc.c
+++ b/gnu/usr.bin/perl/x2p/malloc.c
@@ -1,6 +1,9 @@
-/* $RCSfile: malloc.c,v $$Revision: 1.2 $$Date: 1993/08/24 17:57:39 $
+/* malloc.c,v1.1.1.11994/09/10 06:27:54
+ *
+ * malloc.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
+ * Initial import of Perl 4.046 bmaked
*
- * $Log: malloc.c,v $
* Revision 1.2 1993/08/24 17:57:39 nate
* Fix for ALIGN macros in PERL that conflict with 4.4 macros
*
diff --git a/gnu/usr.bin/perl/x2p/s2p b/gnu/usr.bin/perl/x2p/s2p
index c110e5ef5720..8cc313be3909 100755
--- a/gnu/usr.bin/perl/x2p/s2p
+++ b/gnu/usr.bin/perl/x2p/s2p
@@ -5,9 +5,20 @@ eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
$bin = '/usr/bin';
-# $RCSfile: s2p,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:54 $
+# s2p,v1.21994/10/29 07:14:55
+#
+# s2p,v
+# Revision 1.2 1994/10/29 07:14:55 pst
+# Test test test! sigh!
+#
+# Perl's scripts are still trying to execute perl out of /usr/gnu/bin/perl.
+#
+# The hack Larry was using for h2ph.1 doesn't work with the new macros, so
+# make it a real man page.
+#
+# Also, we weren't building the .ph files, add them as an afterinstall rule
+# in the x2p subdirectory.
#
-# $Log: s2p,v $
# Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
# Initial import of Perl 4.046 bmaked
#
diff --git a/gnu/usr.bin/perl/x2p/s2p.1 b/gnu/usr.bin/perl/x2p/s2p.1
index ab74717833fc..4ca7df38bacd 100644
--- a/gnu/usr.bin/perl/x2p/s2p.1
+++ b/gnu/usr.bin/perl/x2p/s2p.1
@@ -1,7 +1,10 @@
.rn '' }`
-''' $RCSfile: s2p.man,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+''' s2p.1,v1.1.1.11994/09/10 06:27:53
'''
-''' $Log: s2p.man,v $
+''' s2p.1,v
+.\" Revision 1.1.1.1 1994/09/10 06:27:53 gclarkii
+.\" Initial import of Perl 4.046 bmaked
+.\"
.\" Revision 1.1.1.1 1993/08/23 21:30:10 nate
.\" PERL!
.\"
diff --git a/gnu/usr.bin/perl/x2p/str.c b/gnu/usr.bin/perl/x2p/str.c
index 04611946e250..bd245ff40c38 100644
--- a/gnu/usr.bin/perl/x2p/str.c
+++ b/gnu/usr.bin/perl/x2p/str.c
@@ -1,11 +1,14 @@
-/* $RCSfile: str.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:09 $
+/* str.c,v1.1.1.11994/09/10 06:27:54
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: str.c,v $
+ * str.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:54 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:09 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/str.h b/gnu/usr.bin/perl/x2p/str.h
index 765d9ea2113d..d2089aa74d22 100644
--- a/gnu/usr.bin/perl/x2p/str.h
+++ b/gnu/usr.bin/perl/x2p/str.h
@@ -1,11 +1,14 @@
-/* $RCSfile: str.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+/* str.h,v1.1.1.11994/09/10 06:27:55
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: str.h,v $
+ * str.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:55 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:10 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/util.c b/gnu/usr.bin/perl/x2p/util.c
index 4c5b078e4f9e..11f521afb754 100644
--- a/gnu/usr.bin/perl/x2p/util.c
+++ b/gnu/usr.bin/perl/x2p/util.c
@@ -1,11 +1,14 @@
-/* $RCSfile: util.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+/* util.c,v1.1.1.11994/09/10 06:27:55
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: util.c,v $
+ * util.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:55 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:10 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/util.h b/gnu/usr.bin/perl/x2p/util.h
index 15bf78e53f33..9ab97cdd968f 100644
--- a/gnu/usr.bin/perl/x2p/util.h
+++ b/gnu/usr.bin/perl/x2p/util.h
@@ -1,11 +1,14 @@
-/* $RCSfile: util.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:10 $
+/* util.h,v1.1.1.11994/09/10 06:27:55
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: util.h,v $
+ * util.h,v
+ * Revision 1.1.1.1 1994/09/10 06:27:55 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:10 nate
* PERL!
*
diff --git a/gnu/usr.bin/perl/x2p/walk.c b/gnu/usr.bin/perl/x2p/walk.c
index 4cc4a79eb07b..8a20d329e966 100644
--- a/gnu/usr.bin/perl/x2p/walk.c
+++ b/gnu/usr.bin/perl/x2p/walk.c
@@ -1,11 +1,14 @@
-/* $RCSfile: walk.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:30:11 $
+/* walk.c,v1.1.1.11994/09/10 06:27:55
*
* Copyright (c) 1991, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: walk.c,v $
+ * walk.c,v
+ * Revision 1.1.1.1 1994/09/10 06:27:55 gclarkii
+ * Initial import of Perl 4.046 bmaked
+ *
* Revision 1.1.1.1 1993/08/23 21:30:11 nate
* PERL!
*
diff --git a/gnu/usr.bin/ptx/texinfo.tex b/gnu/usr.bin/ptx/texinfo.tex
new file mode 100644
index 000000000000..ce11b7b828e0
--- /dev/null
+++ b/gnu/usr.bin/ptx/texinfo.tex
@@ -0,0 +1,4053 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc.
+
+%This texinfo.tex 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 texinfo.tex 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 texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+\def\texinfoversion{2.115}
+\message{Loading texinfo package [Version \texinfoversion]:}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ } % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }}
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+% Why was this kern here? It messes up equalizing space above and below
+% environments. --karl, 6may93
+%{\advance \baselineskip by -\singlespaceskip
+%\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % We do @comment here in case we are called inside an environment,
+ % such as @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+%Use \input\thisfile to avoid blank after \input, which may be an active
+%char (in which case the blank would become the \input argument).
+%The grouping keeps the value of \thisfile correct even when @include
+%is nested.
+\def\includezzz #1{\begingroup
+\def\thisfile{#1}\input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ \long\def\doignoretext##1\end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ % Similarly for index fonts (mostly for their use in
+ % smallexample)
+ \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont
+ \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont
+ \let\indsf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+%
+\def\set{\parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+}
+\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+ \ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}
+ \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex). But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\font\textrm=cmr12
+\font\texttt=cmtt12
+\else
+\font\textrm=cmr10 scaled \mainmagstep
+\font\texttt=cmtt10 scaled \mainmagstep
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\textbf=cmb10 scaled \mainmagstep
+\font\textit=cmti10 scaled \mainmagstep
+\font\textsl=cmsl10 scaled \mainmagstep
+\font\textsf=cmss10 scaled \mainmagstep
+\font\textsc=cmcsc10 scaled \mainmagstep
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\font\ninett=cmtt9
+\font\indrm=cmr9
+\font\indit=cmsl9
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\let\indsc=\indrm
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+\font\chapsc=cmcsc10 scaled\magstep3
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+\font\secsc=cmcsc10 scaled\magstep2
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad.
+% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+\font\ssecsc=cmcsc10 scaled \magstep1
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current. Plain TeX does, for example,
+% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need
+% to redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+ \resetmathfonts}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+ \resetmathfonts}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+ \resetmathfonts}
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
+ \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\font\shortcontrm=cmr12
+\font\shortcontbf=cmbx12
+\font\shortcontsl=cmsl12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \nohyphenation \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overful hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate an a dash.
+% -- rms.
+{
+\catcode`\-=\active
+\catcode`\_=\active
+\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex}
+% The following is used by \doprintindex to insure that long function names
+% wrap around. It is necessary for - and _ to be active before the index is
+% read from the file, as \entry parses the arguments long before \code is
+% ever called. -- mycroft
+\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder}
+}
+\def\realdash{-}
+\def\realunder{_}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ %{\parskip = 0in
+ %\par
+ %}%
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ %
+ % Make this a paragraph so we get the \parskip glue and wrapping,
+ % but leave it ragged-right.
+ \begingroup
+ \advance\leftskip by-\tableindent
+ \advance\hsize by\tableindent
+ \advance\rightskip by0pt plus1fil
+ \leavevmode\unhbox0\par
+ \endgroup
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \endgroup
+ \itemxneedsnegativevskipfalse
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}\ignorespaces%
+ \endgroup%
+ \itemxneedsnegativevskiptrue%
+ \fi
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\def\doind #1#2{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+ \tex
+ \dobreak \chapheadingskip {10000}
+ \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+ \catcode`\$=\other
+ \catcode`\~=\other
+ \indexbreaks
+ %
+ % The following don't help, since the chars were translated
+ % when the raw index was written, and their fonts were discarded
+ % due to \indexnofonts.
+ %\catcode`\"=\active
+ %\catcode`\^=\active
+ %\catcode`\_=\active
+ %\catcode`\|=\active
+ %\catcode`\<=\active
+ %\catcode`\>=\active
+ % %
+ \def\indexbackslash{\rawbackslashxx}
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+ \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent=2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ % The following is kluged to not output a line of dots in the index if
+ % there are no page numbers. The next person who breaks this will be
+ % cursed by a Unix daemon.
+ \def\tempa{{\rm }}%
+ \def\tempb{#2}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd\ \else%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \fi%
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXbook, page 416.
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage
+ =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \eject
+ %
+ % Now switch to the double-column output routine.
+ \output={\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it once.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +- <
+ % 1pt) as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+ \doublecolumnpagegoal
+}
+
+\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
+
+\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
+ \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
+ \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
+ \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+ \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+}
+\def\doublecolumnpagegoal{%
+ \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\doublecolumnout{%
+ \setbox5=\copy255
+ {\vbadness=10000 \doublecolumnsplit}
+ \ifvbox255
+ \setbox0=\vtop to\dimen@{\unvbox0}
+ \setbox2=\vtop to\dimen@{\unvbox2}
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
+ \else
+ \setbox0=\vbox{\unvbox5}
+ \ifvbox0
+ \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ {\vbadness=10000
+ \loop \global\setbox5=\copy0
+ \setbox1=\vsplit5 to\dimen@
+ \setbox3=\vsplit5 to\dimen@
+ \ifvbox5 \global\advance\dimen@ by1pt \repeat
+ \setbox0=\vbox to\dimen@{\unvbox1}
+ \setbox2=\vbox to\dimen@{\unvbox3}
+ \global\setbox\partialpage=\vbox{\pagesofar}
+ \doublecolumnpagegoal
+ }
+ \fi
+ \fi
+}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appenixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #2\enspace #1}%
+ }%
+ \bigskip
+ \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \ifnum \pageno>0
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{Table of Contents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{Short Contents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm Appendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in in \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+\def\tocentry#1#2{\begingroup
+ \hyphenpenalty = 10000
+ \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% To ending an @example-like environment, we first end the paragraph
+% (via \afterenvbreak's vertical glue), and then the group. That way we
+% keep the zero \parskip that the environments set -- \parskip glue
+% will be inserted at the beginning of the next paragraph in the
+% document, after the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}%
+
+% This macro is
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \rawbackslash % have \ input char produce \ char from current font
+ \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp. This is not used unless the @smallbook
+% command is given. Originally contributed by Pavel@xerox.
+%
+\def\smalllispx{\begingroup
+ \nonfillstart
+ \let\Esmalllisp = \nonfillfinish
+ \let\Esmallexample = \nonfillfinish
+ %
+ % Smaller interline space and fonts for small examples.
+ \baselineskip 10pt
+ \indexfonts \tt
+ \rawbackslash % output the \ character from the current font
+ \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushleft = \nonfillfinish
+ \gobble
+}
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble}
+
+% @quotation does normal linebreaking and narrows the margins.
+%
+\def\quotation{%
+\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\let\Equotation = \nonfillfinish
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\advance \rightskip by \lispnarrowing
+\exdentamount=\lispnarrowing
+\let\nonarrowing=\relax
+\fi}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active % 61 is `='
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+% This is used for \def{tp,vr}parsebody. It could probably be used for
+% some of the others, too, with some judicious conditionals.
+%
+\def\parsebodycommon#1#2#3{%
+ \begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument. Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name. That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any). That's what this does, putting the result in \tptemp.
+%
+\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}%
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+ \removeemptybraces#2\relax
+ #1{\tptemp}{#3}%
+}%
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+% at least some C++ text from working
+\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+% No printed node name was explicitly given.
+\ifx SETxref-automatic-section-title %
+% This line should make the actual chapter or section title appear inside
+% the square brackets. Use the real section title if we have it.
+\ifdim \wd1>0pt%
+% It is in another manual, so we don't have it.
+\def\printednodename{\ignorespaces #1} \else%
+% We know the real title if we have the xref values.
+\ifhavexrefs \def\printednodename{\refx{#1-title}}%
+% Otherwise just copy the Info node name.
+\else \def\printednodename{\ignorespaces #1} \fi%
+\fi\def\printednodename{#1-title}%
+\else% This line just uses the node name.
+\def\printednodename{\ignorespaces #1}%
+\fi% ends \ifx SETxref-automatic-section-title
+\fi% ends \ifdim \wd0
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names. Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss. Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thissection}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed.
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\setleading{15pt}
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+\else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+
+% These values for secheadingskip and subsecheadingskip are
+% experiments. RJC 7 Aug 1992
+\global\secheadingskip = 17pt plus 6pt minus 3pt
+\global\subsecheadingskip = 14pt plus 6pt minus 3pt
+
+\global\lispnarrowing = 0.3in
+\setleading{12pt}
+\advance\topskip by -1cm
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+% \lvvmode is equivalent in function to \leavevmode.
+% Using \leavevmode runs into trouble when written out to
+% an index file due to the expansion of \leavevmode into ``\unhbox
+% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
+% magic tricks with @.
+\def\lvvmode{\vbox to 0pt{}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/gnu/usr.bin/rcs/ci/ci.1 b/gnu/usr.bin/rcs/ci/ci.1
index 5736dc95a001..b21d575a132a 100644
--- a/gnu/usr.bin/rcs/ci/ci.1
+++ b/gnu/usr.bin/rcs/ci/ci.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: ci.1,v 5.9 1991/10/07 17:32:46 eggert Exp $
+.Id ci.1,v 1.1.1.1 1993/06/18 04:22:11 jkh Exp
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/ci/ci.c b/gnu/usr.bin/rcs/ci/ci.c
index 566747e139a9..4b6d7c118809 100644
--- a/gnu/usr.bin/rcs/ci/ci.c
+++ b/gnu/usr.bin/rcs/ci/ci.c
@@ -34,7 +34,10 @@ Report problems and direct all questions to:
-/* $Log: ci.c,v $
+/* ci.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:10 jkh
+ * Updated GNU utilities
+ *
* Revision 5.21 1991/11/20 17:58:07 eggert
* Don't read the delta tree from a nonexistent RCS file.
*
@@ -238,7 +241,7 @@ static struct hshentry newdelta; /* new delta to be inserted */
static struct stat workstat;
static struct Symrev *assoclst, *lastassoc;
-mainProg(ciId, "ci", "$Id: ci.c,v 5.21 1991/11/20 17:58:07 eggert Exp $")
+mainProg(ciId, "ci", "ci.c,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp")
{
static char const cmdusage[] =
"\nci usage: ci -{fklqru}[rev] -mmsg -{nN}name -sstate -t[textfile] -Vn file ...";
diff --git a/gnu/usr.bin/rcs/co/co.1 b/gnu/usr.bin/rcs/co/co.1
index 1fce152cf8f9..af0db7117194 100644
--- a/gnu/usr.bin/rcs/co/co.1
+++ b/gnu/usr.bin/rcs/co/co.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: co.1,v 1.1.1.1 1993/06/18 04:22:11 jkh Exp $
+.Id co.1,v 1.2 1994/05/14 07:00:09 rgrimes Exp
.ds g \&\s-1UTC\s0
.ds r \&\s-1RCS\s0
.if n .ds - \%--
diff --git a/gnu/usr.bin/rcs/co/co.c b/gnu/usr.bin/rcs/co/co.c
index 82f7cc82b9f8..8ee5c052905b 100644
--- a/gnu/usr.bin/rcs/co/co.c
+++ b/gnu/usr.bin/rcs/co/co.c
@@ -33,7 +33,12 @@ Report problems and direct all questions to:
*/
-/* $Log: co.c,v $
+/* co.c,v
+ * Revision 1.2 1994/05/14 07:00:10 rgrimes
+ * Add new option -K from David Dawes that allows you to turn on and off
+ * specific keyword substitution during a rcs co command.
+ * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id$.
+ *
* Revision 1.1.1.1 1993/06/18 04:22:11 jkh
* Updated GNU utilities
*
@@ -167,7 +172,7 @@ static struct hshentries *gendeltas; /* deltas to be generated */
static struct hshentry *targetdelta; /* final delta to be generated */
static struct stat workstat;
-mainProg(coId, "co", "$Id: co.c,v 1.1.1.1 1993/06/18 04:22:11 jkh Exp $")
+mainProg(coId, "co", "co.c,v 1.2 1994/05/14 07:00:10 rgrimes Exp")
{
static char const cmdusage[] =
"\nco usage: co -{flpqru}[rev] -ddate -jjoinlist -sstate -w[login] -Vn file ...";
diff --git a/gnu/usr.bin/rcs/doc/rcs.ms b/gnu/usr.bin/rcs/doc/rcs.ms
index 7b3f80772699..3828e24e6356 100644
--- a/gnu/usr.bin/rcs/doc/rcs.ms
+++ b/gnu/usr.bin/rcs/doc/rcs.ms
@@ -27,7 +27,7 @@
.de Id
.ND \\$4
..
-.Id $Id: rcs.ms,v 5.2 1991/01/03 10:57:28 eggert Exp $
+.Id rcs.ms,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp
.RP
.TL
RCS\*-A System for Version Control
diff --git a/gnu/usr.bin/rcs/ident/ident.1 b/gnu/usr.bin/rcs/ident/ident.1
index 37c8eda202a3..cd1a9f25a10f 100644
--- a/gnu/usr.bin/rcs/ident/ident.1
+++ b/gnu/usr.bin/rcs/ident/ident.1
@@ -3,7 +3,7 @@
.ds Dt \\$4
.ds iD \\$3 \\$4 \\$5 \\$6 \\$7
..
-.Id $Id: ident.1,v 5.0 1990/08/22 09:09:36 eggert Exp $
+.Id ident.1,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp
.ds r \s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/ident/ident.c b/gnu/usr.bin/rcs/ident/ident.c
index a2cc018da3ff..aeb5fbe1edef 100644
--- a/gnu/usr.bin/rcs/ident/ident.c
+++ b/gnu/usr.bin/rcs/ident/ident.c
@@ -28,7 +28,10 @@ Report problems and direct all questions to:
* RCS identification operation
*/
-/* $Log: ident.c,v $
+/* ident.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:11 jkh
+ * Updated GNU utilities
+ *
* 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.
@@ -83,7 +86,7 @@ Report problems and direct all questions to:
static int match P((FILE*));
static void scanfile P((FILE*,char const*,int));
-mainProg(identId, "ident", "$Id: ident.c,v 5.3 1991/09/10 22:15:46 eggert Exp $")
+mainProg(identId, "ident", "ident.c,v 1.1.1.1 1993/06/18 04:22:11 jkh Exp")
/* Ident searches the named files for all occurrences
* of the pattern $keyword:...$, where the keywords are
* Author, Date, Header, Id, Log, RCSfile, Revision, Source, and State.
diff --git a/gnu/usr.bin/rcs/lib/conf.h b/gnu/usr.bin/rcs/lib/conf.h
index b8f4abdc9962..a191d5954286 100644
--- a/gnu/usr.bin/rcs/lib/conf.h
+++ b/gnu/usr.bin/rcs/lib/conf.h
@@ -1,6 +1,6 @@
/* RCS compile-time configuration */
- /* $Id: conf.h,v 1.2 1994/08/05 22:33:44 wollman Exp $ */
+ /* conf.h,v 1.3 1994/08/09 15:15:04 jkh Exp */
/*
* This file is generated automatically.
diff --git a/gnu/usr.bin/rcs/lib/maketime.c b/gnu/usr.bin/rcs/lib/maketime.c
index c95c9f0b1e71..c9b3a9bf8fd0 100644
--- a/gnu/usr.bin/rcs/lib/maketime.c
+++ b/gnu/usr.bin/rcs/lib/maketime.c
@@ -20,7 +20,10 @@
* Copyright 1981 by Ken Harrenstien, SRI International.
* (ARPANET: KLH @ SRI)
*/
-/* $Log: maketime.c,v $
+/* maketime.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
+ * Updated GNU utilities
+ *
* Revision 5.3 1991/08/19 03:13:55 eggert
* Add setfiledate, str2time, TZ_must_be_set.
*
@@ -71,7 +74,7 @@
#include "rcsbase.h"
-libId(maketId, "$Id: maketime.c,v 5.3 1991/08/19 03:13:55 eggert Exp $")
+libId(maketId, "maketime.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
static struct tm const *time2tm P((time_t));
diff --git a/gnu/usr.bin/rcs/lib/merger.c b/gnu/usr.bin/rcs/lib/merger.c
index 7162ffa58eb7..4d5a7650c25c 100644
--- a/gnu/usr.bin/rcs/lib/merger.c
+++ b/gnu/usr.bin/rcs/lib/merger.c
@@ -27,7 +27,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(mergerId, "$Id: merger.c,v 1.3 1991/08/20 23:05:00 eggert Exp $")
+libId(mergerId, "merger.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
static char const *
normalize_arg(s, b)
diff --git a/gnu/usr.bin/rcs/lib/partime.c b/gnu/usr.bin/rcs/lib/partime.c
index 4751fc56d15a..c51287a41dff 100644
--- a/gnu/usr.bin/rcs/lib/partime.c
+++ b/gnu/usr.bin/rcs/lib/partime.c
@@ -20,7 +20,10 @@
* Perhaps should return 0 on success, else a non-zero error val?
*/
-/* $Log: partime.c,v $
+/* partime.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
+ * Updated GNU utilities
+ *
* Revision 5.6 1991/08/19 03:13:55 eggert
* Update timezones.
*
@@ -62,7 +65,7 @@
#include "rcsbase.h"
-libId(partId, "$Id: partime.c,v 5.6 1991/08/19 03:13:55 eggert Exp $")
+libId(partId, "partime.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
#define given(v) (0 <= (v))
#define TMNULL (-1) /* Items not given are given this value */
diff --git a/gnu/usr.bin/rcs/lib/rcsbase.h b/gnu/usr.bin/rcs/lib/rcsbase.h
index 17a123d11414..b3ee83e0a128 100644
--- a/gnu/usr.bin/rcs/lib/rcsbase.h
+++ b/gnu/usr.bin/rcs/lib/rcsbase.h
@@ -2,7 +2,7 @@
/*
* RCS common definitions and data structures
*/
-#define RCSBASE "$Id: rcsbase.h,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp $"
+#define RCSBASE "rcsbase.h,v 1.2 1994/05/14 07:00:20 rgrimes Exp"
/* Copyright (C) 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991 by Paul Eggert
@@ -42,7 +42,12 @@ Report problems and direct all questions to:
*/
-/* $Log: rcsbase.h,v $
+/* rcsbase.h,v
+ * Revision 1.2 1994/05/14 07:00:20 rgrimes
+ * Add new option -K from David Dawes that allows you to turn on and off
+ * specific keyword substitution during a rcs co command.
+ * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id$.
+ *
* Revision 1.1.1.1 1993/06/18 04:22:13 jkh
* Updated GNU utilities
*
diff --git a/gnu/usr.bin/rcs/lib/rcsedit.c b/gnu/usr.bin/rcs/lib/rcsedit.c
index 98e4c4b26728..e66eda3979e0 100644
--- a/gnu/usr.bin/rcs/lib/rcsedit.c
+++ b/gnu/usr.bin/rcs/lib/rcsedit.c
@@ -35,7 +35,12 @@ Report problems and direct all questions to:
*/
-/* $Log: rcsedit.c,v $
+/* rcsedit.c,v
+ * Revision 1.2 1994/05/14 07:00:22 rgrimes
+ * Add new option -K from David Dawes that allows you to turn on and off
+ * specific keyword substitution during a rcs co command.
+ * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id$.
+ *
* Revision 1.1.1.1 1993/06/18 04:22:12 jkh
* Updated GNU utilities
*
@@ -157,7 +162,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(editId, "$Id: rcsedit.c,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp $")
+libId(editId, "rcsedit.c,v 1.2 1994/05/14 07:00:22 rgrimes Exp")
static void keyreplace P((enum markers,struct hshentry const*,FILE*));
diff --git a/gnu/usr.bin/rcs/lib/rcsfcmp.c b/gnu/usr.bin/rcs/lib/rcsfcmp.c
index 75a6bbce1439..c2b2fb9730bd 100644
--- a/gnu/usr.bin/rcs/lib/rcsfcmp.c
+++ b/gnu/usr.bin/rcs/lib/rcsfcmp.c
@@ -37,7 +37,10 @@ Report problems and direct all questions to:
-/* $Log: rcsfcmp.c,v $
+/* rcsfcmp.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
+ * Updated GNU utilities
+ *
* Revision 5.9 1991/10/07 17:32:46 eggert
* Count log lines correctly.
*
@@ -101,7 +104,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(fcmpId, "$Id: rcsfcmp.c,v 5.9 1991/10/07 17:32:46 eggert Exp $")
+libId(fcmpId, "rcsfcmp.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
static int
discardkeyval(c, f)
diff --git a/gnu/usr.bin/rcs/lib/rcsfnms.c b/gnu/usr.bin/rcs/lib/rcsfnms.c
index 02562f08621f..375c2faff367 100644
--- a/gnu/usr.bin/rcs/lib/rcsfnms.c
+++ b/gnu/usr.bin/rcs/lib/rcsfnms.c
@@ -37,7 +37,10 @@ Report problems and direct all questions to:
-/* $Log: rcsfnms.c,v $
+/* rcsfnms.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
+ * Updated GNU utilities
+ *
* Revision 5.8 1991/09/24 00:28:40 eggert
* Don't export bindex().
*
@@ -140,7 +143,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(fnmsId, "$Id: rcsfnms.c,v 5.8 1991/09/24 00:28:40 eggert Exp $")
+libId(fnmsId, "rcsfnms.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
char const *RCSfilename;
char *workfilename;
diff --git a/gnu/usr.bin/rcs/lib/rcsgen.c b/gnu/usr.bin/rcs/lib/rcsgen.c
index 9a6072ea1b27..79bd4cebe52a 100644
--- a/gnu/usr.bin/rcs/lib/rcsgen.c
+++ b/gnu/usr.bin/rcs/lib/rcsgen.c
@@ -30,7 +30,10 @@ Report problems and direct all questions to:
-/* $Log: rcsgen.c,v $
+/* rcsgen.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:12 jkh
+ * Updated GNU utilities
+ *
* Revision 5.10 1991/10/07 17:32:46 eggert
* Fix log bugs, e.g. ci -t/dev/null when has_mmap.
*
@@ -122,7 +125,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(genId, "$Id: rcsgen.c,v 5.10 1991/10/07 17:32:46 eggert Exp $")
+libId(genId, "rcsgen.c,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp")
int interactiveflag; /* Should we act as if stdin is a tty? */
struct buf curlogbuf; /* buffer for current log message */
diff --git a/gnu/usr.bin/rcs/lib/rcskeep.c b/gnu/usr.bin/rcs/lib/rcskeep.c
index 1a0c78f25cf5..40ee458f40a8 100644
--- a/gnu/usr.bin/rcs/lib/rcskeep.c
+++ b/gnu/usr.bin/rcs/lib/rcskeep.c
@@ -35,7 +35,10 @@ Report problems and direct all questions to:
-/* $Log: rcskeep.c,v $
+/* rcskeep.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
+ * Updated GNU utilities
+ *
* Revision 5.4 1991/08/19 03:13:55 eggert
* Tune.
*
@@ -93,7 +96,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(keepId, "$Id: rcskeep.c,v 5.4 1991/08/19 03:13:55 eggert Exp $")
+libId(keepId, "rcskeep.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
static int checknum P((char const*,int));
static int getval P((RILE*,struct buf*,int));
diff --git a/gnu/usr.bin/rcs/lib/rcskeys.c b/gnu/usr.bin/rcs/lib/rcskeys.c
index cb8031451d4c..48d41c01e0ab 100644
--- a/gnu/usr.bin/rcs/lib/rcskeys.c
+++ b/gnu/usr.bin/rcs/lib/rcskeys.c
@@ -30,7 +30,11 @@ Report problems and direct all questions to:
-/* $Log: rcskeys.c,v $
+/* rcskeys.c,v
+ * Revision 1.4 1994/06/22 00:51:42 rgrimes
+ * Fix serious off by one error for FreeBSD keyword, this has been driving
+ * me nuts as it was on by default and that is NOT what I wanted.
+ *
* Revision 1.3 1994/05/15 22:15:14 rgrimes
* To truely have the OLD behavior of RCS by default make the expansion
* of $FreeBSD$ false by default. This should keep them out
@@ -39,7 +43,7 @@ Report problems and direct all questions to:
* Revision 1.2 1994/05/14 07:00:23 rgrimes
* Add new option -K from David Dawes that allows you to turn on and off
* specific keyword substitution during a rcs co command.
- * Add the new keyword FreeBSD that is IDENTICAL in operation to $Id: rcskeys.c,v 1.3 1994/05/15 22:15:14 rgrimes Exp $.
+ * Add the new keyword FreeBSD that is IDENTICAL in operation to rcskeys.c,v 1.4 1994/06/22 00:51:42 rgrimes Exp.
*
* Revision 1.1.1.1 1993/06/18 04:22:12 jkh
* Updated GNU utilities
@@ -73,7 +77,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(keysId, "$Id: rcskeys.c,v 1.3 1994/05/15 22:15:14 rgrimes Exp $")
+libId(keysId, "rcskeys.c,v 1.4 1994/06/22 00:51:42 rgrimes Exp")
char const *const Keyword[] = {
diff --git a/gnu/usr.bin/rcs/lib/rcslex.c b/gnu/usr.bin/rcs/lib/rcslex.c
index cedbc402f2b7..3e35fcb12144 100644
--- a/gnu/usr.bin/rcs/lib/rcslex.c
+++ b/gnu/usr.bin/rcs/lib/rcslex.c
@@ -38,7 +38,11 @@ Report problems and direct all questions to:
-/* $Log: rcslex.c,v $
+/* rcslex.c,v
+ * Revision 1.2 1993/06/28 19:13:10 nate
+ * Added Chris Demetriou's FSYNC_ALL option which causes all writes to be
+ * flushed immediately. (In case of a crash in the middle of CVS/RCS commits
+ *
* Revision 1.1.1.1 1993/06/18 04:22:12 jkh
* Updated GNU utilities
*
@@ -135,7 +139,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(lexId, "$Id: rcslex.c,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp $")
+libId(lexId, "rcslex.c,v 1.2 1993/06/28 19:13:10 nate Exp")
static struct hshentry *nexthsh; /*pointer to next hash entry, set by lookup*/
diff --git a/gnu/usr.bin/rcs/lib/rcsmap.c b/gnu/usr.bin/rcs/lib/rcsmap.c
index 0e7b23c85f4a..3d8a2f04be85 100644
--- a/gnu/usr.bin/rcs/lib/rcsmap.c
+++ b/gnu/usr.bin/rcs/lib/rcsmap.c
@@ -28,7 +28,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(mapId, "$Id: rcsmap.c,v 5.2 1991/08/19 03:13:55 eggert Exp $")
+libId(mapId, "rcsmap.c,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp")
/* map of character types */
/* ISO 8859/1 (Latin-1) */
diff --git a/gnu/usr.bin/rcs/lib/rcsrev.c b/gnu/usr.bin/rcs/lib/rcsrev.c
index ce11f549698d..5e130cc56b4b 100644
--- a/gnu/usr.bin/rcs/lib/rcsrev.c
+++ b/gnu/usr.bin/rcs/lib/rcsrev.c
@@ -31,7 +31,10 @@ Report problems and direct all questions to:
-/* $Log: rcsrev.c,v $
+/* rcsrev.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
+ * Updated GNU utilities
+ *
* Revision 5.3 1991/08/19 03:13:55 eggert
* Add `-r$', `-rB.'. Remove botches like `<now>' from messages. Tune.
*
@@ -94,7 +97,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(revId, "$Id: rcsrev.c,v 5.3 1991/08/19 03:13:55 eggert Exp $")
+libId(revId, "rcsrev.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
static char const *branchtip P((char const*));
static struct hshentry *genbranch P((struct hshentry const*,char const*,unsigned,char const*,char const*,char const*,struct hshentries**));
diff --git a/gnu/usr.bin/rcs/lib/rcssyn.c b/gnu/usr.bin/rcs/lib/rcssyn.c
index 31086c292f0f..b2df3e2983b7 100644
--- a/gnu/usr.bin/rcs/lib/rcssyn.c
+++ b/gnu/usr.bin/rcs/lib/rcssyn.c
@@ -36,7 +36,10 @@ Report problems and direct all questions to:
*/
-/* $Log: rcssyn.c,v $
+/* rcssyn.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:12 jkh
+ * Updated GNU utilities
+ *
* Revision 5.8 1991/08/19 03:13:55 eggert
* Tune.
*
@@ -133,7 +136,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(synId, "$Id: rcssyn.c,v 5.8 1991/08/19 03:13:55 eggert Exp $")
+libId(synId, "rcssyn.c,v 1.1.1.1 1993/06/18 04:22:12 jkh Exp")
/* forward */
static char const *getkeyval P((char const*,enum tokens,int));
diff --git a/gnu/usr.bin/rcs/lib/rcsutil.c b/gnu/usr.bin/rcs/lib/rcsutil.c
index c523ccf1df84..ce82726b6784 100644
--- a/gnu/usr.bin/rcs/lib/rcsutil.c
+++ b/gnu/usr.bin/rcs/lib/rcsutil.c
@@ -31,7 +31,10 @@ Report problems and direct all questions to:
-/* $Log: rcsutil.c,v $
+/* rcsutil.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:13 jkh
+ * Updated GNU utilities
+ *
* Revision 5.10 1991/10/07 17:32:46 eggert
* Support piece tables even if !has_mmap.
*
@@ -136,7 +139,7 @@ Report problems and direct all questions to:
#include "rcsbase.h"
-libId(utilId, "$Id: rcsutil.c,v 5.10 1991/10/07 17:32:46 eggert Exp $")
+libId(utilId, "rcsutil.c,v 1.1.1.1 1993/06/18 04:22:13 jkh Exp")
#if !has_memcmp
int
diff --git a/gnu/usr.bin/rcs/merge/merge.1 b/gnu/usr.bin/rcs/merge/merge.1
index 8b1957fca099..bb909e9f53cb 100644
--- a/gnu/usr.bin/rcs/merge/merge.1
+++ b/gnu/usr.bin/rcs/merge/merge.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: merge.1,v 5.3 1991/02/28 19:18:45 eggert Exp $
+.Id merge.1,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp
.TH MERGE 1 \*(Dt GNU
.SH NAME
merge \- three-way file merge
diff --git a/gnu/usr.bin/rcs/merge/merge.c b/gnu/usr.bin/rcs/merge/merge.c
index 4067c184a255..82faf126502c 100644
--- a/gnu/usr.bin/rcs/merge/merge.c
+++ b/gnu/usr.bin/rcs/merge/merge.c
@@ -39,7 +39,7 @@ badoption(a)
}
-mainProg(mergeId, "merge", "$Id: merge.c,v 1.2 1991/08/19 03:13:55 eggert Exp $")
+mainProg(mergeId, "merge", "merge.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp")
{
register char const *a;
char const *label[2], *arg[3];
diff --git a/gnu/usr.bin/rcs/rcs/rcs.1 b/gnu/usr.bin/rcs/rcs/rcs.1
index 9866a9c0054f..14f4f2578331 100644
--- a/gnu/usr.bin/rcs/rcs/rcs.1
+++ b/gnu/usr.bin/rcs/rcs/rcs.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rcs.1,v 5.6 1991/09/26 23:16:17 eggert Exp $
+.Id rcs.1,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/rcs/rcs.c b/gnu/usr.bin/rcs/rcs/rcs.c
index 70e7ffc5a8ee..e64b9a387005 100644
--- a/gnu/usr.bin/rcs/rcs/rcs.c
+++ b/gnu/usr.bin/rcs/rcs/rcs.c
@@ -30,7 +30,10 @@ Report problems and direct all questions to:
-/* $Log: rcs.c,v $
+/* rcs.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:14 jkh
+ * Updated GNU utilities
+ *
* Revision 5.12 1991/11/20 17:58:08 eggert
* Don't read the delta tree from a nonexistent RCS file.
*
@@ -238,7 +241,7 @@ static struct delrevpair delrev;
static struct hshentry *cuthead, *cuttail, *delstrt;
static struct hshentries *gendeltas;
-mainProg(rcsId, "rcs", "$Id: rcs.c,v 5.12 1991/11/20 17:58:08 eggert Exp $")
+mainProg(rcsId, "rcs", "rcs.c,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp")
{
static char const cmdusage[] =
"\nrcs usage: rcs -{ae}logins -Afile -{blu}[rev] -cstring -{iLU} -{nNs}name[:rev] -orange -t[file] -Vn file ...";
diff --git a/gnu/usr.bin/rcs/rcs/rcsfile.5 b/gnu/usr.bin/rcs/rcs/rcsfile.5
index d0dbbb80cbbb..88124ca8a8d6 100644
--- a/gnu/usr.bin/rcs/rcs/rcsfile.5
+++ b/gnu/usr.bin/rcs/rcs/rcsfile.5
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rcsfile.5,v 5.1 1991/08/19 03:13:55 eggert Exp $
+.Id rcsfile.5,v 1.1.1.1 1993/06/18 04:22:15 jkh Exp
.ds r \s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/rcs/rcsintro.1 b/gnu/usr.bin/rcs/rcs/rcsintro.1
index a76caa0ee2d9..6d15326ea516 100644
--- a/gnu/usr.bin/rcs/rcs/rcsintro.1
+++ b/gnu/usr.bin/rcs/rcs/rcsintro.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rcsintro.1,v 5.1 1991/04/21 12:00:46 eggert Exp $
+.Id rcsintro.1,v 1.1.1.1 1993/06/18 04:22:14 jkh Exp
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/rcsclean/rcsclean.1 b/gnu/usr.bin/rcs/rcsclean/rcsclean.1
index 07ed7228b679..973ba2e08b84 100644
--- a/gnu/usr.bin/rcs/rcsclean/rcsclean.1
+++ b/gnu/usr.bin/rcs/rcsclean/rcsclean.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rcsclean.1,v 1.8 1991/11/03 01:09:19 eggert Exp $
+.Id rcsclean.1,v 1.1.1.1 1993/06/18 04:22:15 jkh Exp
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/rcsclean/rcsclean.c b/gnu/usr.bin/rcs/rcsclean/rcsclean.c
index ba24ab77e0b3..5ad53d411444 100644
--- a/gnu/usr.bin/rcs/rcsclean/rcsclean.c
+++ b/gnu/usr.bin/rcs/rcsclean/rcsclean.c
@@ -37,7 +37,7 @@ static void cleanup P((void));
static RILE *workptr;
static int exitstatus;
-mainProg(rcscleanId, "rcsclean", "$Id: rcsclean.c,v 5.1 1991/11/03 01:11:44 eggert Exp $")
+mainProg(rcscleanId, "rcsclean", "rcsclean.c,v 1.1.1.1 1993/06/18 04:22:15 jkh Exp")
{
static char const usage[] =
"\nrcsclean: usage: rcsclean [-ksubst] [-{nqru}[rev]] [-Vn] [-xsuffixes] [file ...]";
diff --git a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.1 b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.1
index b78bbdd17c1f..e171e8eb1c26 100644
--- a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.1
+++ b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rcsdiff.1,v 5.3 1991/04/21 12:00:46 eggert Exp $
+.Id rcsdiff.1,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
index 7155c8d89b8c..c8f287545374 100644
--- a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
+++ b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
@@ -35,7 +35,10 @@ Report problems and direct all questions to:
-/* $Log: rcsdiff.c,v $
+/* rcsdiff.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:16 jkh
+ * Updated GNU utilities
+ *
* Revision 5.10 1991/10/07 17:32:46 eggert
* Remove lint.
*
@@ -129,7 +132,7 @@ static int exitstatus;
static RILE *workptr;
static struct stat workstat;
-mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 5.10 1991/10/07 17:32:46 eggert Exp $")
+mainProg(rcsdiffId, "rcsdiff", "rcsdiff.c,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp")
{
static char const cmdusage[] =
"\nrcsdiff usage: rcsdiff [-q] [-rrev1 [-rrev2]] [-Vn] [diff options] file ...";
diff --git a/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.1 b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.1
index be669a9f2a0d..7b411a112a6f 100644
--- a/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.1
+++ b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rcsfreeze.1,v 4.4 1990/11/13 15:43:42 hammer Exp $
+.Id rcsfreeze.1,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp
.ds r \s-1RCS\s0
.TH RCSFREEZE 1 \*(Dt GNU
.SH NAME
diff --git a/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh
index 421997946b76..63c314bf1711 100644
--- a/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh
+++ b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh
@@ -2,7 +2,7 @@
# rcsfreeze - assign a symbolic revision number to a configuration of RCS files
-# $Id: rcsfreeze.sh,v 4.4 1991/04/21 11:58:24 eggert Exp $
+# rcsfreeze.sh,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp
# The idea is to run rcsfreeze each time a new version is checked
# in. A unique symbolic revision number (C_[number], where number
diff --git a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.1 b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.1
index 82871b033bfd..0d819e01dd56 100644
--- a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.1
+++ b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rcsmerge.1,v 5.3 1991/08/19 03:13:55 eggert Exp $
+.Id rcsmerge.1,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
diff --git a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
index e5d439452789..72d4130e3b52 100644
--- a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
+++ b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
@@ -34,7 +34,10 @@ Report problems and direct all questions to:
-/* $Log: rcsmerge.c,v $
+/* rcsmerge.c,v
+ * Revision 1.1.1.1 1993/06/18 04:22:16 jkh
+ * Updated GNU utilities
+ *
* Revision 5.7 1991/11/20 17:58:09 eggert
* Don't Iopen(f, "r+"); it's not portable.
*
@@ -98,7 +101,7 @@ Report problems and direct all questions to:
static char const co[] = CO;
-mainProg(rcsmergeId, "rcsmerge", "$Id: rcsmerge.c,v 5.7 1991/11/20 17:58:09 eggert Exp $")
+mainProg(rcsmergeId, "rcsmerge", "rcsmerge.c,v 1.1.1.1 1993/06/18 04:22:16 jkh Exp")
{
static char const cmdusage[] =
"\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] [-p] [-Vn] file";
diff --git a/gnu/usr.bin/rcs/rcstest b/gnu/usr.bin/rcs/rcstest
index e0b6c828f7c5..f8f0c41e2ce3 100755..100644
--- a/gnu/usr.bin/rcs/rcstest
+++ b/gnu/usr.bin/rcs/rcstest
@@ -15,7 +15,7 @@
# The current directory and ./RCS must be readable, writable, and searchable.
-# $Id: rcstest,v 5.8 1991/11/20 17:58:10 eggert Exp $
+# rcstest,v 1.1.1.1 1993/06/18 04:22:10 jkh Exp
# Copyright 1990, 1991 by Paul Eggert
diff --git a/gnu/usr.bin/rcs/rlog/rlog.1 b/gnu/usr.bin/rcs/rlog/rlog.1
index e3deb6871ee9..2b231af693d7 100644
--- a/gnu/usr.bin/rcs/rlog/rlog.1
+++ b/gnu/usr.bin/rcs/rlog/rlog.1
@@ -2,7 +2,7 @@
.ds Rv \\$3
.ds Dt \\$4
..
-.Id $Id: rlog.1,v 1.2 1994/05/11 22:39:43 phk Exp $
+.Id rlog.1,v 1.3 1994/05/12 00:37:57 phk Exp
.ds g \&\s-1UTC\s0
.ds r \&\s-1RCS\s0
.if n .ds - \%--
diff --git a/gnu/usr.bin/rcs/rlog/rlog.c b/gnu/usr.bin/rcs/rlog/rlog.c
index bf59e66ac3a3..6cfcb9ae17c5 100644
--- a/gnu/usr.bin/rcs/rlog/rlog.c
+++ b/gnu/usr.bin/rcs/rlog/rlog.c
@@ -35,7 +35,10 @@ Report problems and direct all questions to:
-/* $Log: rlog.c,v $
+/* rlog.c,v
+ * Revision 1.5 1994/05/12 00:42:59 phk
+ * typo.
+ *
* Revision 1.4 1994/05/12 00:37:59 phk
* made -v produce tip-revision, which was what I wanted in the first place...
*
@@ -204,7 +207,7 @@ static struct lockers *lockerlist;
static struct stateattri *statelist;
-mainProg(rlogId, "rlog", "$Id: rlog.c,v 1.4 1994/05/12 00:37:59 phk Exp $")
+mainProg(rlogId, "rlog", "rlog.c,v 1.5 1994/05/12 00:42:59 phk Exp")
{
static char const cmdusage[] =
"\nrlog usage: rlog -{bhLRt} [-v[string]] -ddates -l[lockers] -rrevs -sstates -w[logins] -Vn file ...";
diff --git a/gnu/usr.bin/tar/getdate.y b/gnu/usr.bin/tar/getdate.y
index aa8f6b512a33..59fbdd1728a1 100644
--- a/gnu/usr.bin/tar/getdate.y
+++ b/gnu/usr.bin/tar/getdate.y
@@ -1,5 +1,5 @@
%{
-/* $Revision: 1.1.1.1 $
+/* 1.2
**
** Originally written by Steven M. Bellovin <smb@research.att.com> while
** at the University of North Carolina at Chapel Hill. Later tweaked by
@@ -98,7 +98,7 @@ extern struct tm *localtime();
#if !defined(lint) && !defined(SABER)
static char RCS[] =
- "$Header: /home/ncvs/src/gnu/usr.bin/tar/getdate.y,v 1.1.1.1 1993/06/18 04:22:21 jkh Exp $";
+ "/home/ncvs/src/gnu/usr.bin/tar/getdate.y,v 1.2 1994/11/04 02:12:22 jkh Exp";
#endif /* !defined(lint) && !defined(SABER) */
diff --git a/gnu/usr.bin/texinfo/Makefile b/gnu/usr.bin/texinfo/Makefile
index d8c51ed4a6a5..a5eae793b00f 100644
--- a/gnu/usr.bin/texinfo/Makefile
+++ b/gnu/usr.bin/texinfo/Makefile
@@ -1,6 +1,6 @@
#
# Bmake file for texinfo
-# $Id$
+# Makefile,v 1.2 1994/09/15 12:09:35 jkh Exp
#
SUBDIR= info info-files makedoc makeinfo texindex
diff --git a/gnu/usr.bin/texinfo/Makefile.inc b/gnu/usr.bin/texinfo/Makefile.inc
index 9b2886022b7e..6eb36a3f1e4d 100644
--- a/gnu/usr.bin/texinfo/Makefile.inc
+++ b/gnu/usr.bin/texinfo/Makefile.inc
@@ -1,5 +1,5 @@
# Texinfo defaults.
-# $Id$
+# Makefile.inc,v 1.2 1994/09/15 12:09:36 jkh Exp
INFODIR?= /usr/share/info
diff --git a/gnu/usr.bin/texinfo/info-files/texi-files/texinfo.tex b/gnu/usr.bin/texinfo/info-files/texi-files/texinfo.tex
new file mode 100644
index 000000000000..ce8124ecb7bd
--- /dev/null
+++ b/gnu/usr.bin/texinfo/info-files/texi-files/texinfo.tex
@@ -0,0 +1,4003 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc.
+
+%This texinfo.tex 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 texinfo.tex 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 texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+\def\texinfoversion{2.108}
+\message{Loading texinfo package [Version \texinfoversion]:}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ } % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }}
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+% Why was this kern here? It messes up equalizing space above and below
+% environments. --karl, 6may93
+%{\advance \baselineskip by -\singlespaceskip
+%\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % We do @comment here in case we are called inside an environment,
+ % such as @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+%Use \input\thisfile to avoid blank after \input, which may be an active
+%char (in which case the blank would become the \input argument).
+%The grouping keeps the value of \thisfile correct even when @include
+%is nested.
+\def\includezzz #1{\begingroup
+\def\thisfile{#1}\input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ \long\def\doignoretext##1\end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+%
+\def\set{\parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+}
+\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+ \ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}
+ \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex). But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\font\textrm=cmr12
+\font\texttt=cmtt12
+\else
+\font\textrm=cmr10 scaled \mainmagstep
+\font\texttt=cmtt10 scaled \mainmagstep
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\textbf=cmb10 scaled \mainmagstep
+\font\textit=cmti10 scaled \mainmagstep
+\font\textsl=cmsl10 scaled \mainmagstep
+\font\textsf=cmss10 scaled \mainmagstep
+\font\textsc=cmcsc10 scaled \mainmagstep
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\font\ninett=cmtt9
+\font\indrm=cmr9
+\font\indit=cmsl9
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\let\indsc=\indrm
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+\font\chapsc=cmcsc10 scaled\magstep3
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+\font\secsc=cmcsc10 scaled\magstep2
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad.
+% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+\font\ssecsc=cmcsc10 scaled \magstep1
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current. Plain TeX does, for example,
+% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need
+% to redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+ \resetmathfonts}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+ \resetmathfonts}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+ \resetmathfonts}
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
+ \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\font\shortcontrm=cmr12
+\font\shortcontbf=cmbx12
+\font\shortcontsl=cmsl12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \nohyphenation \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overful hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate an a dash.
+% -- rms.
+{
+\catcode `\-=\active
+\catcode `\_=\active
+\global\def\code{\begingroup \catcode `\-=\active \let-\codedash \let_\codeunder \codex}
+}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ {\parskip = 0in
+ \par
+ }%
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}%
+ \fi
+ \endgroup
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\def\doind #1#2{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+ \tex
+ \dobreak \chapheadingskip {10000}
+ \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+ \catcode`\$=\other\catcode`\_=\other
+ \catcode`\~=\other
+ %
+ % The following don't help, since the chars were translated
+ % when the raw index was written, and their fonts were discarded
+ % due to \indexnofonts.
+ %\catcode`\"=\active
+ %\catcode`\^=\active
+ %\catcode`\_=\active
+ %\catcode`\|=\active
+ %\catcode`\<=\active
+ %\catcode`\>=\active
+ % %
+ \def\indexbackslash{\rawbackslashxx}
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+ \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent=2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXbook, page 416.
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage
+ =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \eject
+ %
+ % Now switch to the double-column output routine.
+ \output={\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it once.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +- <
+ % 1pt) as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+ \doublecolumnpagegoal
+}
+
+\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
+
+\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
+ \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
+ \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
+ \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+ \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+}
+\def\doublecolumnpagegoal{%
+ \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\doublecolumnout{%
+ \setbox5=\copy255
+ {\vbadness=10000 \doublecolumnsplit}
+ \ifvbox255
+ \setbox0=\vtop to\dimen@{\unvbox0}
+ \setbox2=\vtop to\dimen@{\unvbox2}
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
+ \else
+ \setbox0=\vbox{\unvbox5}
+ \ifvbox0
+ \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ {\vbadness=10000
+ \loop \global\setbox5=\copy0
+ \setbox1=\vsplit5 to\dimen@
+ \setbox3=\vsplit5 to\dimen@
+ \ifvbox5 \global\advance\dimen@ by1pt \repeat
+ \setbox0=\vbox to\dimen@{\unvbox1}
+ \setbox2=\vbox to\dimen@{\unvbox3}
+ \global\setbox\partialpage=\vbox{\pagesofar}
+ \doublecolumnpagegoal
+ }
+ \fi
+ \fi
+}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appenixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #2\enspace #1}%
+ }%
+ \bigskip
+ \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \ifnum \pageno>0
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{Table of Contents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{Short Contents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm Appendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in in \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+\def\tocentry#1#2{\begingroup
+ \hyphenpenalty = 10000
+ \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces %
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% To ending an @example-like environment, we first end the paragraph
+% (via \afterenvbreak's vertical glue), and then the group. That way we
+% keep the zero \parskip that the environments set -- \parskip glue
+% will be inserted at the beginning of the next paragraph in the
+% document, after the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}%
+
+% This macro is
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \rawbackslash % have \ input char produce \ char from current font
+ \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp. This is not used unless the @smallbook
+% command is given. Originally contributed by Pavel@xerox.
+%
+\def\smalllispx{\begingroup
+ \nonfillstart
+ \let\Esmalllisp = \nonfillfinish
+ \let\Esmallexample = \nonfillfinish
+ %
+ % Smaller interline space and fonts for small examples.
+ \baselineskip 10pt
+ \indexfonts \tt
+ \rawbackslash % output the \ character from the current font
+ \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushleft = \nonfillfinish
+ \gobble
+}
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble}
+
+% @quotation does normal linebreaking and narrows the margins.
+%
+\def\quotation{%
+\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\let\Equotation = \nonfillfinish
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\advance \rightskip by \lispnarrowing
+\exdentamount=\lispnarrowing
+\let\nonarrowing=\relax
+\fi}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+\def\defvrparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#4}}}
+
+% This seems to work right in all cases.
+\let\deftpparsebody=\defvrparsebody
+% This fails to work. When given `@deftp {Data Type} foo_t',
+% it thinks the type name is just `f'.
+%%% This is the same as all the others except for the last line. We need
+%%% to parse the arguments differently for @deftp, since the ``attributes''
+%%% there are optional.
+%%%
+%%\def\deftpparsebody #1#2#3#4 {\begingroup\inENV %
+%%\medbreak %
+%%% Define the end token that this defining construct specifies
+%%% so that it will exit this group.
+%%\def#1{\endgraf\endgroup\medbreak}%
+%%\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+%%\parindent=0in
+%%\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+%%\exdentamount=\defbodyindent
+%%\begingroup\obeylines\parsetpheaderline{#3{#4}}}
+
+%%{\obeylines %
+%% % Parse the type name and any attributes (field names, etc.).
+%% % #1 is the beginning of the macro call that will produce the output,
+%% % i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody.
+%% % #2 is the type name, e.g., `struct termios'.
+%% % #3 is the (possibly empty) attribute list.
+%% %
+%% \gdef\parsetpheaderline#1#2#3^^M{%
+%% \endgroup % Started in \deftpparsebody.
+%% %
+%% % If the attribute list is in fact empty, there will be no space after
+%% % #2; so we can't put a space in our TeX parameter list. But if it
+%% % isn't empty, then #3 will begin with an unwanted space.
+%% \def\theargs{\ignorespaces #3}%
+%% %
+%% % Call the macro to produce the output.
+%% #1{#2}\theargs %
+%% }%
+%%}
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names. Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss. Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed.
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\setleading{15pt}
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+\else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+
+% These values for secheadingskip and subsecheadingskip are
+% experiments. RJC 7 Aug 1992
+\global\secheadingskip = 17pt plus 6pt minus 3pt
+\global\subsecheadingskip = 14pt plus 6pt minus 3pt
+
+\global\lispnarrowing = 0.3in
+\setleading{12pt}
+\advance\topskip by -1cm
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+% \lvvmode is equivalent in function to \leavevmode.
+% Using \leavevmode runs into trouble when written out to
+% an index file due to the expansion of \leavevmode into ``\unhbox
+% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
+% magic tricks with @.
+\def\lvvmode{\vbox to 0pt{}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/gnu/usr.bin/texinfo/makedoc/Makefile b/gnu/usr.bin/texinfo/makedoc/Makefile
index 930e4abdff3e..25f7469622a5 100644
--- a/gnu/usr.bin/texinfo/makedoc/Makefile
+++ b/gnu/usr.bin/texinfo/makedoc/Makefile
@@ -1,7 +1,7 @@
#
# Bmakefile for GNU info
#
-# $Id$
+# Makefile,v 1.2 1994/09/15 13:10:41 jkh Exp
#
PROG= makedoc
diff --git a/gnu/usr.bin/texinfo/makeinfo/Makefile b/gnu/usr.bin/texinfo/makeinfo/Makefile
index 26fbbea84963..f3799afc5947 100644
--- a/gnu/usr.bin/texinfo/makeinfo/Makefile
+++ b/gnu/usr.bin/texinfo/makeinfo/Makefile
@@ -1,7 +1,7 @@
#
# Bmakefile for GNU info
#
-# $Id$
+# Makefile,v 1.2 1994/09/15 13:11:36 jkh Exp
#
PROG= makeinfo
diff --git a/gnu/usr.bin/texinfo/misc/texindex b/gnu/usr.bin/texinfo/misc/texindex
new file mode 100755
index 000000000000..7ec39200bf9b
--- /dev/null
+++ b/gnu/usr.bin/texinfo/misc/texindex
Binary files differ
diff --git a/gnu/usr.bin/texinfo/texindex/Makefile b/gnu/usr.bin/texinfo/texindex/Makefile
index 94320b5d6e5b..8b06483eb903 100644
--- a/gnu/usr.bin/texinfo/texindex/Makefile
+++ b/gnu/usr.bin/texinfo/texindex/Makefile
@@ -1,7 +1,7 @@
#
# Bmakefile for GNU info
#
-# $Id$
+# Makefile,v 1.2 1994/09/15 13:12:23 jkh Exp
#
PROG= texindex